Line data Source code
1 : import 'package:amadeus_proto/constants.dart';
2 : import 'package:amadeus_proto/exercises/categories/rhythm/beats/rhythm_card.dart';
3 : import 'package:amadeus_proto/exercises/providers/beats_clicking_provider.dart';
4 : import 'package:amadeus_proto/exercises/widget/animation_dialog_wrapper.dart';
5 : import 'package:amadeus_proto/exercises/widget/exercise_header.dart';
6 : import 'package:amadeus_proto/exercises/widget/exercises_end_dialog.dart';
7 : import 'package:amadeus_proto/api/models/exercise_info.dart';
8 : import 'package:flutter/material.dart';
9 : import 'package:provider/provider.dart';
10 :
11 : class RhythmPage extends StatefulWidget {
12 0 : const RhythmPage({super.key, required this.info});
13 :
14 : final ExerciseInfo info;
15 :
16 0 : @override
17 0 : State<RhythmPage> createState() => Rhythmxercises();
18 : }
19 :
20 : class Rhythmxercises extends State<RhythmPage> {
21 0 : @override
22 : void initState() {
23 0 : super.initState();
24 0 : WidgetsBinding.instance.addPostFrameCallback((_) {
25 0 : context.read<BeatsClickingProvider>().reset();
26 : });
27 : }
28 :
29 0 : @override
30 : Widget build(BuildContext context) {
31 0 : final BeatsClickingProvider rhtyhm = context.watch<BeatsClickingProvider>();
32 :
33 0 : WidgetsBinding.instance.addPostFrameCallback((_) {
34 0 : if (!rhtyhm.isInitialized) {
35 0 : rhtyhm.initializeData(widget.info.exerciseData);
36 0 : rhtyhm.exerciseInfo = widget.info;
37 : }
38 0 : if (rhtyhm.playing == RhythmState.end) {
39 0 : int errors = checkPressed(rhtyhm.timers, rhtyhm.gap);
40 0 : Future.delayed(Duration.zero, () {
41 0 : if (errors != 0) {
42 0 : rhtyhm.lives--;
43 0 : rhtyhm.correctAnswer = false;
44 : }
45 0 : rhtyhm.playing = RhythmState.done;
46 : });
47 : }
48 0 : if (!rhtyhm.displayDialog && rhtyhm.playing == RhythmState.done) {
49 0 : rhtyhm.displayDialog = true;
50 :
51 0 : Future.delayed(Duration.zero, () {
52 0 : if (!context.mounted) return;
53 0 : showGeneralDialog(
54 : context: context,
55 : transitionDuration: const Duration(milliseconds: fastAnimation),
56 0 : pageBuilder: (context, animation1, animation2) {
57 0 : return ExerciseEndDialog<BeatsClickingProvider>(
58 0 : leavingExerciseCallback: () {
59 0 : Navigator.of(context).pop();
60 0 : Navigator.of(context).pop();
61 : },
62 0 : resetExerciseCallback: () {
63 0 : Navigator.of(context).pop();
64 0 : Future.delayed(const Duration(milliseconds: fastAnimation),
65 0 : () {
66 0 : if (mounted) {
67 0 : context.read<BeatsClickingProvider>().reset();
68 : }
69 : });
70 : },
71 0 : exerciseTitle: widget.info.exerciseData!["title"],
72 0 : exerciseCategory: widget.info.exerciseData!["category"],
73 : );
74 : },
75 : transitionBuilder:
76 0 : (context, animation, secondaryAnimation, child) {
77 0 : return ScaleTransition(
78 : scale: animation,
79 0 : child: AnimatedDialogWrapper(
80 : animation: animation,
81 : child: child,
82 : ),
83 : );
84 : });
85 : });
86 : }
87 : });
88 0 : return Scaffold(
89 0 : body: SafeArea(
90 0 : child: Container(
91 : decoration: const BoxDecoration(
92 : gradient: LinearGradient(
93 : begin: Alignment.centerLeft,
94 : end: Alignment.centerRight,
95 : colors: [
96 : Color(0xFFEAE6F6),
97 : Colors.white, // End color
98 : ],
99 : stops: [0.0, 1.0], // The gradient's stops
100 : ),
101 : ),
102 : child: const Column(
103 : children: [
104 : Column(children: [ExerciseHeader<BeatsClickingProvider>()]),
105 : SizedBox(
106 : height: 10,
107 : ),
108 : Expanded(child: RhythmCard())
109 : ],
110 : ),
111 : ),
112 : ));
113 : }
114 :
115 0 : int checkPressed(List<int> timers, int gap) {
116 : final BeatsClickingProvider rhythmExercise =
117 0 : context.read<BeatsClickingProvider>();
118 : int errors = 0;
119 0 : List<int> converted = [];
120 :
121 0 : for (int i = 0; i < rhythmExercise.pressed.length; i++) {
122 : converted
123 0 : .add(rhythmExercise.pressed[i] - rhythmExercise.startMilliseconds);
124 : }
125 :
126 0 : for (int i = 0; i < converted.length; i++) {
127 0 : if (i >= timers.length) {
128 0 : errors++;
129 : continue;
130 : }
131 0 : if (converted[i] > timers[i] + gap || converted[i] < timers[i] - gap) {
132 0 : errors++;
133 : }
134 : }
135 0 : if (converted.length < timers.length) {
136 0 : errors += timers.length - converted.length;
137 : }
138 : return errors;
139 : }
140 : }
|