297 lines
10 KiB
Dart
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,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|