mnemo_cards/lib/features/tests/test_widgets/input_buttons_test.dart
2024-05-31 17:35:41 +03:00

297 lines
10 KiB
Dart

import 'dart:math';
import 'package:collection/collection.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mnemo_cards/features/tests/test_manager.dart';
import 'package:mnemo_cards/features/tests/test_widgets/test_image.dart';
import 'package:mnemo_cards/theme/themes.dart';
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 {
bool get isCorrect => state.answer.join() == correctAnswer;
final InputButtonsTestQuestionBody _inputButtonModel;
InputButtonsTestQuestionBody get model => _inputButtonModel;
InputButtonsTestState get state =>
manager.getState(model.id!) as InputButtonsTestState;
String get correctAnswer {
String correctAnswer = '';
for (int i = 0; i < model.template.length; i++) {
if (model.template[i] == '_') {
correctAnswer += model.answer[i];
}
}
return correctAnswer;
}
TestManager get manager => locator.testManager;
Color get testColor => manager.color;
InputButtonsTestWidget(this._inputButtonModel, {super.key});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context).textTheme;
// 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(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (model.image != null)
Container(
margin: const EdgeInsets.all(4.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.0),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AspectRatio(
aspectRatio: model.text == null ? 1 : 1.5,
child: TestImageWidget(
TestImage.image(model.image!),
),
),
if (model.text != null)
Container(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: Center(
child: Text(
model.text!,
style: theme.headlineLarge,
),
),
),
],
),
)
else
Flexible(
child: Center(
child: Text(
model.text!,
style: theme.headlineLarge,
),
),
),
StatefulBuilder(builder: (context, setState) {
void buttonTapped(int index, TestButtonDto button) {
if (state.answer.fold(0, (p, n) => p + n.length) >=
correctAnswer.length) {
return;
}
setState(() {
var answer = [...state.answer, button.text!];
manager.setState(
model.id!,
state.copyWith(
answer: answer,
answerIds: [...state.answerIds, button.id],
),
);
manager.setState(
model.id!,
state.copyWith(
isAnswered: isCorrect,
isCorrect: isCorrect,
),
);
});
print('${state.answer} ${correctAnswer} ${state.isCorrect}');
if (isCorrect) {
Future.delayed(
Duration(milliseconds: 300),
manager.nextTest,
);
}
}
int splitIndex = 0;
if (model.template.length * 30 > constraints.maxWidth * 0.9) {
splitIndex = model.template.indexOf(
' ',
(model.template.length / 2).ceil(),
);
if (splitIndex < 10) {
splitIndex = model.template.indexOf(
' ',
(model.template.length / 3).ceil(),
);
}
if (splitIndex == -1) {
splitIndex = model.template.indexOf(
' ',
0,
);
}
}
if (splitIndex < 0) {
splitIndex = 0;
}
int stateAnswerIndex = 0;
final letters = model.template
.split('')
.map(
(letter) => letter == '_'
? _Letter(
text: state.answer.length > stateAnswerIndex
? state.answer[stateAnswerIndex++]
: ' ',
borderColor: testColor,
)
: _Letter.readOnly(
text: letter,
),
)
.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),
)
];
return Expanded(
child: Column(
children: [
Expanded(
child: GestureDetector(
onTap: () {
var answer = state.answer.toList();
var answerIds = state.answerIds.toList();
if (answer.isNotEmpty) {
answer.removeLast();
answerIds.removeLast();
}
setState(() {
manager.setState(
model.id!,
state.copyWith(
// isAnswered: false,
// isCorrect: false,
answer: answer,
answerIds: answerIds,
),
);
});
},
behavior: HitTestBehavior.opaque,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: rows,
),
),
),
SizedBox(
height: 16.0,
),
AbsorbPointer(
absorbing: state.isCorrect,
child: Wrap(
children: [
...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,
),
),
),
],
),
),
],
),
);
})
],
);
}),
);
}
}
class _Letter extends StatelessWidget {
final String text;
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;
_Letter.readOnly({
this.text = '',
}) : this.borderColor = null,
this.backgroundColor = Colors.transparent,
this._width = text == ' ' ? 10 : 20,
this._padding = 0.0,
this._margin = 0.0;
@override
Widget build(BuildContext context) {
return Container(
width: _width,
height: 45,
alignment: Alignment.center,
margin: EdgeInsets.all(_margin),
padding: EdgeInsets.all(_padding),
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(6.0),
border: borderColor != null ? Border.all(color: borderColor!) : null,
),
child: Material(
color: backgroundColor,
child: Text(
text,
style: Theme.of(context).textTheme.titleLarge,
textAlign: TextAlign.center,
),
),
);
}
}