Files
jadb/lib/search/radical_search.dart
T
2026-06-03 20:18:02 +09:00

64 lines
2.1 KiB
Dart

import 'package:jadb/const_data/radicals.dart';
import 'package:jadb/table_names/radkfile.dart';
import 'package:sqflite_common/sqlite_api.dart';
// TODO: validate that the list of radicals all are valid radicals
/// Returns a list of radicals that are part of any kanji that contains all of the input radicals.
///
/// 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<List<RadkfileRadical>> searchRemainingRadicalsWithDbConnection(
DatabaseExecutor connection,
List<RadkfileRadical> radicals,
) async {
final distinctRadicals = radicals.toSet();
final queryResult = await connection.rawQuery(
'''
SELECT DISTINCT "radical"
FROM "${RADKFILETableNames.radkfile}"
WHERE "kanji" IN (
SELECT "kanji"
FROM "${RADKFILETableNames.radkfile}"
WHERE "radical" IN (${List.filled(distinctRadicals.length, '?').join(',')})
GROUP BY "kanji"
HAVING COUNT(DISTINCT "radical") = ?
)
''',
[...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;
}
/// Returns a list of kanji that contain all of the input radicals.
Future<List<String>> searchKanjiByRadicalsWithDbConnection(
DatabaseExecutor connection,
List<RadkfileRadical> radicals,
) async {
final distinctRadicals = radicals.toSet();
final queryResult = await connection.rawQuery(
'''
SELECT "kanji"
FROM "${RADKFILETableNames.radkfile}"
WHERE "radical" IN (${List.filled(distinctRadicals.length, '?').join(',')})
GROUP BY "kanji"
HAVING COUNT(DISTINCT "radical") = ?
''',
[...distinctRadicals.map((r) => r.formalVariant), distinctRadicals.length],
);
final kanji = queryResult.map((row) => row['kanji'] as String).toList();
return kanji;
}