Created
October 5, 2022 13:42
-
-
Save nmbr73/468230447943e34dcfec01eafa95d362 to your computer and use it in GitHub Desktop.
This is the 'Education' part only - it's a mess already and so I did not go down the 'Entertainment' route.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ContentView.swift | |
// Edut(r)ainMe - Day35 | |
// | |
// Created by mbr73 on 04.10.22. | |
// | |
import SwiftUI | |
struct Question { | |
var multiplier: Int | |
var table: Int | |
var answer : Int? | |
init(_ multiplier: Int, _ table: Int) { | |
self.multiplier = multiplier | |
self.table = table | |
self.answer = nil | |
} | |
var hasCorrectAnswer: Bool { | |
answer ?? 0 == multiplier*table | |
} | |
var hasAnswer: Bool { | |
answer != nil | |
} | |
var string: String { | |
"\(multiplier) × \(table)" | |
} | |
} | |
extension Question: Hashable { | |
func hash(into hasher: inout Hasher) { | |
hasher.combine(multiplier) | |
hasher.combine(table) | |
} | |
} | |
struct ContentView: View { | |
enum GameState { | |
case showingSettings | |
case isRunning | |
case showingResults | |
} | |
var gameStateTitle: String { | |
switch gameState { | |
case .showingSettings: | |
return "Settings" | |
case .isRunning: | |
return "Question \(currentQuestion + 1)/\(numberOfQuestionsSelected)" | |
case .showingResults: | |
return "Results" | |
} | |
} | |
@State private var gameState = GameState.showingSettings | |
let numberOfQuestionsOptions = [5, 10, 20] | |
@State private var numberOfQuestionsSelected = 5 | |
@State private var multiplicationUpTo = 2 | |
@State private var currentQuestion = 0 | |
@State private var correctAnswers = 0 | |
@State private var questions = Array<Question>() | |
@FocusState private var answerTextFieldFocused: Bool | |
func buildQuestions(upTo: Int, number: Int) { | |
questions = Array<Question>() | |
for i in 1...12 { | |
for j in 1...upTo { | |
questions.append(Question(i,j)) | |
} | |
} | |
questions.shuffle() | |
questions.removeLast(upTo*12 - number) | |
} | |
var body: some View { | |
NavigationView { | |
List { | |
switch gameState { | |
case .showingSettings: | |
Section { | |
Stepper("Tables up to \(multiplicationUpTo)", value: $multiplicationUpTo, in: 2...12) | |
HStack { | |
Text("Questions") | |
Spacer() | |
Picker("Questions", selection: $numberOfQuestionsSelected) { | |
ForEach(numberOfQuestionsOptions, id: \.self) { | |
Text("\($0)") | |
} | |
} | |
.pickerStyle(.segmented) | |
} | |
} header: { | |
Text("Let /me EduT(r)ain U") | |
} footer: { | |
Text("Multiplication tables to practice are 1 up to \(multiplicationUpTo) by asking \(numberOfQuestionsSelected) questions.") | |
} | |
Section { | |
Button { | |
buildQuestions(upTo: multiplicationUpTo, number: numberOfQuestionsSelected) | |
currentQuestion = 0 | |
correctAnswers = 0 | |
answerTextFieldFocused = true | |
withAnimation { | |
gameState = .isRunning | |
} | |
} label: { | |
HStack { | |
Spacer() | |
Text("Go!") | |
Spacer() | |
} | |
} | |
} | |
case .isRunning: | |
Section { | |
HStack { | |
Text("What's") // Without the text the Spacer() causes an ugly gap!?!! | |
Spacer() | |
Text("\(questions[currentQuestion].string)") | |
.font(.largeTitle) | |
Spacer() | |
} | |
TextField("Type in your answer", value: $questions[currentQuestion].answer, format: .number) | |
.keyboardType(.decimalPad) | |
.focused($answerTextFieldFocused) | |
} header: { | |
Text("Question from table \(questions[currentQuestion].table):") | |
} footer: { | |
Text("Multiplication tables to practice are 1 up to \(multiplicationUpTo). This is a question from table \(questions[currentQuestion].table).") | |
} | |
case .showingResults: | |
Section { | |
ForEach(questions, id: \.self) { question in | |
HStack { | |
Text("\(question.string) = \(question.answer!)") | |
.foregroundColor(question.hasCorrectAnswer ? .black : .red ) | |
//.font(.monospaced(.body)()) | |
Spacer() | |
Text(question.hasCorrectAnswer ? "✅" : "❌") | |
} | |
} | |
} footer: { | |
Text("You had \(correctAnswers) out of \(numberOfQuestionsSelected) questions answered correctly.") | |
} | |
} | |
} | |
.navigationTitle(gameStateTitle) | |
.toolbar { | |
ToolbarItemGroup(placement: .navigationBarTrailing) { | |
if gameState == .isRunning { | |
Button("Abort") { | |
withAnimation { | |
gameState = .showingSettings | |
} | |
} | |
} else if gameState == .showingResults { | |
Button("Done") { | |
withAnimation { | |
gameState = .showingSettings | |
} | |
} | |
} | |
} | |
} | |
}.onSubmit { | |
if gameState == .isRunning { | |
let question = questions[currentQuestion] | |
if question.hasAnswer { | |
if question.hasCorrectAnswer | |
{ correctAnswers += 1 | |
} | |
if currentQuestion+1 < questions.count { | |
currentQuestion += 1 | |
} else { | |
withAnimation { | |
gameState = .showingResults | |
} | |
} | |
} | |
answerTextFieldFocused = true | |
} | |
} | |
} | |
} | |
struct ContentView_Previews: PreviewProvider { | |
static var previews: some View { | |
ContentView() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment