Adds trivia to Veggie details screen ()

pull/64/head
Andrew Brogdon 6 years ago committed by GitHub
parent dcca6e44b2
commit 526ee0602a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -19,6 +19,35 @@ class LocalVeggieProvider {
vitaminCPercentage: 8,
servingSize: 'One large apple',
caloriesPerServing: 130,
trivia: [
Trivia(
'A peck of apples (that\'s a real unit of mesaurement!) weighs approximately how many pounds?',
[
'10 pounds',
'20 pounds',
'30 pounds',
],
0,
),
Trivia(
'Which of these is an actual variety of apples?',
[
'Dancing Turkey',
'Winter Banana',
'Red Sloth',
],
1,
),
Trivia(
'In Greek mythology, Paris gives a golden apple marked "To the Fairest" to a goddess. Which one?',
[
'Hera',
'Athena',
'Aphrodite',
],
2,
),
],
),
Veggie(
id: 2,
@ -32,6 +61,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 25,
servingSize: '1 medium artichoke',
caloriesPerServing: 60,
trivia: [],
),
Veggie(
id: 3,
@ -45,6 +75,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 15,
servingSize: '5 spears',
caloriesPerServing: 20,
trivia: [],
),
Veggie(
id: 4,
@ -58,6 +89,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 4,
servingSize: '1/5 medium avocado',
caloriesPerServing: 50,
trivia: [],
),
Veggie(
id: 5,
@ -71,6 +103,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 4,
servingSize: '1 cup',
caloriesPerServing: 62,
trivia: [],
),
Veggie(
id: 6,
@ -84,6 +117,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 80,
servingSize: '1/4 medium canteloupe',
caloriesPerServing: 50,
trivia: [],
),
Veggie(
id: 7,
@ -97,6 +131,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 100,
servingSize: '1/6 medium head',
caloriesPerServing: 25,
trivia: [],
),
Veggie(
id: 8,
@ -110,6 +145,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 2,
servingSize: '1/2 cup, chopped',
caloriesPerServing: 4,
trivia: [],
),
Veggie(
id: 9,
@ -123,6 +159,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 2,
servingSize: '1 large fig',
caloriesPerServing: 50,
trivia: [],
),
Veggie(
id: 10,
@ -136,6 +173,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 2,
servingSize: '3/4 cup',
caloriesPerServing: 90,
trivia: [],
),
Veggie(
id: 11,
@ -149,6 +187,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 190,
servingSize: '1 medium pepper',
caloriesPerServing: 25,
trivia: [],
),
Veggie(
id: 12,
@ -162,6 +201,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 100,
servingSize: '1 pepper',
caloriesPerServing: 20,
trivia: [],
),
Veggie(
id: 13,
@ -175,6 +215,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 134,
servingSize: '1 cup, chopped',
caloriesPerServing: 33,
trivia: [],
),
Veggie(
id: 14,
@ -188,6 +229,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 240,
servingSize: '2 medium kiwis',
caloriesPerServing: 90,
trivia: [],
),
Veggie(
id: 15,
@ -201,6 +243,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 40,
servingSize: '1 medium lemon',
caloriesPerServing: 15,
trivia: [],
),
Veggie(
id: 16,
@ -214,6 +257,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 35,
servingSize: '1 medium lime',
caloriesPerServing: 20,
trivia: [],
),
Veggie(
id: 17,
@ -227,6 +271,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 203,
servingSize: '1 fruit',
caloriesPerServing: 201,
trivia: [],
),
Veggie(
id: 18,
@ -240,6 +285,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 2,
servingSize: '5 medium \'shrooms',
caloriesPerServing: 20,
trivia: [],
),
Veggie(
id: 19,
@ -253,6 +299,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 15,
servingSize: '1 medium nectarine',
caloriesPerServing: 60,
trivia: [],
),
Veggie(
id: 20,
@ -266,6 +313,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 27,
servingSize: '1 fruit',
caloriesPerServing: 32,
trivia: [],
),
Veggie(
id: 21,
@ -279,6 +327,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 10,
servingSize: '2 medium plums',
caloriesPerServing: 70,
trivia: [],
),
Veggie(
id: 22,
@ -292,6 +341,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 45,
servingSize: '1 medium spud',
caloriesPerServing: 110,
trivia: [],
),
Veggie(
id: 23,
@ -305,6 +355,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 10,
servingSize: '2 cups shredded',
caloriesPerServing: 20,
trivia: [],
),
Veggie(
id: 24,
@ -318,6 +369,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 30,
servingSize: '7 radishes',
caloriesPerServing: 10,
trivia: [],
),
Veggie(
id: 25,
@ -331,6 +383,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 48,
servingSize: '1 cup diced butternut',
caloriesPerServing: 63,
trivia: [],
),
Veggie(
id: 26,
@ -345,6 +398,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 160,
servingSize: '8 medium strawberries',
caloriesPerServing: 50,
trivia: [],
),
Veggie(
id: 27,
@ -358,6 +412,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 181,
servingSize: '1 medium tangelo',
caloriesPerServing: 60,
trivia: [],
),
Veggie(
id: 28,
@ -371,6 +426,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 40,
servingSize: '1 medium tomato',
caloriesPerServing: 25,
trivia: [],
),
Veggie(
id: 29,
@ -384,6 +440,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 25,
servingSize: '2 cups diced',
caloriesPerServing: 80,
trivia: [],
),
Veggie(
id: 30,
@ -397,6 +454,7 @@ class LocalVeggieProvider {
vitaminCPercentage: 190,
servingSize: '1 medium pepper',
caloriesPerServing: 25,
trivia: [],
),
];
}

@ -33,6 +33,14 @@ enum Season {
autumn,
}
class Trivia {
final String question;
final List<String> answers;
final int correctAnswerIndex;
const Trivia(this.question, this.answers, this.correctAnswerIndex);
}
const Map<VeggieCategory, String> veggieCategoryNames = {
VeggieCategory.allium: 'Allium',
VeggieCategory.berry: 'Berry',
@ -67,6 +75,7 @@ class Veggie {
@required this.vitaminCPercentage,
@required this.servingSize,
@required this.caloriesPerServing,
@required this.trivia,
this.isFavorite = false,
});
@ -80,7 +89,7 @@ class Veggie {
final VeggieCategory category;
/// A short, snappy line, possibly with trivia.
/// A short, snappy line.
final String shortDescription;
/// A color value to use when constructing UI elements to match the image
@ -108,5 +117,8 @@ class Veggie {
/// as a favorite).
bool isFavorite;
/// A set of trivia questions and answers related to the veggie.
final List<Trivia> trivia;
String get categoryName => veggieCategoryNames[category];
}

@ -10,6 +10,7 @@ import 'package:veggieseasons/data/preferences.dart';
import 'package:veggieseasons/data/veggie.dart';
import 'package:veggieseasons/styles.dart';
import 'package:veggieseasons/widgets/close_button.dart';
import 'package:veggieseasons/widgets/trivia.dart';
class ServingInfoChart extends StatelessWidget {
const ServingInfoChart(this.veggie, this.prefs);
@ -211,20 +212,6 @@ class InfoView extends StatelessWidget {
}
}
class TriviaView extends StatelessWidget {
final int id;
const TriviaView(this.id);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(32.0),
child: Text('Trivia goes here.'),
);
}
}
class DetailsScreen extends StatefulWidget {
final int id;

@ -127,6 +127,30 @@ abstract class Styles {
fontWeight: FontWeight.normal,
);
static const triviaFinishedTitleText = TextStyle(
color: Color.fromRGBO(0, 0, 0, 0.9),
fontFamily: 'NotoSans',
fontSize: 32.0,
fontStyle: FontStyle.normal,
fontWeight: FontWeight.normal,
);
static const triviaFinishedText = TextStyle(
color: Color.fromRGBO(0, 0, 0, 0.9),
fontFamily: 'NotoSans',
fontSize: 16.0,
fontStyle: FontStyle.normal,
fontWeight: FontWeight.normal,
);
static const triviaFinishedBigText = TextStyle(
color: Color.fromRGBO(0, 0, 0, 0.9),
fontFamily: 'NotoSans',
fontSize: 48.0,
fontStyle: FontStyle.normal,
fontWeight: FontWeight.normal,
);
static const appBackground = Color(0xffd0d0d0);
static const scaffoldBackground = Color(0xfff0f0f0);

@ -0,0 +1,210 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
import 'package:scoped_model/scoped_model.dart';
import 'package:veggieseasons/data/app_state.dart';
import 'package:veggieseasons/data/veggie.dart';
import 'package:veggieseasons/styles.dart';
/// Presents a series of trivia questions about a particular widget, and tracks
/// the user's score.
class TriviaView extends StatefulWidget {
final int id;
const TriviaView(this.id);
@override
_TriviaViewState createState() => _TriviaViewState();
}
/// Possible states of the game.
enum PlayerStatus {
readyToAnswer,
wasCorrect,
wasIncorrect,
}
class _TriviaViewState extends State<TriviaView> {
/// Current app state. This is used to fetch veggie data.
AppState appState;
/// The veggie trivia about which to show.
Veggie veggie;
/// Index of the current trivia question.
int triviaIndex = 0;
/// User's score on the current veggie.
int score = 0;
/// Trivia question currently being displayed.
Trivia get currentTrivia => veggie.trivia[triviaIndex];
/// The current state of the game.
PlayerStatus status = PlayerStatus.readyToAnswer;
// Called at init and again if any dependencies (read: InheritedWidgets) on
// on which this object relies are changed.
@override
void didChangeDependencies() {
super.didChangeDependencies();
final newAppState =
ScopedModel.of<AppState>(context, rebuildOnChange: true);
setState(() {
appState = newAppState;
veggie = appState.getVeggie(widget.id);
});
}
// Called when the widget associated with this object is swapped out for a new
// one. If the new widget has a different Veggie ID value, the state object
// needs to do a little work to reset itself for the new Veggie.
@override
void didUpdateWidget(TriviaView oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.id != widget.id) {
setState(() {
veggie = appState.getVeggie(widget.id);
});
_resetGame();
}
}
@override
Widget build(BuildContext context) {
if (triviaIndex >= veggie.trivia.length) {
return _buildFinishedView();
} else if (status == PlayerStatus.readyToAnswer) {
return _buildQuestionView();
} else {
return _buildResultView();
}
}
void _resetGame() {
setState(() {
triviaIndex = 0;
score = 0;
status = PlayerStatus.readyToAnswer;
});
}
void _processAnswer(int answerIndex) {
setState(() {
if (answerIndex == currentTrivia.correctAnswerIndex) {
status = PlayerStatus.wasCorrect;
score++;
} else {
status = PlayerStatus.wasIncorrect;
}
});
}
// Widget shown when the game is over. It includes the score and a button to
// restart everything.
Widget _buildFinishedView() {
return Padding(
padding: const EdgeInsets.all(32.0),
child: Column(
children: [
Text(
'All done!',
style: Styles.triviaFinishedTitleText,
),
SizedBox(height: 16.0),
Text(
'You answered',
style: Styles.triviaFinishedText,
),
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
textBaseline: TextBaseline.alphabetic,
children: [
Text(
'$score',
style: Styles.triviaFinishedBigText,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
' of ',
style: Styles.triviaFinishedText,
),
),
Text(
'${veggie.trivia.length}',
style: Styles.triviaFinishedBigText,
),
],
),
Text(
'questions correctly!',
style: Styles.triviaFinishedText,
),
SizedBox(height: 16.0),
CupertinoButton(
child: Text('Try Again'),
onPressed: () => _resetGame(),
),
],
),
);
}
// Presents the current trivia's question and answer choices.
Widget _buildQuestionView() {
List<Widget> buttons = [];
for (int i = 0; i < currentTrivia.answers.length; i++) {
buttons.add(Padding(
padding: const EdgeInsets.all(8.0),
child: CupertinoButton(
color: CupertinoColors.activeBlue,
child: Text(
currentTrivia.answers[i],
textAlign: TextAlign.center,
),
onPressed: () => _processAnswer(i),
),
));
}
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
SizedBox(height: 16.0),
Text(currentTrivia.question),
SizedBox(height: 32.0),
]..addAll(buttons),
),
);
}
// Shows whether the last answer was right or wrong and prompts the user to
// continue through the game.
Widget _buildResultView() {
return Padding(
padding: const EdgeInsets.all(32.0),
child: Column(
children: [
Text(status == PlayerStatus.wasCorrect
? 'That\'s right!'
: 'Sorry, that wasn\'t the right answer.'),
SizedBox(height: 16.0),
CupertinoButton(
child: Text('Next Question'),
onPressed: () => setState(() {
triviaIndex++;
status = PlayerStatus.readyToAnswer;
}),
),
],
),
);
}
}
Loading…
Cancel
Save