explanation

master
gitea 4 weeks ago
parent cd3b75995d
commit 82be8dbdf3

@ -17,18 +17,21 @@ class DefaultDeck {
prompt: 'What is the capital city of Australia?',
answers: ['Sydney', 'Melbourne', 'Canberra', 'Perth'],
correctAnswerIndices: [2],
explanation: 'Canberra was chosen as the capital in 1908 as a compromise between Sydney and Melbourne.',
),
Question(
id: 'gk_2',
prompt: 'Which planet is known as the Red Planet?',
answers: ['Venus', 'Mars', 'Jupiter', 'Saturn'],
correctAnswerIndices: [1],
explanation: 'Mars appears red due to iron oxide (rust) on its surface.',
),
Question(
id: 'gk_3',
prompt: 'What is the largest ocean on Earth?',
answers: ['Atlantic Ocean', 'Indian Ocean', 'Arctic Ocean', 'Pacific Ocean'],
correctAnswerIndices: [3],
explanation: 'The Pacific Ocean covers about 63 million square miles and is larger than all of Earth\'s land area combined.',
),
Question(
id: 'gk_4',
@ -203,6 +206,7 @@ class DefaultDeck {
prompt: 'What is the capital city of Australia?',
answers: ['Sydney', 'Melbourne', 'Canberra', 'Perth'],
correctAnswerIndices: [2],
explanation: 'Canberra was chosen as the capital in 1908 as a compromise between Sydney and Melbourne.',
consecutiveCorrect: 3,
isKnown: true,
priorityPoints: 0,
@ -216,6 +220,7 @@ class DefaultDeck {
prompt: 'Which planet is known as the Red Planet?',
answers: ['Venus', 'Mars', 'Jupiter', 'Saturn'],
correctAnswerIndices: [1],
explanation: 'Mars appears red due to iron oxide (rust) on its surface.',
consecutiveCorrect: 3,
isKnown: true,
priorityPoints: 0,
@ -227,6 +232,7 @@ class DefaultDeck {
Question(
id: 'gk_3',
prompt: 'What is the largest ocean on Earth?',
explanation: 'The Pacific Ocean covers about 63 million square miles and is larger than all of Earth\'s land area combined.',
answers: ['Atlantic Ocean', 'Indian Ocean', 'Arctic Ocean', 'Pacific Ocean'],
correctAnswerIndices: [3],
consecutiveCorrect: 3,

@ -209,6 +209,22 @@ class _AttemptResultScreenState extends State<AttemptResultScreen> {
),
);
}),
if (q.explanation != null && q.explanation!.trim().isNotEmpty) ...[
const SizedBox(height: 16),
const Divider(),
const SizedBox(height: 8),
Text(
'Explanation',
style: Theme.of(context).textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
Text(
q.explanation!,
style: Theme.of(context).textTheme.bodyMedium,
),
],
],
),
),

@ -161,6 +161,7 @@ class _DeckEditScreenState extends State<DeckEditScreen> {
final list = questions.map((q) => {
'id': q.id,
'prompt': q.prompt,
if (q.explanation != null && q.explanation!.isNotEmpty) 'explanation': q.explanation,
'answers': q.answers,
'correctAnswerIndices': q.correctAnswerIndices,
}).toList();
@ -378,6 +379,16 @@ class _QuestionEditorCardState extends State<QuestionEditorCard> {
),
maxLines: 2,
),
const SizedBox(height: 12),
TextField(
controller: widget.editor.explanationController,
decoration: const InputDecoration(
labelText: 'Explanation (optional)',
helperText: 'Shown when viewing question details after an attempt',
border: OutlineInputBorder(),
),
maxLines: 3,
),
const SizedBox(height: 16),
// Answers
@ -474,12 +485,14 @@ class _QuestionEditorCardState extends State<QuestionEditorCard> {
class QuestionEditor {
final TextEditingController promptController;
final TextEditingController explanationController;
final List<TextEditingController> answerControllers;
Set<int> correctAnswerIndices;
final String? originalId;
QuestionEditor({
required this.promptController,
required this.explanationController,
required this.answerControllers,
Set<int>? correctAnswerIndices,
this.originalId,
@ -488,6 +501,7 @@ class QuestionEditor {
factory QuestionEditor.fromQuestion(Question question) {
return QuestionEditor(
promptController: TextEditingController(text: question.prompt),
explanationController: TextEditingController(text: question.explanation ?? ''),
answerControllers: question.answers
.map((answer) => TextEditingController(text: answer))
.toList(),
@ -499,6 +513,7 @@ class QuestionEditor {
factory QuestionEditor.empty() {
return QuestionEditor(
promptController: TextEditingController(),
explanationController: TextEditingController(),
answerControllers: [
TextEditingController(),
TextEditingController(),
@ -521,9 +536,11 @@ class QuestionEditor {
}
Question toQuestion() {
final explanationText = explanationController.text.trim();
return Question(
id: originalId ?? DateTime.now().millisecondsSinceEpoch.toString(),
prompt: promptController.text.trim(),
explanation: explanationText.isEmpty ? null : explanationText,
answers: answerControllers.map((c) => c.text.trim()).toList(),
correctAnswerIndices: correctAnswerIndices.toList()..sort(),
);
@ -531,6 +548,7 @@ class QuestionEditor {
void dispose() {
promptController.dispose();
explanationController.dispose();
for (final controller in answerControllers) {
controller.dispose();
}

@ -64,6 +64,7 @@ class _DeckImportScreenState extends State<DeckImportScreen> {
return Question(
id: questionMap['id'] as String? ?? '',
prompt: questionMap['prompt'] as String? ?? '',
explanation: questionMap['explanation'] as String?,
answers: (questionMap['answers'] as List<dynamic>?)
?.map((e) => e.toString())
.toList() ??
@ -643,6 +644,7 @@ class _DeckImportScreenState extends State<DeckImportScreen> {
const Text('• answers: array of strings (required)'),
const Text('• correctAnswerIndex: number (deprecated, use correctAnswerIndices)'),
const Text('• correctAnswerIndices: array of numbers (for multiple correct answers)'),
const Text('• explanation: string (optional, shown when viewing question details)'),
const Text('• isKnown: boolean (optional)'),
const Text('• consecutiveCorrect: number (optional)'),
const Text('• priorityPoints: number (optional)'),

@ -156,8 +156,10 @@ class _FlaggedQuestionsScreenState extends State<FlaggedQuestionsScreen> {
if (id == null) continue;
final existing = questionMap[id];
if (existing == null) continue;
final explanationText = editor.explanationController.text.trim();
final updated = existing.copyWith(
prompt: editor.promptController.text.trim(),
explanation: explanationText.isEmpty ? null : explanationText,
answers: editor.answerControllers.map((c) => c.text.trim()).toList(),
correctAnswerIndices: editor.correctAnswerIndices.toList()..sort(),
);
@ -203,6 +205,7 @@ class _FlaggedQuestionsScreenState extends State<FlaggedQuestionsScreen> {
final list = questions.map((q) => {
'id': q.id,
'prompt': q.prompt,
if (q.explanation != null && q.explanation!.isNotEmpty) 'explanation': q.explanation,
'answers': q.answers,
'correctAnswerIndices': q.correctAnswerIndices,
}).toList();

@ -66,6 +66,7 @@ class DeckStorage {
'questions': deck.questions.map((q) => {
'id': q.id,
'prompt': q.prompt,
if (q.explanation != null && q.explanation!.isNotEmpty) 'explanation': q.explanation,
'answers': q.answers,
'correctAnswerIndices': q.correctAnswerIndices,
'consecutiveCorrect': q.consecutiveCorrect,
@ -133,6 +134,7 @@ class DeckStorage {
return Question(
id: questionMap['id'] as String? ?? '',
prompt: questionMap['prompt'] as String? ?? '',
explanation: questionMap['explanation'] as String?,
answers: (questionMap['answers'] as List<dynamic>?)
?.map((e) => e.toString())
.toList() ??

@ -6,6 +6,9 @@ class Question {
/// The question prompt.
final String prompt;
/// Optional explanation shown when viewing question details (e.g. after an attempt).
final String? explanation;
/// List of possible answers.
final List<String> answers;
@ -42,6 +45,7 @@ class Question {
Question({
required this.id,
required this.prompt,
this.explanation,
required this.answers,
List<int>? correctAnswerIndices,
@Deprecated('Use correctAnswerIndices instead') int? correctAnswerIndex,
@ -60,6 +64,7 @@ class Question {
Question copyWith({
String? id,
String? prompt,
String? explanation,
List<String>? answers,
List<int>? correctAnswerIndices,
@Deprecated('Use correctAnswerIndices instead') int? correctAnswerIndex,
@ -74,6 +79,7 @@ class Question {
return Question(
id: id ?? this.id,
prompt: prompt ?? this.prompt,
explanation: explanation ?? this.explanation,
answers: answers ?? this.answers,
correctAnswerIndices: correctAnswerIndices ?? this.correctAnswerIndices,
correctAnswerIndex: correctAnswerIndex ?? this.correctAnswerIndex,
@ -119,6 +125,7 @@ class Question {
runtimeType == other.runtimeType &&
id == other.id &&
prompt == other.prompt &&
explanation == other.explanation &&
answers.toString() == other.answers.toString() &&
correctAnswerIndices.toString() == other.correctAnswerIndices.toString() &&
consecutiveCorrect == other.consecutiveCorrect &&
@ -133,6 +140,7 @@ class Question {
int get hashCode =>
id.hashCode ^
prompt.hashCode ^
(explanation?.hashCode ?? 0) ^
answers.hashCode ^
correctAnswerIndices.hashCode ^
consecutiveCorrect.hashCode ^

Loading…
Cancel
Save

Powered by TurnKey Linux.