diff --git a/lib/const_data/radicals.dart b/lib/const_data/radicals.dart index 21937cc..003928f 100644 --- a/lib/const_data/radicals.dart +++ b/lib/const_data/radicals.dart @@ -1,3 +1,5 @@ +import 'package:collection/collection.dart'; + class RadkfileRadical { /// The formal variant of the radical /// @@ -302,3 +304,7 @@ const Map> radicals = { ], 17: [RadkfileRadical(formalVariant: '龠', strokeCount: 17)], }; + +final Map radicalsByFormalVariant = { + for (final r in radicals.values.flattened) r.formalVariant: r, +}; diff --git a/lib/search.dart b/lib/search.dart index 7089d9e..8a44777 100644 --- a/lib/search.dart +++ b/lib/search.dart @@ -1,3 +1,4 @@ +import 'package:jadb/const_data/radicals.dart'; import 'package:jadb/models/kanji_search/kanji_search_result.dart'; import 'package:jadb/models/verify_tables.dart'; import 'package:jadb/models/word_search/word_search_result.dart'; @@ -63,13 +64,15 @@ extension JaDBConnection on DatabaseExecutor { /// 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> jadbSearchRemainingRadicals(List radicals) => - searchRemainingRadicalsWithDbConnection(this, radicals); + Future> jadbSearchRemainingRadicals( + List radicals, + ) => searchRemainingRadicalsWithDbConnection(this, radicals); /// Given a list of radicals, search which kanji contains all /// of the radicals, and return those. - Future> jadbSearchKanjiByRadicals(List radicals) => - searchKanjiByRadicalsWithDbConnection(this, radicals); + Future> jadbSearchKanjiByRadicals( + List radicals, + ) => searchKanjiByRadicalsWithDbConnection(this, radicals); /// Retrieve the version information for all datasources in the database. Future jadbGetDatasourceVersions() => diff --git a/lib/search/radical_search.dart b/lib/search/radical_search.dart index e0bd4e1..abab301 100644 --- a/lib/search/radical_search.dart +++ b/lib/search/radical_search.dart @@ -1,3 +1,4 @@ +import 'package:jadb/const_data/radicals.dart'; import 'package:jadb/table_names/radkfile.dart'; import 'package:sqflite_common/sqlite_api.dart'; @@ -7,9 +8,9 @@ import 'package:sqflite_common/sqlite_api.dart'; /// /// This can be used to limit the choices of additional radicals provided to a user, /// so that any choice they make will still yield at least one kanji. -Future> searchRemainingRadicalsWithDbConnection( +Future> searchRemainingRadicalsWithDbConnection( DatabaseExecutor connection, - List radicals, + List radicals, ) async { final distinctRadicals = radicals.toSet(); @@ -25,11 +26,14 @@ Future> searchRemainingRadicalsWithDbConnection( HAVING COUNT(DISTINCT "radical") = ? ) ''', - [...distinctRadicals, distinctRadicals.length], + [...distinctRadicals.map((r) => r.formalVariant), distinctRadicals.length], ); final remainingRadicals = queryResult .map((row) => row['radical'] as String) + // TODO: maybe we should do some runtime checking here, just to throw a sensible error + // if something goes horribly wrong? + .map((r) => radicalsByFormalVariant[r]!) .toList(); return remainingRadicals; @@ -38,7 +42,7 @@ Future> searchRemainingRadicalsWithDbConnection( /// Returns a list of kanji that contain all of the input radicals. Future> searchKanjiByRadicalsWithDbConnection( DatabaseExecutor connection, - List radicals, + List radicals, ) async { final distinctRadicals = radicals.toSet(); @@ -50,7 +54,7 @@ Future> searchKanjiByRadicalsWithDbConnection( GROUP BY "kanji" HAVING COUNT(DISTINCT "radical") = ? ''', - [...distinctRadicals, distinctRadicals.length], + [...distinctRadicals.map((r) => r.formalVariant), distinctRadicals.length], ); final kanji = queryResult.map((row) => row['kanji'] as String).toList(); diff --git a/test/search/radical_search_test.dart b/test/search/radical_search_test.dart index e05b44f..7c61f65 100644 --- a/test/search/radical_search_test.dart +++ b/test/search/radical_search_test.dart @@ -58,31 +58,26 @@ void main() { }, ); - test( - 'All constant radicals are located in the correct stroke count group', - () { - for (final mapEntry in radicals.entries) { - final strokeCount = mapEntry.key; - final radicalsInGroup = mapEntry.value; - for (final radical in radicalsInGroup) { - expect( - strokeCount, - radical.strokeCount, - reason: - 'Radical ${radical.formalVariant} should have stroke count $strokeCount but has ${radical.strokeCount}', - ); - } + test('All constant radicals are located in the correct stroke count group', () { + for (final mapEntry in radicals.entries) { + final strokeCount = mapEntry.key; + final radicalsInGroup = mapEntry.value; + for (final radical in radicalsInGroup) { + expect( + strokeCount, + radical.strokeCount, + reason: + 'Radical ${radical.formalVariant} should have stroke count $strokeCount but has ${radical.strokeCount}', + ); } - }, - ); + } + }); group('All radicals should return results', () { for (final radical in radicals.values.flattened) { test(' - $radical', () async { final connection = await setupDatabaseConnection(); - final result = await connection.jadbSearchKanjiByRadicals([ - radical.formalVariant, - ]); + final result = await connection.jadbSearchKanjiByRadicals([radical]); expect(result, isNotEmpty); }); }