You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
4.4 KiB

/// A question in a practice deck.
class Question {
/// Unique identifier for this question.
final String id;
/// The question prompt.
final String prompt;
/// List of possible answers.
final List<String> answers;
/// Indices of correct answers in [answers].
/// For backward compatibility, if empty, falls back to [correctAnswerIndex] (deprecated).
final List<int> correctAnswerIndices;
/// Deprecated: Use [correctAnswerIndices] instead.
/// Kept for backward compatibility with existing data.
@Deprecated('Use correctAnswerIndices instead')
final int? correctAnswerIndex;
/// Number of consecutive correct answers.
final int consecutiveCorrect;
/// Whether this question is considered "known".
final bool isKnown;
/// Priority points (higher = more likely to be selected).
final int priorityPoints;
/// The last attempt index where this question was seen.
final int lastAttemptIndex;
/// Total number of correct attempts.
final int totalCorrectAttempts;
/// Total number of attempts.
final int totalAttempts;
Question({
required this.id,
required this.prompt,
required this.answers,
List<int>? correctAnswerIndices,
@Deprecated('Use correctAnswerIndices instead') int? correctAnswerIndex,
this.consecutiveCorrect = 0,
this.isKnown = false,
this.priorityPoints = 0,
this.lastAttemptIndex = -1,
this.totalCorrectAttempts = 0,
this.totalAttempts = 0,
}) : correctAnswerIndices = correctAnswerIndices ??
(correctAnswerIndex != null ? [correctAnswerIndex] : const []),
correctAnswerIndex = correctAnswerIndex;
/// Creates a copy of this question with the given fields replaced.
Question copyWith({
String? id,
String? prompt,
List<String>? answers,
List<int>? correctAnswerIndices,
@Deprecated('Use correctAnswerIndices instead') int? correctAnswerIndex,
int? consecutiveCorrect,
bool? isKnown,
int? priorityPoints,
int? lastAttemptIndex,
int? totalCorrectAttempts,
int? totalAttempts,
}) {
return Question(
id: id ?? this.id,
prompt: prompt ?? this.prompt,
answers: answers ?? this.answers,
correctAnswerIndices: correctAnswerIndices ?? this.correctAnswerIndices,
correctAnswerIndex: correctAnswerIndex ?? this.correctAnswerIndex,
consecutiveCorrect: consecutiveCorrect ?? this.consecutiveCorrect,
isKnown: isKnown ?? this.isKnown,
priorityPoints: priorityPoints ?? this.priorityPoints,
lastAttemptIndex: lastAttemptIndex ?? this.lastAttemptIndex,
totalCorrectAttempts: totalCorrectAttempts ?? this.totalCorrectAttempts,
totalAttempts: totalAttempts ?? this.totalAttempts,
);
}
/// Gets the correct answer indices, with backward compatibility.
List<int> get correctIndices {
if (correctAnswerIndices.isNotEmpty) {
return correctAnswerIndices;
}
// Backward compatibility
if (correctAnswerIndex != null) {
return [correctAnswerIndex!];
}
return [];
}
/// Checks if an answer index is correct.
bool isCorrectAnswer(int index) {
return correctIndices.contains(index);
}
/// Whether this question has multiple correct answers.
bool get hasMultipleCorrectAnswers => correctIndices.length > 1;
/// Validates that priorityPoints is non-negative.
Question withPriorityPoints(int points) {
return copyWith(priorityPoints: points < 0 ? 0 : points);
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Question &&
runtimeType == other.runtimeType &&
id == other.id &&
prompt == other.prompt &&
answers.toString() == other.answers.toString() &&
correctAnswerIndices.toString() == other.correctAnswerIndices.toString() &&
consecutiveCorrect == other.consecutiveCorrect &&
isKnown == other.isKnown &&
priorityPoints == other.priorityPoints &&
lastAttemptIndex == other.lastAttemptIndex &&
totalCorrectAttempts == other.totalCorrectAttempts &&
totalAttempts == other.totalAttempts;
@override
int get hashCode =>
id.hashCode ^
prompt.hashCode ^
answers.hashCode ^
correctAnswerIndices.hashCode ^
consecutiveCorrect.hashCode ^
isKnown.hashCode ^
priorityPoints.hashCode ^
lastAttemptIndex.hashCode ^
totalCorrectAttempts.hashCode ^
totalAttempts.hashCode;
}

Powered by TurnKey Linux.