mnemo_cards/lib/features/tests/test_complete_widget.dart
2024-06-15 18:42:18 +03:00

204 lines
7.1 KiB
Dart

import 'dart:math';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:mnemo_cards/utils/color_helper.dart';
import 'package:rxdart/rxdart.dart';
import '../../di/locator.dart';
import '../../widgets/big_back_button.dart';
import '../../widgets/horizontal_progress.dart';
import 'question_states/test_question_state.dart';
class TestCompleteWidget extends StatelessWidget {
final Iterable<TestQuestionState> states;
final Color successColor;
static final _pieChartKey = GlobalKey<ImplicitlyAnimatedWidgetState>();
TestCompleteWidget(
this.states,
this.successColor,
);
@override
Widget build(BuildContext context) {
final total = states.length;
final correct = states.where((e) => e.isCorrect).length;
final incorrect = states.where((e) => !e.isCorrect && e.isAnswered).length;
final skipped = states.where((e) => !e.isAnswered).length;
final words = states
.fold(
Map<String, WordStat>(),
(map, state) => map
..[state.word] = (map[state.word] ?? WordStat.zero(state.word))
.inc(state.isCorrect),
)
.values
.toList()
..sort(
(p, n) => (p.correctCount.toDouble() / p.totalCount)
.compareTo(n.correctCount.toDouble() / n.totalCount),
);
return PopScope(
onPopInvoked: (v) {
if (v) {
locator.testManager.sendStatistics();
locator.testManager.triggerPoll();
}
},
child: Column(
children: [
Expanded(
flex: 3,
child: Padding(
padding: const EdgeInsets.only(top: 12.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: MediaQuery.of(context).size.width / 1.8,
height: MediaQuery.of(context).size.width / 1.8,
padding: const EdgeInsets.all(20.0),
child: StreamBuilder<int>(
stream: Stream.fromIterable([5])
.interval(Duration(milliseconds: 0)),
initialData: 0,
builder: (context, snapshot) {
final a = min(snapshot.requireData / 5.0, 1.0);
return PieChart(
key: _pieChartKey,
swapAnimationDuration: Duration(milliseconds: 600),
PieChartData(
pieTouchData: PieTouchData(),
borderData: FlBorderData(
show: false,
),
sectionsSpace: 0,
centerSpaceRadius:
MediaQuery.of(context).size.width / 8,
sections: [
PieChartSectionData(
color: successColor,
showTitle: false,
value: correct.toDouble() * a,
badgeWidget: Image.asset(
'icons/crown.png',
width: 20.w,
),
),
PieChartSectionData(
color: successColor.lighten(0.15),
showTitle: false,
value: incorrect.toDouble() * a,
badgeWidget: Image.asset(
'icons/skull.png',
width: 20.w,
),
),
PieChartSectionData(
color: Colors.white,
showTitle: false,
value: skipped.toDouble(),
badgeWidget: Image.asset(
'icons/small_circle.png',
width: 20.w,
),
),
],
),
);
}),
),
Text(
'$correct/$total',
style: TextStyle(
fontSize: 36,
fontWeight: FontWeight.w500,
),
),
// Text(
// '1:47',
// style: TextStyle(
// fontSize: 20,
// fontWeight: FontWeight.w500,
// height: 0.85,
// ),
// ),
],
),
),
),
Expanded(
flex: 2,
child: Container(
alignment: Alignment.bottomCenter,
child: ListView.builder(
shrinkWrap: true,
itemCount: words.length,
itemBuilder: (context, index) {
final word = words[index];
return Padding(
padding: const EdgeInsets.only(
left: 12.0,
right: 24,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${word.word}',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w500,
),
),
Flexible(
child: SizedBox(
width: MediaQuery.of(context).size.width / 2.5,
child: HorizontalProgressWidget(
word.correctCount,
word.totalCount,
successColor,
),
),
),
],
),
);
},
),
),
),
const BigBackButton(),
],
),
);
}
}
class WordStat {
String word;
int correctCount;
int totalCount;
WordStat(this.word, this.correctCount, this.totalCount);
factory WordStat.zero(String word) => WordStat(word, 0, 0);
WordStat inc(bool isCorrect) => isCorrect ? correct(this) : incorrect(this);
WordStat correct(WordStat stat) => WordStat(
stat.word,
stat.correctCount + 1,
stat.totalCount + 1,
);
WordStat incorrect(WordStat stat) => WordStat(
stat.word,
stat.correctCount,
stat.totalCount + 1,
);
}