changeset 4:de54f05adb78

add prototype game stats
author Dennis C. M. <dennis@denniscm.com>
date Thu, 22 Sep 2022 11:38:42 +0200
parents 4dbe0cd9dadc
children f31a61462e7a
files GeoQuiz.xcodeproj/project.pbxproj GeoQuiz/BuyLivesModal.swift GeoQuiz/BuyLivesModalView.swift GeoQuiz/ContentView.swift GeoQuiz/GameStatsModalView.swift GeoQuiz/GuessTheCapitalView.swift GeoQuiz/GuessTheFlagView.swift GeoQuiz/Helpers/GameAlertsModifier.swift GeoQuiz/Helpers/GameToolbar.swift GeoQuiz/Logic/Game.swift GeoQuiz/Logic/GuessTheCapital.swift GeoQuiz/Logic/GuessTheFlag.swift
diffstat 12 files changed, 174 insertions(+), 92 deletions(-) [+]
line wrap: on
line diff
--- a/GeoQuiz.xcodeproj/project.pbxproj	Thu Sep 22 10:42:39 2022 +0200
+++ b/GeoQuiz.xcodeproj/project.pbxproj	Thu Sep 22 11:38:42 2022 +0200
@@ -15,6 +15,7 @@
 		951B630228D1A87C004F9877 /* GuessTheCapitalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951B630128D1A87C004F9877 /* GuessTheCapitalView.swift */; };
 		951D197328D485E000671FAD /* CustomColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951D197228D485E000671FAD /* CustomColors.swift */; };
 		952E41E928DC521200198643 /* GameAlertsModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 952E41E828DC521200198643 /* GameAlertsModifier.swift */; };
+		952E41EB28DC612400198643 /* GameStatsModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 952E41EA28DC612400198643 /* GameStatsModalView.swift */; };
 		9539829328C51EDE00B70973 /* GeoQuizApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9539829228C51EDE00B70973 /* GeoQuizApp.swift */; };
 		9539829728C51EDF00B70973 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9539829628C51EDF00B70973 /* Assets.xcassets */; };
 		9539829A28C51EDF00B70973 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9539829928C51EDF00B70973 /* Preview Assets.xcassets */; };
@@ -23,7 +24,7 @@
 		955A658528D73EC600CEEC6D /* GuessTheCapital.swift in Sources */ = {isa = PBXBuildFile; fileRef = 955A658428D73EC600CEEC6D /* GuessTheCapital.swift */; };
 		955A65A928D7815E00CEEC6D /* Haptics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 955A65A828D7815E00CEEC6D /* Haptics.swift */; };
 		956273EA28CB2E98008DC094 /* FlagImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 956273E928CB2E98008DC094 /* FlagImage.swift */; };
-		959D257028C7251F00C55A5E /* BuyLivesModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 959D256F28C7251F00C55A5E /* BuyLivesModal.swift */; };
+		959D257028C7251F00C55A5E /* BuyLivesModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 959D256F28C7251F00C55A5E /* BuyLivesModalView.swift */; };
 		959D414928C87ED900BAAC14 /* CityPopulation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 959D414828C87ED900BAAC14 /* CityPopulation.swift */; };
 		959D415028C8834B00BAAC14 /* CountryFlags.json in Resources */ = {isa = PBXBuildFile; fileRef = 959D414A28C8834B00BAAC14 /* CountryFlags.json */; };
 		959D415128C8834B00BAAC14 /* CountryPopulation.json in Resources */ = {isa = PBXBuildFile; fileRef = 959D414B28C8834B00BAAC14 /* CountryPopulation.json */; };
@@ -54,6 +55,7 @@
 		951B630128D1A87C004F9877 /* GuessTheCapitalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuessTheCapitalView.swift; sourceTree = "<group>"; };
 		951D197228D485E000671FAD /* CustomColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomColors.swift; sourceTree = "<group>"; };
 		952E41E828DC521200198643 /* GameAlertsModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameAlertsModifier.swift; sourceTree = "<group>"; };
+		952E41EA28DC612400198643 /* GameStatsModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameStatsModalView.swift; sourceTree = "<group>"; };
 		9539828F28C51EDE00B70973 /* GeoQuiz.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GeoQuiz.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		9539829228C51EDE00B70973 /* GeoQuizApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoQuizApp.swift; sourceTree = "<group>"; };
 		9539829628C51EDF00B70973 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -63,7 +65,7 @@
 		955A658428D73EC600CEEC6D /* GuessTheCapital.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuessTheCapital.swift; sourceTree = "<group>"; };
 		955A65A828D7815E00CEEC6D /* Haptics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Haptics.swift; sourceTree = "<group>"; };
 		956273E928CB2E98008DC094 /* FlagImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlagImage.swift; sourceTree = "<group>"; };
-		959D256F28C7251F00C55A5E /* BuyLivesModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuyLivesModal.swift; sourceTree = "<group>"; };
+		959D256F28C7251F00C55A5E /* BuyLivesModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuyLivesModalView.swift; sourceTree = "<group>"; };
 		959D414828C87ED900BAAC14 /* CityPopulation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityPopulation.swift; sourceTree = "<group>"; };
 		959D414A28C8834B00BAAC14 /* CountryFlags.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = CountryFlags.json; sourceTree = "<group>"; };
 		959D414B28C8834B00BAAC14 /* CountryPopulation.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = CountryPopulation.json; sourceTree = "<group>"; };
@@ -158,7 +160,8 @@
 				95C4315528C64A8C00212131 /* ContentView.swift */,
 				95FA409928D9876B00129B60 /* GuessTheFlagView.swift */,
 				951B630128D1A87C004F9877 /* GuessTheCapitalView.swift */,
-				959D256F28C7251F00C55A5E /* BuyLivesModal.swift */,
+				959D256F28C7251F00C55A5E /* BuyLivesModalView.swift */,
+				952E41EA28DC612400198643 /* GameStatsModalView.swift */,
 				959D414728C87EA600BAAC14 /* Helpers */,
 				959D414528C87E8D00BAAC14 /* Models */,
 				95030CE728D1B60F001AA3A1 /* Logic */,
@@ -290,7 +293,7 @@
 				950C59FB28DB1F73007C8504 /* ProtocolTest.swift in Sources */,
 				959D414928C87ED900BAAC14 /* CityPopulation.swift in Sources */,
 				955A658528D73EC600CEEC6D /* GuessTheCapital.swift in Sources */,
-				959D257028C7251F00C55A5E /* BuyLivesModal.swift in Sources */,
+				959D257028C7251F00C55A5E /* BuyLivesModalView.swift in Sources */,
 				959D415928C8854800BAAC14 /* CountryCities.swift in Sources */,
 				950C59F528DADA10007C8504 /* Animation.swift in Sources */,
 				951B630228D1A87C004F9877 /* GuessTheCapitalView.swift in Sources */,
@@ -307,6 +310,7 @@
 				951D197328D485E000671FAD /* CustomColors.swift in Sources */,
 				95C430F928D0A8E500480D23 /* CustomGradients.swift in Sources */,
 				95FA409A28D9876B00129B60 /* GuessTheFlagView.swift in Sources */,
+				952E41EB28DC612400198643 /* GameStatsModalView.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
--- a/GeoQuiz/BuyLivesModal.swift	Thu Sep 22 10:42:39 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-//
-//  BuyLivesModal.swift
-//  GeoQuiz
-//
-//  Created by Dennis Concepción Martín on 6/9/22.
-//
-
-import SwiftUI
-
-struct BuyLivesModal: View {
-    @Environment(\.dismiss) var dismiss
-    
-    var body: some View {
-        ScrollView {
-            HStack {
-                Spacer()
-                Button {
-                    dismiss()
-                } label: {
-                    Image(systemName: "multiply")
-                        .imageScale(.large)
-                        
-                }
-            }
-            .padding([.trailing, .top])
-            
-            Section {
-                VStack(spacing: 20) {
-                    Text("Buy lifes")
-                        .font(.largeTitle)
-                        .fontWeight(.semibold)
-                    
-                    Text("Keep learning about countries.")
-                        .font(.headline)
-                        .foregroundColor(.secondary)
-                    
-                    Image("heart")
-                        .resizable()
-                        .scaledToFit()
-                        .frame(width: 180)
-                        .padding(40)
-                        .background(
-                            Color.blue.opacity(0.5)
-                                .cornerRadius(20)
-                                .shadow(radius: 20)
-                        )
-                        .padding()
-                    
-                    VStack(spacing: 30) {
-                        
-                    }
-                }
-                .padding()
-            } footer: {
-                Text("GeoQuiz is an indie app made by just one person. I'm glad that you are considering buying lifes to keep playing GeoQuiz.")
-                    .font(.callout)
-                    .foregroundColor(.secondary)
-                    .padding()
-            }
-        }
-    }
-}
-
-struct BuyLivesView_Previews: PreviewProvider {
-    static var previews: some View {
-        BuyLivesModal()
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GeoQuiz/BuyLivesModalView.swift	Thu Sep 22 11:38:42 2022 +0200
@@ -0,0 +1,68 @@
+//
+//  BuyLivesModalView.swift
+//  GeoQuiz
+//
+//  Created by Dennis Concepción Martín on 6/9/22.
+//
+
+import SwiftUI
+
+struct BuyLivesModalView: View {
+    @Environment(\.dismiss) var dismiss
+    
+    var body: some View {
+        ScrollView {
+            HStack {
+                Spacer()
+                Button {
+                    dismiss()
+                } label: {
+                    Image(systemName: "multiply")
+                        .imageScale(.large)
+                        
+                }
+            }
+            .padding([.trailing, .top])
+            
+            Section {
+                VStack(spacing: 20) {
+                    Text("Buy lifes")
+                        .font(.largeTitle)
+                        .fontWeight(.semibold)
+                    
+                    Text("Keep learning about countries.")
+                        .font(.headline)
+                        .foregroundColor(.secondary)
+                    
+                    Image("heart")
+                        .resizable()
+                        .scaledToFit()
+                        .frame(width: 180)
+                        .padding(40)
+                        .background(
+                            Color.blue.opacity(0.5)
+                                .cornerRadius(20)
+                                .shadow(radius: 20)
+                        )
+                        .padding()
+                    
+                    VStack(spacing: 30) {
+                        
+                    }
+                }
+                .padding()
+            } footer: {
+                Text("GeoQuiz is an indie app made by just one person. I'm glad that you are considering buying lifes to keep playing GeoQuiz.")
+                    .font(.callout)
+                    .foregroundColor(.secondary)
+                    .padding()
+            }
+        }
+    }
+}
+
+struct BuyLivesModalView_Previews: PreviewProvider {
+    static var previews: some View {
+        BuyLivesModalView()
+    }
+}
--- a/GeoQuiz/ContentView.swift	Thu Sep 22 10:42:39 2022 +0200
+++ b/GeoQuiz/ContentView.swift	Thu Sep 22 11:38:42 2022 +0200
@@ -71,7 +71,7 @@
                 }
             }
             .sheet(isPresented: $showingBuyLivesModal) {
-                BuyLivesModal()
+                BuyLivesModalView()
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GeoQuiz/GameStatsModalView.swift	Thu Sep 22 11:38:42 2022 +0200
@@ -0,0 +1,51 @@
+//
+//  GameStatsModalView.swift
+//  GeoQuiz
+//
+//  Created by Dennis Concepción Martín on 22/9/22.
+//
+
+import SwiftUI
+
+struct GameStatsModalView<T: Game>: View {
+    @ObservedObject var game: T
+    @Environment(\.dismiss) var dismiss
+    
+    var body: some View {
+        NavigationView {
+            List {
+                Section {
+                    ForEach(Array(game.correctAnswers.keys), id: \.self) { key in
+                        Text(key)
+                    }
+                } header: {
+                    Text("Correct answers")
+                }
+                
+                Section {
+                    ForEach(Array(game.wrongAnswers.keys), id: \.self) { key in
+                        Text(key)
+                    }
+                } header: {
+                    Text("Wrong answers")
+                }
+            }
+            .navigationTitle("Game stats")
+            .toolbar {
+                ToolbarItem(placement: .cancellationAction) {
+                    Button {
+                        dismiss()
+                    } label: {
+                        Label("Exit", systemImage: "multiply")
+                    }
+                }
+            }
+        }
+    }
+}
+
+struct GameStatsModalView_Previews: PreviewProvider {
+    static var previews: some View {
+        GameStatsModalView(game: GuessTheFlag())
+    }
+}
--- a/GeoQuiz/GuessTheCapitalView.swift	Thu Sep 22 10:42:39 2022 +0200
+++ b/GeoQuiz/GuessTheCapitalView.swift	Thu Sep 22 11:38:42 2022 +0200
@@ -72,7 +72,7 @@
         .navigationBarHidden(true)
         
 //        .sheet(isPresented: $game.showingBuyLivesView) {
-//            BuyLivesModal()
+//            BuyLivesModalView()
 //        }
 //
 //        .alert(game.alertTitle, isPresented: $game.showingNoLivesAlert) {
--- a/GeoQuiz/GuessTheFlagView.swift	Thu Sep 22 10:42:39 2022 +0200
+++ b/GeoQuiz/GuessTheFlagView.swift	Thu Sep 22 11:38:42 2022 +0200
@@ -18,7 +18,7 @@
             
             GeometryReader { geo in
                 VStack(spacing: 20) {
-                    GameToolbar(gameName: $gameName, game: game)
+                    GameToolbar(game: game)
                     
                     HStack {
                         VStack(alignment: .leading, spacing: 10) {
@@ -55,7 +55,11 @@
         .navigationBarHidden(true)
         .modifier(GameAlertsModifier(game: game, gameName: $gameName))
         .sheet(isPresented: $game.showingBuyLivesView) {
-            BuyLivesModal()
+            BuyLivesModalView()
+        }
+        
+        .sheet(isPresented: $game.showingGameStatsView) {
+            GameStatsModalView(game: game)
         }
     }
 }
--- a/GeoQuiz/Helpers/GameAlertsModifier.swift	Thu Sep 22 10:42:39 2022 +0200
+++ b/GeoQuiz/Helpers/GameAlertsModifier.swift	Thu Sep 22 11:38:42 2022 +0200
@@ -32,5 +32,12 @@
             } message: {
                 Text(game.alertMessage)
             }
+        
+            .alert("Are you sure?", isPresented: $game.showingExitGameAlert) {
+                Button("Exit", role: .destructive) { gameName = nil }
+                Button("Cancel", role: .cancel) { }
+            } message: {
+                Text("You'll loose the progress so far.")
+            }
     }
 }
--- a/GeoQuiz/Helpers/GameToolbar.swift	Thu Sep 22 10:42:39 2022 +0200
+++ b/GeoQuiz/Helpers/GameToolbar.swift	Thu Sep 22 11:38:42 2022 +0200
@@ -8,7 +8,6 @@
 import SwiftUI
 
 struct GameToolbar<T: Game>: View {
-    @Binding var gameName: GameName?
     @ObservedObject var game: T
     
     
@@ -16,7 +15,7 @@
         HStack(spacing: 0) {
             Group {
                 Button {
-                    gameName = nil
+                    game.showingExitGameAlert = true
                 } label: {
                     Image(systemName: "multiply")
                         .padding(10)
@@ -31,12 +30,16 @@
             .frame(maxWidth: .infinity, alignment: .leading)
             
             Group {
-                Text("\(game.userScore)")
-                    .padding()
-                    .background(
-                        Circle()
-                            .strokeBorder(lineWidth: 3)
-                    )
+                Button {
+                    game.showingGameStatsView = true
+                } label: {
+                    Text("\(game.userScore)")
+                        .padding()
+                        .background(
+                            Circle()
+                                .strokeBorder(lineWidth: 3)
+                        )
+                }
             }
             .foregroundColor(.white)
             .font(.title2)
@@ -74,10 +77,7 @@
             
             GeometryReader { geo in
                 VStack {
-                    GameToolbar(
-                        gameName: .constant(GameName.guessTheFlag),
-                        game: GuessTheFlag()
-                    )
+                    GameToolbar(game: GuessTheFlag())
                     
                     Spacer()
                 }
--- a/GeoQuiz/Logic/Game.swift	Thu Sep 22 10:42:39 2022 +0200
+++ b/GeoQuiz/Logic/Game.swift	Thu Sep 22 11:38:42 2022 +0200
@@ -22,6 +22,8 @@
     var userChoices: [String: T] { get set }
     var userScore: Int { get set }
     var userLives: Int { get set }
+    var correctAnswers: [String: T] { get set }
+    var wrongAnswers: [String: T] { get set }
     
     // Alerts
     var alertTitle: String { get set }
@@ -29,6 +31,7 @@
     var showingNoLivesAlert: Bool { get set }
     var showingEndGameAlert: Bool { get set }
     var showingWrongAnswerAlert: Bool { get set }
+    var showingExitGameAlert: Bool { get set }
     
     // Animations
     var scoreScaleAmount: Double { get set }
@@ -36,6 +39,7 @@
     
     // Modal views
     var showingBuyLivesView: Bool { get set }
+    var showingGameStatsView: Bool { get set }
 }
 
 extension Game {
@@ -91,24 +95,28 @@
         
         if correctAnswer == choice {
             hapticSuccess()
-            userScore += 1
-
+            
             withAnimation(.easeIn(duration: 0.5)) {
                 scoreScaleAmount += 1
+                userScore += 1
             }
             
+            correctAnswers[correctAnswer.key] = correctAnswer.value
             askQuestion()
         } else {
             hapticError()
-            userLives -= 1
+            
 
             withAnimation(.easeIn(duration: 0.5)) {
                 livesScaleAmount += 1
+                userLives -= 1
             }
 
             alertTitle = "Wrong!"
             alertMessage = "You have \(userLives) lives left"
             showingWrongAnswerAlert = true
+            
+            wrongAnswers[choice.key] = choice.value
         }
         
         DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [self] in
--- a/GeoQuiz/Logic/GuessTheCapital.swift	Thu Sep 22 10:42:39 2022 +0200
+++ b/GeoQuiz/Logic/GuessTheCapital.swift	Thu Sep 22 11:38:42 2022 +0200
@@ -7,7 +7,7 @@
 
 import Foundation
 
-class GuessTheCapital: ObservableObject {
+//class GuessTheCapital: ObservableObject {
     
 //    struct Country: Hashable {
 //        let capitalName: String
@@ -114,4 +114,8 @@
 //            self.showingWrongAnswerAlert = true
 //        }
 //    }
+//}
+
+class GuessTheCapital: ObservableObject {
+    
 }
--- a/GeoQuiz/Logic/GuessTheFlag.swift	Thu Sep 22 10:42:39 2022 +0200
+++ b/GeoQuiz/Logic/GuessTheFlag.swift	Thu Sep 22 11:38:42 2022 +0200
@@ -21,6 +21,8 @@
     @Published var userChoices = [String: String]()
     @Published var userScore = 0
     @Published var userLives = 3
+    @Published var correctAnswers = [String: String]()
+    @Published var wrongAnswers = [String: String]()
     
     // Alerts
     @Published var alertTitle = String()
@@ -28,6 +30,7 @@
     @Published var showingNoLivesAlert = false
     @Published var showingEndGameAlert = false
     @Published var showingWrongAnswerAlert = false
+    @Published var showingExitGameAlert = false
     
     // Animations
     @Published var scoreScaleAmount = 1.0
@@ -35,6 +38,7 @@
     
     // Modal views
     @Published var showingBuyLivesView = false
+    @Published var showingGameStatsView = false
     
     init() {
         let flags: CountryFlags = load("CountryFlags.json")