辞書を片手に~PatternResponderの作成(13) | Pythonでなんか作ってみる

辞書を片手に~PatternResponderの作成(13)

さすがにそろそろラストスパートである。


ToDoリスト

・正規表現を使ってパターンに反応するResponder(以下の仕様を満たす)

・応答例の中に「%match%」という文字列があれば、パターンにマッチした文字列と置き換えられる

・Dictionaryでコンストラクタで動作を分けているのは美しくない


さて、リファクタリングもひと段落ついたと見なして、最後の機能追加である。まずは、テスト。


PatternResponderTest

public void testMatch() throws FileNotFoundException {
PatternResponder resp = new PatternResponder("pattern", new Dictionary(
new FileReader("dics/pattern.txt")));

assertEquals("カステラは太るよ", resp.response("カステラたべたい"));
assertEquals("甘いものは太るよ", resp.response("甘いものたべたい"));
}
 


「甘いもの」や「カステラ」に反応させて「~は太るよ」と反応させたいわけだ。

テスト実行。当然、Red。


じゃあ、実装だ。

まずは、pattern.txtを仕様にしたがって変更する。以下の定義を追加する。


カステラ|甘いもの[→] %match%は太るよ


テスト実行。やっぱりRedだが、結果はさっきと異なっている。

「カステラ」の定義が追加されているので「%match%は太るよ」と反応している。

この「%match%」の部分をパターンに一致した部分で置換するわけだが?

とりあえずドキュメントをみて正規表現クラスが使えそうだと分かった。


PatternResponderのresponse()を修正する。修正したのは以下の下線部分である。


PatternResponder

public String response(String msg) {
for (int index=0;index < patterns.length; index++) {
Matcher m = patterns[index].matcher(msg);
if (m.find()) {
String resp = responses[index].response(msg);
Pattern p = Pattern.compile("%match%");
Matcher m2 = p.matcher(resp);

if (!m2.find()) {
return resp;
} else {
return m2.replaceFirst(msg);
}

}
}
return randomResponder.response(msg);
}

パターンに一致した部分だけってのが良く分からなかったので、まずは、入力された文字列で置換した。

テスト実行。当然Redだが、応答は「カステラたべたいは太るよ」である。一歩前進した。


もう一度ドキュメントを探索。どうやらMatcherクラスの 以下のメソッドで一致した部分が入手できるようだ。


string group () 前回のマッチで一致した入力部分シーケンスを返します。


PatternResponder

public String response(String msg) {
for (int index=0;index < patterns.length; index++) {
Matcher m = patterns[index].matcher(msg);
if (m.find()) {
String resp = responses[index].response(msg);
Pattern p = Pattern.compile("%match%");
Matcher m2 = p.matcher(resp);

if (!m2.find()) {
return resp;
} else {
return m2.replaceFirst(m.group());
}
}
}
return randomResponder.response(msg);
}

テスト実行。今度こそGreenである。


さて、残ったToDoであるが、「Dictionaryでコンストラクタで動作を分けているのは美しくない」であるが、これを解決するためにポリモーフィズムでクラスを分割するのも大げさな気がする。

また、検索の結果、 public Dictionary(Reader reader)はテストからしか呼ばれず、しかも全て public Dictionary(String fileName)で置き換えることが可能である。

後々後悔するかもしれないが、 Dictionary(Reader reader)を削除して呼び出し元をDictionary(String fileName)で置き換えることにする。


テスト実行。OK。Greenだ。


Dictionaryのソースを眺めても、これ以上良い案が思い浮かばないので、Closeする。


ToDoリスト

・正規表現を使ってパターンに反応するResponder(以下の仕様を満たす)

・応答例の中に「%match%」という文字列があれば、パターンにマッチした文字列と置き換えられる

・Dictionaryでコンストラクタで動作を分けているのは美しくない



とにかく、これで本章は終了である。