changeset 8:e09959b4e4a8

fix bugs
author Dennis C. M. <dennis@denniscm.com>
date Thu, 06 Oct 2022 11:14:34 +0200
parents d945e52b0704
children 3540c7efc216
files GeoQuiz/Assets.xcassets/Flags/np.imageset/np@1x.png GeoQuiz/Assets.xcassets/Flags/np.imageset/np@2x.png GeoQuiz/Assets.xcassets/heart.imageset/Contents.json GeoQuiz/Assets.xcassets/heart.imageset/heart.png GeoQuiz/Assets.xcassets/heart.imageset/heart@2x.png GeoQuiz/Assets.xcassets/heart.imageset/heart@3x.png GeoQuiz/ContentView.swift GeoQuiz/GuessTheCapitalView.swift GeoQuiz/GuessTheCountryView.swift GeoQuiz/GuessTheFlagView.swift GeoQuiz/GuessThePopulationView.swift GeoQuiz/Helpers/AnswerButton.swift GeoQuiz/Helpers/CityMap.swift GeoQuiz/Helpers/FlagImage.swift GeoQuiz/Helpers/GameAlertsModifier.swift GeoQuiz/Helpers/GameToolbar.swift GeoQuiz/Logic/CityGame.swift GeoQuiz/Logic/CountryGame.swift GeoQuiz/Logic/Game.swift GeoQuiz/ProfileModalView.swift README.md
diffstat 21 files changed, 172 insertions(+), 112 deletions(-) [+]
line wrap: on
line diff
Binary file GeoQuiz/Assets.xcassets/Flags/np.imageset/np@1x.png has changed
Binary file GeoQuiz/Assets.xcassets/Flags/np.imageset/np@2x.png has changed
--- a/GeoQuiz/Assets.xcassets/heart.imageset/Contents.json	Tue Oct 04 18:54:24 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-{
-  "images" : [
-    {
-      "filename" : "heart.png",
-      "idiom" : "universal",
-      "scale" : "1x"
-    },
-    {
-      "filename" : "heart@2x.png",
-      "idiom" : "universal",
-      "scale" : "2x"
-    },
-    {
-      "filename" : "heart@3x.png",
-      "idiom" : "universal",
-      "scale" : "3x"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}
Binary file GeoQuiz/Assets.xcassets/heart.imageset/heart.png has changed
Binary file GeoQuiz/Assets.xcassets/heart.imageset/heart@2x.png has changed
Binary file GeoQuiz/Assets.xcassets/heart.imageset/heart@3x.png has changed
--- a/GeoQuiz/ContentView.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/ContentView.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -36,7 +36,7 @@
                             level: "Level 3", symbol: "globe.americas.fill", name: "Guess the country"
                         )
                     }
-//
+
 //                    NavigationLink(
 //                        destination: Text("Guess the population"),
 //                        tag: GameName.guessThePopulation,
--- a/GeoQuiz/GuessTheCapitalView.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/GuessTheCapitalView.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -45,7 +45,9 @@
                     VStack {
                         ForEach(Array(game.userChoices.keys), id: \.self) { countryName in
                             Button {
-                                game.answer((key: countryName, value: game.data[countryName]!))
+                                game.answer((key: countryName, value: game.data[countryName]!)) {
+                                    game.selector()
+                                }
                             } label: {
                                 AnswerButton(
                                     optionName: game.data[countryName]!.capital,
--- a/GeoQuiz/GuessTheCountryView.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/GuessTheCountryView.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -21,7 +21,7 @@
                     
                     Spacer()
     
-                    CityMap(game: game)
+                    CityMap(game: game, geo: geo)
                     
                     Spacer()
                     
@@ -43,7 +43,9 @@
                     VStack {
                         ForEach(Array(game.userChoices.keys), id: \.self) { cityName in
                             Button {
-                                game.answer((key: cityName, value: game.data[cityName]!))
+                                game.answer((key: cityName, value: game.data[cityName]!)) {
+                                    game.selector()
+                                }
                             } label: {
                                 AnswerButton(
                                     optionName: game.data[cityName]!.country,
--- a/GeoQuiz/GuessTheFlagView.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/GuessTheFlagView.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -38,7 +38,9 @@
                     
                     ForEach(Array(game.userChoices.keys), id: \.self) { countryName in
                         Button {
-                            game.answer((key: countryName, value: game.data[countryName]!))
+                            game.answer((key: countryName, value: game.data[countryName]!)) {
+                                game.selector()
+                            }
                         } label: {
                             FlagImage(flagSymbol: game.data[countryName]!.flag, cornerRadius: 20)
                                 .shadow(radius: 10)
--- a/GeoQuiz/GuessThePopulationView.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/GuessThePopulationView.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -9,7 +9,7 @@
 
 struct GuessThePopulationView: View {
     var body: some View {
-        Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
+        Text("Hello, World!")
     }
 }
 
--- a/GeoQuiz/Helpers/AnswerButton.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/Helpers/AnswerButton.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -13,7 +13,7 @@
     
     var body: some View {
         RoundedRectangle(cornerRadius: 15)
-            .foregroundStyle(.regularMaterial)
+            .foregroundStyle(.ultraThickMaterial)
             .overlay(
                 Text(optionName)
                     .font(.title2.bold())
--- a/GeoQuiz/Helpers/CityMap.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/Helpers/CityMap.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -6,13 +6,17 @@
 //
 
 import SwiftUI
+import MapKit
 
 struct CityMap: View {
     @ObservedObject var game: CityGame
+    @State private var mapImage: UIImage? = nil
+    
+    let geo: GeometryProxy
     
     var body: some View {
-        Group {
-            if let mapImage = game.mapImage {
+        VStack {
+            if let mapImage = mapImage {
                 Image(uiImage: mapImage)
                     .resizable()
                     .scaledToFit()
@@ -22,11 +26,42 @@
                 ProgressView()
             }
         }
+        .onChange(of: game.correctAnswer.value) { _ in getMapImage() }
+        .onAppear(perform: getMapImage)
+    }
+    
+    private func getMapImage() {
+        let region = MKCoordinateRegion(
+            center: CLLocationCoordinate2D(
+                latitude: game.correctAnswer.value.lat,
+                longitude: game.correctAnswer.value.lon
+            ),
+            span: MKCoordinateSpan(
+                latitudeDelta: 0.1,
+                longitudeDelta: 0.1
+            )
+        )
+
+        // Map options
+        let mapOptions = MKMapSnapshotter.Options()
+        mapOptions.region = region
+        mapOptions.size = CGSize(width: geo.size.width * 0.8, height: geo.size.width * 0.8)
+        mapOptions.pointOfInterestFilter = .excludingAll
+
+        // Create the snapshotter and run it
+        let snapshotter = MKMapSnapshotter(options: mapOptions)
+        snapshotter.start { (snapshot, error) in
+            if let snapshot = snapshot {
+                self.mapImage = snapshot.image
+            } else if let error = error {
+                print(error.localizedDescription)
+            }
+        }
     }
 }
 
-struct CityMap_Previews: PreviewProvider {
-    static var previews: some View {
-        CityMap(game: CityGame())
-    }
-}
+//struct CityMap_Previews: PreviewProvider {
+//    static var previews: some View {
+//        CityMap(game: CityGame())
+//    }
+//}
--- a/GeoQuiz/Helpers/FlagImage.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/Helpers/FlagImage.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -24,7 +24,7 @@
 
 struct FlagImage_Previews: PreviewProvider {
     static var previews: some View {
-        FlagImage(flagSymbol: "es", cornerRadius: 20)
+        FlagImage(flagSymbol: "np", cornerRadius: 20)
             .frame(height: 130)
     }
 }
--- a/GeoQuiz/Helpers/GameAlertsModifier.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/Helpers/GameAlertsModifier.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -14,20 +14,32 @@
     func body(content: Content) -> some View {
         content
             .alert(game.alertTitle, isPresented: $game.showingWrongAnswerAlert) {
-                Button("Continue", role: .cancel) { game.askQuestion() }
+                Button("Continue", role: .cancel) {
+                    game.askQuestion {
+                        game.selector()
+                    }
+                }
             } message: {
                 Text(game.alertMessage)
             }
         
             .alert(game.alertTitle, isPresented: $game.showingGameOverAlert) {
-                Button("Try again") { game.reset() }
+                Button("Try again") {
+                    game.reset {
+                        game.selector()
+                    }
+                }
                 Button("Exit", role: .cancel) { dismiss()}
             } message: {
                 Text(game.alertMessage)
             }
             
             .alert(game.alertTitle, isPresented: $game.showingEndGameAlert) {
-                Button("Play again") { game.reset() }
+                Button("Play again") {
+                    game.reset() {
+                        game.selector()
+                    }
+                }
                 Button("Exit", role: .cancel) { dismiss() }
             } message: {
                 Text(game.alertMessage)
--- a/GeoQuiz/Helpers/GameToolbar.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/Helpers/GameToolbar.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -24,7 +24,7 @@
                         .padding(10)
                         .background(
                             Circle()
-                                .foregroundStyle(.regularMaterial)
+                                .foregroundStyle(.ultraThickMaterial)
                         )
                 }
             }
@@ -37,8 +37,14 @@
                     .foregroundColor(color)
                     .padding()
                     .background(
-                        Circle()
-                            .foregroundStyle(.regularMaterial)
+                        Group {
+                            if game.userScore < 1000 {
+                                Circle()
+                            } else {
+                                Capsule()
+                            }
+                        }
+                        .foregroundStyle(.ultraThickMaterial)
                     )
             }
             .font(.title2)
@@ -55,7 +61,7 @@
                 .padding(10)
                 .background(
                     Capsule()
-                        .foregroundStyle(.regularMaterial)
+                        .foregroundStyle(.ultraThickMaterial)
                 )
                 .scaleEffect(game.livesScaleAmount)
             }
--- a/GeoQuiz/Logic/CityGame.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/Logic/CityGame.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -8,7 +8,6 @@
 import Foundation
 import AVFAudio
 import SwiftUI
-import MapKit
 
 class CityGame: Game, ObservableObject {
     
@@ -18,12 +17,11 @@
     var data: [String: T]
     var dataAsked = [String: T]()
     
-    @Published var mapImage: UIImage? = nil
-    @Published var correctAnswer = (key: String(), value: T(country: String(), lat: Double(), lon: Double())) {
-        willSet {
-            getMapImage(lat: newValue.value.lat, lon: newValue.value.lon)
-        }
-    }
+    // Data
+    @Published var correctAnswer = (
+        key: String(),
+        value: T(country: String(), lat: Double(), lon: Double())
+    )
     
     // User
     @Published var userChoices = [String: T]()
@@ -50,38 +48,48 @@
     init() {
         let data: CityModel = load("cities.json")
         self.data = data.cities
-        askQuestion()
+        askQuestion {
+            selector()
+        }
     }
 }
 
 extension CityGame {
-    func getMapImage(lat: Double, lon: Double) {
-        let region = MKCoordinateRegion(
-            center: CLLocationCoordinate2D(
-                latitude: lat,
-                longitude: lon
-            ),
-            span: MKCoordinateSpan(
-                latitudeDelta: 1.0,
-                longitudeDelta: 1.0
-            )
-        )
-
-        // Map options
-        let mapOptions = MKMapSnapshotter.Options()
-        mapOptions.region = region
-        mapOptions.size = CGSize(width: 600, height: 600)
-        mapOptions.showsBuildings = true
-
-        // Create the snapshotter and run it
-        let snapshotter = MKMapSnapshotter(options: mapOptions)
-        snapshotter.start { (snapshot, error) in
-            if let snapshot = snapshot {
-                self.mapImage = snapshot.image
-            } else if let error = error {
-                print(error.localizedDescription)
+    func selector() {
+        
+        // Get random choices
+        var userChoices = [String: T]()
+        
+        while userChoices.count < 2 {
+            if let choice = data.randomElement() {
+                let userChoicesCountry = userChoices.map { $0.value.country }
+                
+                if !userChoicesCountry.contains(choice.value.country) {
+                    userChoices[choice.key] = choice.value
+                }
+            } else {
+                fatalError("Couldn't get a random value from data")
             }
         }
+        
+        // Get question asked (correct answer)
+        let userChoicesCountry = userChoices.map { $0.value.country }
+        let correctAnswer = data.first(where: {
+            !userChoices.keys.contains($0.key) &&           // Avoid duplicated cities
+            !dataAsked.keys.contains($0.key) &&             // Avoid cities already asked
+            !userChoicesCountry.contains($0.value.country)  // Avoid duplicated country names in userChoices
+        })
+        
+        // Unwrap optional
+        if let correctAnswer = correctAnswer {
+            userChoices[correctAnswer.key] = correctAnswer.value
+            dataAsked[correctAnswer.key] = correctAnswer.value
+            self.correctAnswer = correctAnswer
+        } else {
+            fatalError("Couldn't unwrap optional value")
+        }
+        
+        self.userChoices = userChoices
     }
 }
 
--- a/GeoQuiz/Logic/CountryGame.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/Logic/CountryGame.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -47,6 +47,41 @@
     init() {
         let data: CountryModel = load("countries.json")
         self.data = data.countries
-        askQuestion()
+        askQuestion {
+            selector()
+        }
     }
 }
+
+extension CountryGame {
+    func selector() {
+        
+        // Get random choices
+        var userChoices = [String: T]()
+        
+        while userChoices.count < 2 {
+            if let choice = data.randomElement() {
+                userChoices[choice.key] = choice.value
+            } else {
+                fatalError("Couldn't get a random value from data")
+            }
+        }
+        
+        // Get question asked (correct answer)
+        let correctAnswer = data.first(where: {
+            !userChoices.keys.contains($0.key) &&  // Avoid duplicated countries
+            !dataAsked.keys.contains($0.key)       // Avoid countries already asked
+        })
+        
+        // Unwrap optional
+        if let correctAnswer = correctAnswer {
+            userChoices[correctAnswer.key] = correctAnswer.value
+            dataAsked[correctAnswer.key] = correctAnswer.value
+            self.correctAnswer = correctAnswer
+        } else {
+            fatalError("Couldn't unwrap optional value")
+        }
+        
+        self.userChoices = userChoices
+    }
+}
--- a/GeoQuiz/Logic/Game.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/Logic/Game.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -40,6 +40,8 @@
     
     // Sound effects
     var player: AVAudioPlayer? { get set }
+    
+    func selector()
 }
 
 extension Game {
@@ -47,7 +49,7 @@
        dataAsked.count
     }
     
-    func askQuestion() {
+    func askQuestion(selector: () -> Void) {
         guard questionCounter < data.count else {
             alertTitle = "⭐️ Congratulations ⭐️"
             alertMessage = "You completed the game."
@@ -56,35 +58,10 @@
             return
         }
         
-        // Get random choices
-        var userChoices = [String: T]()
-        
-        while userChoices.count < 2 {
-            if let choice = data.randomElement() {
-                userChoices[choice.key] = choice.value
-            } else {
-                fatalError("Couldn't get a random value from data")
-            }
-        }
-        
-        // Get question asked (correct answer)
-        let correctAnswer = data.first(where: {
-            !userChoices.keys.contains($0.key) && !dataAsked.keys.contains($0.key)
-        })
-        
-        // Unwrap optional
-        if let correctAnswer = correctAnswer {
-            userChoices[correctAnswer.key] = correctAnswer.value
-            dataAsked[correctAnswer.key] = correctAnswer.value
-            self.correctAnswer = correctAnswer
-        } else {
-            fatalError("Couldn't unwrap optional value")
-        }
-        
-        self.userChoices = userChoices
+        selector()
     }
     
-    func answer(_ choice: (key: String, value: T)) {
+    func answer(_ choice: (key: String, value: T), selector: () -> Void) {
         if correctAnswer == choice {
             hapticSuccess()
             playSound("correctAnswer")
@@ -95,7 +72,9 @@
             }
             
             correctAnswers[correctAnswer.key] = correctAnswer.value
-            askQuestion()
+            askQuestion {
+                selector()
+            }
         } else {
             hapticError()
             playSound("wrongAnswer")
@@ -126,13 +105,15 @@
         }
     }
     
-    func reset() {
+    func reset(selector: () -> Void) {
         dataAsked = [String: T]()
         userScore = 0
         userLives = 3
         correctAnswers = [String: T]()
         wrongAnswers = [String: T]()
-        askQuestion()
+        askQuestion {
+            selector()
+        }
     }
     
     private func playSound(_ filename: String) {
--- a/GeoQuiz/ProfileModalView.swift	Tue Oct 04 18:54:24 2022 +0200
+++ b/GeoQuiz/ProfileModalView.swift	Thu Oct 06 11:14:34 2022 +0200
@@ -9,7 +9,7 @@
 
 struct ProfileModalView: View {
     var body: some View {
-        Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
+        Text("Hello, World!")
     }
 }
 
--- a/README.md	Tue Oct 04 18:54:24 2022 +0200
+++ b/README.md	Thu Oct 06 11:14:34 2022 +0200
@@ -1,1 +1,1 @@
-geoquiz-app
+# geoquiz-app