added sound

This commit is contained in:
Rene Kievits
2025-10-28 05:44:14 +01:00
parent 29909a07a7
commit 6dabb9c977
10 changed files with 139 additions and 35 deletions

View File

@@ -6,6 +6,8 @@ import '../services/deck_repository.dart';
import '../services/distractor_generator.dart';
import '../widgets/kanji_card.dart';
import '../widgets/options_grid.dart';
import 'package:audioplayers/audioplayers.dart';
import 'settings_screen.dart';
class _ReadingInfo {
@@ -28,6 +30,7 @@ class _HomeScreenState extends State<HomeScreen> {
String _status = 'Loading deck...';
final DistractorGenerator _dg = DistractorGenerator();
final Random _random = Random();
final _audioPlayer = AudioPlayer();
QuizMode _mode = QuizMode.kanjiToEnglish;
KanjiItem? _current;
@@ -109,14 +112,20 @@ class _HomeScreenState extends State<HomeScreen> {
void _nextQuestion() {
_deck.sort((a, b) {
final aSrsItem = a.srsItems[_mode.toString()] ?? SrsItem(kanjiId: a.id, quizMode: _mode);
final bSrsItem = b.srsItems[_mode.toString()] ?? SrsItem(kanjiId: b.id, quizMode: _mode);
final aSrsItem = a.srsItems[_mode.toString()];
final bSrsItem = b.srsItems[_mode.toString()];
final stageComparison = aSrsItem.srsStage.compareTo(bSrsItem.srsStage);
if (stageComparison != 0) {
return stageComparison;
final aStage = aSrsItem?.srsStage ?? 0;
final bStage = bSrsItem?.srsStage ?? 0;
if (aStage != bStage) {
return aStage.compareTo(bStage);
}
return aSrsItem.lastAsked.compareTo(bSrsItem.lastAsked);
final aLastAsked = aSrsItem?.lastAsked ?? DateTime.fromMillisecondsSinceEpoch(0);
final bLastAsked = bSrsItem?.lastAsked ?? DateTime.fromMillisecondsSinceEpoch(0);
return aLastAsked.compareTo(bLastAsked);
});
_current = _deck.first;
@@ -128,16 +137,19 @@ class _HomeScreenState extends State<HomeScreen> {
switch (_mode) {
case QuizMode.kanjiToEnglish:
_correctAnswers = [_current!.meanings.first];
_options = [_correctAnswers.first, ..._dg.generateMeanings(_current!, _deck, 3)]
.map(_toTitleCase)
.toList()
_options = [
_correctAnswers.first,
..._dg.generateMeanings(_current!, _deck, 3)
].map(_toTitleCase).toList()
..shuffle();
break;
case QuizMode.englishToKanji:
_correctAnswers = [_current!.characters];
_options = [_correctAnswers.first, ..._dg.generateKanji(_current!, _deck, 3)]
..shuffle();
_options = [
_correctAnswers.first,
..._dg.generateKanji(_current!, _deck, 3)
]..shuffle();
break;
case QuizMode.reading:
@@ -149,10 +161,15 @@ class _HomeScreenState extends State<HomeScreen> {
? _deck.expand((k) => k.onyomi)
: _deck.expand((k) => k.kunyomi);
final distractors =
readingsSource.where((r) => !_correctAnswers.contains(r)).toSet().toList()
final distractors = readingsSource
.where((r) => !_correctAnswers.contains(r))
.toSet()
.toList()
..shuffle();
_options = ([_correctAnswers[_random.nextInt(_correctAnswers.length)], ...distractors.take(3)])
_options = ([
_correctAnswers[_random.nextInt(_correctAnswers.length)],
...distractors.take(3)
])
..shuffle();
break;
}
@@ -176,29 +193,31 @@ class _HomeScreenState extends State<HomeScreen> {
var srsItem = current.srsItems[srsKey];
final isNew = srsItem == null;
srsItem ??= SrsItem(kanjiId: current.id, quizMode: _mode, readingType: readingType);
final srsItemForUpdate = srsItem ??=
SrsItem(kanjiId: current.id, quizMode: _mode, readingType: readingType);
setState(() {
_asked += 1;
if (isCorrect) {
_score += 1;
srsItem!.srsStage += 1;
_audioPlayer.play(AssetSource('sfx/confirm.mp3'));
} else {
srsItem!.srsStage = max(0, srsItem.srsStage - 1);
srsItemForUpdate.srsStage = max(0, srsItemForUpdate.srsStage - 1);
}
srsItem.lastAsked = DateTime.now();
current.srsItems[srsKey] = srsItem;
srsItemForUpdate.lastAsked = DateTime.now();
current.srsItems[srsKey] = srsItemForUpdate;
});
if (isNew) {
await repo.insertSrsItem(srsItem);
await repo.insertSrsItem(srsItemForUpdate);
} else {
await repo.updateSrsItem(srsItem);
await repo.updateSrsItem(srsItemForUpdate);
}
final correctDisplay = (_mode == QuizMode.kanjiToEnglish)
? _toTitleCase(_correctAnswers.first)
: (_mode == QuizMode.reading ? _correctAnswers.join(', ') : _correctAnswers.first);
: (_mode == QuizMode.reading
? _correctAnswers.join(', ')
: _correctAnswers.first);
final snack = SnackBar(
content: Text(
@@ -271,7 +290,6 @@ class _HomeScreenState extends State<HomeScreen> {
],
),
const SizedBox(height: 12),
Wrap(
spacing: 6,
runSpacing: 4,
@@ -282,9 +300,7 @@ class _HomeScreenState extends State<HomeScreen> {
_buildChoiceChip('Reading', QuizMode.reading),
],
),
const SizedBox(height: 18),
Expanded(
flex: 3,
child: Center(
@@ -303,9 +319,7 @@ class _HomeScreenState extends State<HomeScreen> {
),
),
),
const SizedBox(height: 12),
SafeArea(
top: false,
child: Column(
@@ -346,4 +360,4 @@ class _HomeScreenState extends State<HomeScreen> {
backgroundColor: const Color(0xFF1E1E1E),
);
}
}
}

View File

@@ -6,11 +6,13 @@ import '../services/deck_repository.dart';
import '../services/distractor_generator.dart';
import '../widgets/kanji_card.dart';
import '../widgets/options_grid.dart';
import 'package:audioplayers/audioplayers.dart';
import 'settings_screen.dart';
class VocabScreen extends StatefulWidget {
const VocabScreen({super.key});
@override
State<VocabScreen> createState() => _VocabScreenState();
}
@@ -19,7 +21,7 @@ class _VocabScreenState extends State<VocabScreen> {
bool _loading = false;
String _status = 'Loading deck...';
final DistractorGenerator _dg = DistractorGenerator();
final Random _random = Random();
final _audioPlayer = AudioPlayer();
VocabQuizMode _mode = VocabQuizMode.vocabToEnglish;
VocabularyItem? _current;
@@ -138,17 +140,19 @@ class _VocabScreenState extends State<VocabScreen> {
final srsKey = _mode.toString();
var srsItem = current.srsItems[srsKey];
final isNew = srsItem == null;
srsItem ??= VocabSrsItem(vocabId: current.id, quizMode: _mode);
var srsItemNullable = current.srsItems[srsKey];
final isNew = srsItemNullable == null;
final srsItem =
srsItemNullable ?? VocabSrsItem(vocabId: current.id, quizMode: _mode);
setState(() {
_asked += 1;
if (isCorrect) {
_score += 1;
srsItem!.srsStage += 1;
_audioPlayer.play(AssetSource('sfx/confirm.mp3'));
srsItem.srsStage += 1;
} else {
srsItem!.srsStage = max(0, srsItem.srsStage - 1);
srsItem.srsStage = max(0, srsItem.srsStage - 1);
}
srsItem.lastAsked = DateTime.now();
current.srsItems[srsKey] = srsItem;