diff --git a/lib/models/radkfile/radicals_search_result.dart b/lib/models/radkfile/radicals_search_result.dart deleted file mode 100644 index 4f9d346..0000000 --- a/lib/models/radkfile/radicals_search_result.dart +++ /dev/null @@ -1,3 +0,0 @@ -class RadicalsSearchResult { - // TODO: implement me -} diff --git a/lib/search.dart b/lib/search.dart index 5d4490f..aa8c2ae 100644 --- a/lib/search.dart +++ b/lib/search.dart @@ -1,6 +1,6 @@ import 'package:jadb/models/word_search/word_search_result.dart'; import 'package:jadb/models/kanji_search/kanji_search_result.dart'; -import 'package:jadb/models/radkfile/radicals_search_result.dart'; +import 'package:jadb/search/radical_search.dart'; import 'package:jadb/search/word_search/word_search.dart'; import 'package:jadb/search/kanji_search.dart'; @@ -15,15 +15,15 @@ class JaDBConnection { Future searchKanji(String kanji) => searchKanjiWithDbConnection(this._connection, kanji); - Future searchKanjiByRadicals( - List radicals, - ) async { - throw UnimplementedError(); - } - Future?> searchWord(String word) => searchWordWithDbConnection(this._connection, word); Future searchWordCount(String word) => searchWordCountWithDbConnection(this._connection, word); + + Future> searchRemainingRadicals(List radicals) => + searchRemainingRadicalsWithDbConnection(this._connection, radicals); + + Future> searchKanjiByRadicals(List radicals) => + searchKanjiByRadicalsWithDbConnection(this._connection, radicals); } diff --git a/lib/search/radical_search.dart b/lib/search/radical_search.dart new file mode 100644 index 0000000..3a28a4a --- /dev/null +++ b/lib/search/radical_search.dart @@ -0,0 +1,60 @@ +import 'package:sqflite_common/sqlite_api.dart'; + +// TODO: validate that the list of radicals all are valid radicals + +/// Given a list of radicals, search which kanji contains all +/// of the radicals, find their other radicals, and return those. +/// This is used to figure out which remaining combinations of radicals +/// the user can search for without getting zero results. +Future> searchRemainingRadicalsWithDbConnection( + DatabaseExecutor connection, + List radicals, +) async { + final queryResult = await connection.rawQuery( + ''' + SELECT DISTINCT radical + FROM RADKFILE + WHERE kanji IN ( + SELECT kanji + FROM RADKFILE + WHERE radical IN (${List.filled(radicals.length, '?').join(',')}) + GROUP BY kanji + HAVING COUNT(DISTINCT radical) = ? + ) + ''', + [ + ...radicals, + radicals.length, + ], + ); + + final remainingRadicals = + queryResult.map((row) => row['radical'] as String).toList(); + + return remainingRadicals; +} + +/// Given a list of radicals, search which kanji contains all +/// of the radicals, and return those. +Future> searchKanjiByRadicalsWithDbConnection( + DatabaseExecutor connection, + List radicals, +) async { + final queryResult = await connection.rawQuery( + ''' + SELECT kanji + FROM RADKFILE + WHERE radical IN (${List.filled(radicals.length, '?').join(',')}) + GROUP BY kanji + HAVING COUNT(DISTINCT radical) = ? + ''', + [ + ...radicals, + radicals.length, + ], + ); + + final kanji = queryResult.map((row) => row['kanji'] as String).toList(); + + return kanji; +}