Skip to content

Commit

Permalink
Allow swiping back to revisit previous answered questions
Browse files Browse the repository at this point in the history
Prerequisite for #64
  • Loading branch information
ttencate committed Jun 10, 2020
1 parent 4ac3714 commit 8fdba41
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 12 deletions.
26 changes: 20 additions & 6 deletions app/lib/model/user_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,25 +102,39 @@ class Quiz {
bool get isComplete => _currentQuestionIndex >= questionCount;

int get currentQuestionIndex => _currentQuestionIndex;

set currentQuestionIndex(int index) {
if (index < 0) index = 0;
if (index > questionCount) index = questionCount;
_currentQuestionIndex = index;
}

int get firstUnansweredQuestionIndex {
final index = questions.indexWhere((question) => !question.isAnswered);
return index >= 0 ? index : questionCount;
}

int get currentQuestionNumber => _currentQuestionIndex + 1;

Question get currentQuestion => isComplete ? null : questions[_currentQuestionIndex];

void proceedToNextQuestion() {
assert(!isComplete);
_currentQuestionIndex++;
while (currentQuestion?.isAnswered ?? false) {
_currentQuestionIndex++;
}
}

int get correctAnswerCount => questions.where((question) => question.isCorrect == true).length;

int get scorePercent => correctAnswerCount * 100 ~/ questionCount;

Set<Species> get fullyCorrectSpecies =>
questions
.map((question) => question.correctAnswer)
.toSet()
..removeAll(incorrectQuestions.map((question) => question.correctAnswer))
..removeAll(incorrectQuestions.map((question) => question.givenAnswer));
questions
.map((question) => question.correctAnswer)
.toSet()
..removeAll(incorrectQuestions.map((question) => question.correctAnswer))
..removeAll(incorrectQuestions.map((question) => question.givenAnswer));

List<Question> get correctQuestions => questions.where((question) => question.isCorrect == true).toList();
List<Question> get incorrectQuestions => questions.where((question) => question.isCorrect == false).toList();
Expand Down
18 changes: 12 additions & 6 deletions app/lib/screens/quiz_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ class _QuizPageState extends State<QuizPage> {
body: PageView.builder(
controller: _pageController,
scrollDirection: Axis.horizontal,
physics: NeverScrollableScrollPhysics(),
physics: PageScrollPhysics(),
onPageChanged: _showQuestion,
// We don't pass `itemCount` because if we set it to `quiz.questionCount + 1`,
// the `PageView` sometimes creates pages before they are visible, causing
// https://github.com/ttencate/papageno/issues/58.
Expand All @@ -78,21 +79,22 @@ class _QuizPageState extends State<QuizPage> {
// (shouldn't keys prevent this?).
itemCount: null,
itemBuilder: (BuildContext context, int index) {
if (index > quiz.firstUnansweredQuestionIndex) {
return null;
}
if (index < quiz.questionCount) {
return QuestionScreen(
key: ObjectKey(quiz.questions[index]),
question: quiz.questions[index],
onAnswer: _storeAnswer,
onProceed: _showNextQuestion,
);
} else if (index == quiz.questionCount) {
} else {
return QuizResult(
quiz: quiz,
onRetry: _restart,
onBack: _back,
);
} else {
return null;
}
},
),
Expand All @@ -118,6 +120,10 @@ class _QuizPageState extends State<QuizPage> {
}
}

void _showQuestion(int index) {
setState(() { quiz.currentQuestionIndex = index; });
}

void _restart() {
Navigator.of(context).pop(QuizPageResult(restart: true));
}
Expand Down Expand Up @@ -175,7 +181,7 @@ class _QuestionScreenState extends State<QuestionScreen> {
@override
void initState() {
super.initState();
_playerController = PlayerController(playing: true, looping: true);
_playerController = PlayerController(playing: !_question.isAnswered, looping: !_question.isAnswered);
}

@override
Expand Down Expand Up @@ -217,7 +223,7 @@ class _QuestionScreenState extends State<QuestionScreen> {
fit: StackFit.expand,
alignment: Alignment.center,
children: <Widget>[
if (_image == null) Placeholder(),
if (_image == null) Container(),
if (_image != null) material.Image(
image: AssetImage(join('assets', 'images', _image.fileName)),
fit: BoxFit.cover,
Expand Down
3 changes: 3 additions & 0 deletions app/lib/widgets/revealing_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ class _RevealingImageState extends State<RevealingImage> with SingleTickerProvid
animation = Tween<double>(begin: 0.0, end: 1.0).animate(controller)
// TODO figure out why we need this -- CustomClipper.reclip is tied to this animation so it should be updating outside the build cycle, right?
..addListener(() { setState(() {}); });
if (widget.revealed) {
controller.forward(from: 1.0); // Skip to end.
}
}

@override
Expand Down

0 comments on commit 8fdba41

Please sign in to comment.