辞書を片手に~PatternResponderの作成(4)
失敗するテストが無ければ実装を進めれないので変更する。
public void testLoadDictionaryResponse() throws FileNotFoundException {
assertEquals(new String[]{"さむくないよ","食べれば","いいね"},
PatternResponder
.loadDictionaryResponse(new FileReader("dics/pattern.txt")));
}
random.txtからコピーしてpattern.txtも作成した。[→]はタブである。
今日はさむいね[→]さむくないよ
チョコたべたい[→]食べれば
きのう10円ひろった[→]いいね
テストを実行。予定通り失敗。
さて、どう実装しようか?仮実装を進めても意味が無い気がするので、既存処理を用いた安易な実装を試みる。
今のデータをRandomResponder.loadDictionary()で読み込めば、タブと応答例も含めた文字列の配列になるはず。
それを切り取れば良いんじゃないだろうか。
public static String[] loadDictionaryResponse(FileReader reader) {
String[] patternStrings = RandomResponder.loadDictionary(reader);
String[] responses = new String[patternStrings.length];
for (int index=0;index < responses.length; index++) {
responses[index] = patternStrings[index].split("\t")[1];
}
return responses;
}
あえて、タブが無いときなどは考慮にいれていない。それはToDoに追加しておこう。
テスト実行。Green。あっさり動いたな。loadDictionary()の方も、pattern.txtからの読み込みに変えてみる。
public void testLoadDictionary() throws FileNotFoundException {
assertEquals(new Pattern[] { Pattern.compile("今日はさむいね"),
Pattern.compile("チョコたべたい"), Pattern.compile("きのう10円ひろった") },
PatternResponder
.loadDictionary(new FileReader("dics/pattern.txt")));
}
テスト実行。当然失敗である。応答例まで含んでいるからだ。パターンを作るときに、タブより前の部分のみ使うようにする。
public static Pattern[] loadDictionary(FileReader reader) {
String[] patternStrings = RandomResponder.loadDictionary(reader);
Pattern[] patterns = new Pattern[patternStrings.length];
for (int index=0;index < patterns.length; index++) {
patterns[index] = Pattern.compile(patternStrings[index].split("\t")[0]);
}
return patterns;
}
テスト実行。Green。一応、これで応答例の配列は入手できるようになった。
loadDictionary()とloadDictionaryResponse()の類似性も気になるところで、リファクタリング対象に持って来いだろう。
ToDoリスト
・正規表現を使ってパターンに反応するResponder(以下の仕様を満たす)
・パターン辞書の先頭行からパターンマッチを行い、マッチした行の応答例をもとに応答メッセージを作る
・1つのパターンに対して応答例は「|」で区切って複数設定でき、いずれかがランダムに選択される
・マッチするパターンがなかったときは、ランダム辞書からランダムに選択した応答を返す
・応答例の中に「%match」という文字列があれば、パターンにマッチした文字列と置き換えられる
・パターン辞書から応答例のグループを作る
・パターンオブジェクトのグループに対して順番に入力文字列がマッチするか確認し、対応する応答例を求める
・PatternResponderがRandomResponderの機能を利用している(メソッドの上位クラスへの移動に関するリファクタリングが出来そうである)
・パターン辞書に応答例が無い場合のイリーガルケース
・loadDictionary()とloadDictionaryResponse()の重複処理の解消