192 lines
6.5 KiB
Dart
192 lines
6.5 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 '../../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.compareTo(n.correctCount));
|
|
return 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,
|
|
);
|
|
}
|