mnemo_cards/lib/features/tests/test_widgets/input_buttons_test.dart

268 lines
9.1 KiB
Dart
Raw Normal View History

2024-05-22 20:48:44 +00:00
import 'dart:math';
2024-05-28 21:25:51 +00:00
import 'package:collection/collection.dart';
2024-05-22 20:48:44 +00:00
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mnemo_cards/features/tests/test_manager.dart';
2024-06-05 02:41:14 +00:00
import 'package:mnemo_cards/features/tests/test_widgets/common_test_question_widget.dart';
2024-05-22 20:48:44 +00:00
import 'package:mnemo_cards/features/tests/test_widgets/test_image.dart';
2024-05-28 21:25:51 +00:00
import 'package:mnemo_cards/theme/themes.dart';
2024-05-22 20:48:44 +00:00
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
import '../../../di/locator.dart';
import '../question_states/input_buttons_test_state.dart';
import 'test_button.dart';
class InputButtonsTestWidget extends StatelessWidget {
2024-05-31 14:35:41 +00:00
bool get isCorrect => state.answer.join() == correctAnswer;
2024-05-28 21:25:51 +00:00
final InputButtonsTestQuestionBody _inputButtonModel;
InputButtonsTestQuestionBody get model => _inputButtonModel;
2024-05-22 20:48:44 +00:00
InputButtonsTestState get state =>
manager.getState(model.id!) as InputButtonsTestState;
2024-05-31 14:35:41 +00:00
String get correctAnswer {
String correctAnswer = '';
for (int i = 0; i < model.template.length; i++) {
if (model.template[i] == '_') {
correctAnswer += model.answer[i];
}
}
return correctAnswer;
}
2024-05-22 20:48:44 +00:00
TestManager get manager => locator.testManager;
2024-05-28 21:25:51 +00:00
Color get testColor => manager.color;
2024-05-22 20:48:44 +00:00
2024-05-28 21:25:51 +00:00
InputButtonsTestWidget(this._inputButtonModel, {super.key});
2024-05-22 20:48:44 +00:00
@override
Widget build(BuildContext context) {
final theme = Theme.of(context).textTheme;
2024-05-28 21:25:51 +00:00
// final random = Random(state.seed);
final buttons = model.buttons; //..shuffle(random);
return Padding(
padding: const EdgeInsets.all(8.0),
child: LayoutBuilder(builder: (context, constraints) {
return Column(
2024-05-22 20:48:44 +00:00
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
2024-06-05 02:41:14 +00:00
Expanded(
child: CommonTestQuestionWidget(
text: model.text,
image: model.image,
audio: model.audio,
2024-05-22 20:48:44 +00:00
),
2024-06-05 02:41:14 +00:00
),
2024-05-22 20:48:44 +00:00
StatefulBuilder(builder: (context, setState) {
2024-05-28 21:25:51 +00:00
void buttonTapped(int index, TestButtonDto button) {
2024-05-22 20:48:44 +00:00
if (state.answer.fold(0, (p, n) => p + n.length) >=
2024-05-31 14:35:41 +00:00
correctAnswer.length) {
2024-05-22 20:48:44 +00:00
return;
}
setState(() {
2024-05-28 21:25:51 +00:00
var answer = [...state.answer, button.text!];
2024-05-22 20:48:44 +00:00
manager.setState(
model.id!,
state.copyWith(
2024-05-28 21:25:51 +00:00
answer: answer,
answerIds: [...state.answerIds, button.id],
2024-05-22 20:48:44 +00:00
),
);
manager.setState(
model.id!,
state.copyWith(
isAnswered: isCorrect,
isCorrect: isCorrect,
),
);
});
2024-05-31 14:35:41 +00:00
print('${state.answer} ${correctAnswer} ${state.isCorrect}');
2024-05-22 20:48:44 +00:00
if (isCorrect) {
Future.delayed(
Duration(milliseconds: 300),
manager.nextTest,
);
}
}
2024-05-28 21:25:51 +00:00
int splitIndex = 0;
2024-06-05 02:41:14 +00:00
if (model.template.length * 32 > constraints.maxWidth * 0.9) {
2024-05-31 14:35:41 +00:00
splitIndex = model.template.indexOf(
2024-05-28 21:25:51 +00:00
' ',
2024-05-31 14:35:41 +00:00
(model.template.length / 2).ceil(),
2024-05-28 21:25:51 +00:00
);
if (splitIndex < 10) {
2024-05-31 14:35:41 +00:00
splitIndex = model.template.indexOf(
2024-05-28 21:25:51 +00:00
' ',
2024-05-31 14:35:41 +00:00
(model.template.length / 3).ceil(),
2024-05-28 21:25:51 +00:00
);
}
if (splitIndex == -1) {
2024-05-31 14:35:41 +00:00
splitIndex = model.template.indexOf(
2024-05-28 21:25:51 +00:00
' ',
0,
);
}
}
if (splitIndex < 0) {
splitIndex = 0;
}
2024-05-31 14:35:41 +00:00
int stateAnswerIndex = 0;
final letters = model.template
2024-05-28 21:25:51 +00:00
.split('')
2024-05-31 14:35:41 +00:00
.map(
(letter) => letter == '_'
? _Letter(
text: state.answer.length > stateAnswerIndex
? state.answer[stateAnswerIndex++]
2024-05-28 21:25:51 +00:00
: ' ',
2024-05-31 14:35:41 +00:00
borderColor: testColor,
)
: _Letter.readOnly(
text: letter,
2024-05-28 21:25:51 +00:00
),
)
.toList();
final rows = [
if (splitIndex > 0)
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: letters.sublist(0, splitIndex),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: letters.sublist(splitIndex),
)
];
2024-05-22 20:48:44 +00:00
return Expanded(
child: Column(
children: [
Expanded(
child: GestureDetector(
onTap: () {
2024-05-28 21:25:51 +00:00
var answer = state.answer.toList();
var answerIds = state.answerIds.toList();
if (answer.isNotEmpty) {
2024-05-31 14:35:41 +00:00
answer.removeLast();
answerIds.removeLast();
2024-05-28 21:25:51 +00:00
}
2024-05-31 14:35:41 +00:00
2024-05-22 20:48:44 +00:00
setState(() {
manager.setState(
model.id!,
state.copyWith(
2024-05-28 21:25:51 +00:00
// isAnswered: false,
// isCorrect: false,
answer: answer,
answerIds: answerIds,
2024-05-22 20:48:44 +00:00
),
);
});
},
2024-05-31 14:35:41 +00:00
behavior: HitTestBehavior.opaque,
2024-05-28 21:25:51 +00:00
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
2024-05-22 20:48:44 +00:00
mainAxisAlignment: MainAxisAlignment.center,
2024-05-28 21:25:51 +00:00
mainAxisSize: MainAxisSize.min,
children: rows,
2024-05-22 20:48:44 +00:00
),
),
),
SizedBox(
height: 16.0,
),
AbsorbPointer(
absorbing: state.isCorrect,
child: Wrap(
children: [
2024-05-28 21:25:51 +00:00
...buttons.mapIndexed(
(index, button) => Container(
margin: EdgeInsets.all(4.0),
width: button.text!.length > 3
? null
: constraints.maxWidth / 6,
height: 50,
child: state.answerIds.contains(button.id)
? SizedBox.shrink()
: TestButton(
text: button.text,
onTap: () => buttonTapped(index, button),
color: state.answer == button
? isCorrect
? Colors.green[200]
: Colors.red[200]
: Colors.white,
),
2024-05-22 20:48:44 +00:00
),
),
],
),
),
],
),
);
})
],
2024-05-28 21:25:51 +00:00
);
}),
);
}
}
class _Letter extends StatelessWidget {
final String text;
2024-05-31 14:35:41 +00:00
final Color? borderColor;
final Color backgroundColor;
final double _width;
final double _padding;
final double _margin;
_Letter({
this.text = '',
this.borderColor,
this.backgroundColor = Colors.white,
}) : this._width = 32,
this._padding = 5,
this._margin = 2.0;
2024-05-28 21:25:51 +00:00
2024-05-31 14:35:41 +00:00
_Letter.readOnly({
this.text = '',
}) : this.borderColor = null,
this.backgroundColor = Colors.transparent,
this._width = text == ' ' ? 10 : 20,
this._padding = 0.0,
this._margin = 0.0;
2024-05-28 21:25:51 +00:00
@override
Widget build(BuildContext context) {
return Container(
2024-05-31 14:35:41 +00:00
width: _width,
2024-05-28 21:25:51 +00:00
height: 45,
2024-05-31 14:35:41 +00:00
alignment: Alignment.center,
margin: EdgeInsets.all(_margin),
padding: EdgeInsets.all(_padding),
2024-05-28 21:25:51 +00:00
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
2024-05-31 14:35:41 +00:00
color: backgroundColor,
2024-05-28 21:25:51 +00:00
borderRadius: BorderRadius.circular(6.0),
2024-05-31 14:35:41 +00:00
border: borderColor != null ? Border.all(color: borderColor!) : null,
2024-05-28 21:25:51 +00:00
),
child: Material(
2024-05-31 14:35:41 +00:00
color: backgroundColor,
2024-05-28 21:25:51 +00:00
child: Text(
text,
style: Theme.of(context).textTheme.titleLarge,
textAlign: TextAlign.center,
2024-05-22 20:48:44 +00:00
),
2024-05-28 21:25:51 +00:00
),
);
2024-05-22 20:48:44 +00:00
}
}