changeset 30:eb23effeede7

add DatasetView
author Dennis C. M. <dennis@denniscm.com>
date Thu, 10 Nov 2022 11:51:52 +0100
parents f5a2c2dab208
children 9d6dd0e59c22
files GeoQuiz.xcodeproj/project.pbxproj GeoQuiz/Controllers/CityGameController.swift GeoQuiz/Controllers/CountryGameController.swift GeoQuiz/DatasetView-ViewModel.swift GeoQuiz/DatasetView.swift GeoQuiz/Helpers/SettingsRow.swift GeoQuiz/SettingsModalView.swift
diffstat 7 files changed, 142 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/GeoQuiz.xcodeproj/project.pbxproj	Thu Nov 10 10:27:28 2022 +0100
+++ b/GeoQuiz.xcodeproj/project.pbxproj	Thu Nov 10 11:51:52 2022 +0100
@@ -243,6 +243,8 @@
 		951F0C0E291CFADF0026D5A2 /* CityGameController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951F0C04291CFADF0026D5A2 /* CityGameController.swift */; };
 		951F0C0F291CFADF0026D5A2 /* PersistenceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951F0C05291CFADF0026D5A2 /* PersistenceController.swift */; };
 		951F0C10291CFADF0026D5A2 /* UserController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951F0C06291CFADF0026D5A2 /* UserController.swift */; };
+		951F0C12291D05AE0026D5A2 /* DatasetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951F0C11291D05AE0026D5A2 /* DatasetView.swift */; };
+		951F0C14291D06810026D5A2 /* DatasetView-ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 951F0C13291D06810026D5A2 /* DatasetView-ViewModel.swift */; };
 		952E41E928DC521200198643 /* GameAlertsModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 952E41E828DC521200198643 /* GameAlertsModifier.swift */; };
 		952E41ED28DC658900198643 /* SettingsModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 952E41EC28DC658900198643 /* SettingsModalView.swift */; };
 		952E41F228DC6F6E00198643 /* correctAnswer.wav in Resources */ = {isa = PBXBuildFile; fileRef = 952E41F028DC6F6D00198643 /* correctAnswer.wav */; };
@@ -511,6 +513,8 @@
 		951F0C04291CFADF0026D5A2 /* CityGameController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CityGameController.swift; sourceTree = "<group>"; };
 		951F0C05291CFADF0026D5A2 /* PersistenceController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersistenceController.swift; sourceTree = "<group>"; };
 		951F0C06291CFADF0026D5A2 /* UserController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserController.swift; sourceTree = "<group>"; };
+		951F0C11291D05AE0026D5A2 /* DatasetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatasetView.swift; sourceTree = "<group>"; };
+		951F0C13291D06810026D5A2 /* DatasetView-ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DatasetView-ViewModel.swift"; sourceTree = "<group>"; };
 		952E41E828DC521200198643 /* GameAlertsModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameAlertsModifier.swift; sourceTree = "<group>"; };
 		952E41EC28DC658900198643 /* SettingsModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsModalView.swift; sourceTree = "<group>"; };
 		952E41F028DC6F6D00198643 /* correctAnswer.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = correctAnswer.wav; sourceTree = "<group>"; };
@@ -854,6 +858,8 @@
 				950C535228F2FA3300179C78 /* BuyPremiumModalView.swift */,
 				952E41EC28DC658900198643 /* SettingsModalView.swift */,
 				95D8BF31291BAF8C006FC606 /* SettingsModalView-ViewModel.swift */,
+				951F0C11291D05AE0026D5A2 /* DatasetView.swift */,
+				951F0C13291D06810026D5A2 /* DatasetView-ViewModel.swift */,
 				9590359428E098FF00B24560 /* ProfileModalView.swift */,
 				95C6457128FFC4DC000CD570 /* ProfileEditModalView.swift */,
 				957822462918EED3005F2D50 /* Helpers */,
@@ -1209,6 +1215,7 @@
 				9509A8E228E5A3D700CFCDBA /* GuessThePopulationView.swift in Sources */,
 				95C6459D290003E1000CD570 /* RecentGame.swift in Sources */,
 				95C6456E28FE8C04000CD570 /* UserProfile.swift in Sources */,
+				951F0C14291D06810026D5A2 /* DatasetView-ViewModel.swift in Sources */,
 				95C4315628C64A8C00212131 /* ContentView.swift in Sources */,
 				954AF4682905397A00180065 /* PlayedGamesList.swift in Sources */,
 				95C4315928C6500000212131 /* GameButton.swift in Sources */,
@@ -1235,6 +1242,7 @@
 				957822482918F445005F2D50 /* Extensions.swift in Sources */,
 				95C6457728FFC934000CD570 /* GeoQuiz.xcdatamodeld in Sources */,
 				9590359528E098FF00B24560 /* ProfileModalView.swift in Sources */,
+				951F0C12291D05AE0026D5A2 /* DatasetView.swift in Sources */,
 				95C6456C28FE87E4000CD570 /* UserDataModel.swift in Sources */,
 				951F0C0B291CFADF0026D5A2 /* HapticsController.swift in Sources */,
 				95C6459B28FFE5A3000CD570 /* PlayedGame+CoreDataProperties.swift in Sources */,
--- a/GeoQuiz/Controllers/CityGameController.swift	Thu Nov 10 10:27:28 2022 +0100
+++ b/GeoQuiz/Controllers/CityGameController.swift	Thu Nov 10 11:51:52 2022 +0100
@@ -45,7 +45,14 @@
     
     init() {
         let data: CityModel = Bundle.main.decode("cities.json")
-        self.data = data.cities
+        let shuffledCities = data.cities.shuffled().prefix(100)
+        
+        var cities = [String: T]()
+        for shuffledCity in shuffledCities {
+            cities[shuffledCity.key] = shuffledCity.value
+        }
+        
+        self.data = cities
         
         let user = UserController()
         userLives = user.data.numberOfLives
@@ -80,18 +87,24 @@
             }
         }
         
-        // Get question asked (correct answer)
+        // Get correct answer
+        let randomCityKeys = data.keys.shuffled()
         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
+        
+        let correctCityKey = randomCityKeys.first(where: {
+            !userChoices.keys.contains($0) &&                  // Avoid duplicated cities
+            !dataAsked.keys.contains($0) &&                    // Avoid cities already asked
+            !userChoicesCountry.contains(data[$0]!.country)    // Avoid duplicated country names in userChoices
         })
-        
+
         // Unwrap optional
-        if let correctAnswer = correctAnswer {
-            userChoices[correctAnswer.key] = correctAnswer.value
-            dataAsked[correctAnswer.key] = correctAnswer.value
+        if let correctCityKey = correctCityKey {
+            let correctCityValue = data[correctCityKey]!
+            
+            userChoices[correctCityKey] = correctCityValue
+            dataAsked[correctCityKey] = correctCityValue
+            
+            let correctAnswer = (key: correctCityKey, value: correctCityValue)
             self.correctAnswer = correctAnswer
         } else {
             fatalError("Couldn't unwrap optional value")
--- a/GeoQuiz/Controllers/CountryGameController.swift	Thu Nov 10 10:27:28 2022 +0100
+++ b/GeoQuiz/Controllers/CountryGameController.swift	Thu Nov 10 11:51:52 2022 +0100
@@ -45,7 +45,14 @@
     
     init() {
         let data: CountryModel = Bundle.main.decode("countries.json")
-        self.data = data.countries
+        let shuffledCountries = data.countries.shuffled().prefix(100)
+        
+        var countries = [String: T]()
+        for shuffledCountry in shuffledCountries {
+            countries[shuffledCountry.key] = shuffledCountry.value
+        }
+        
+        self.data = countries
         
         let user = UserController()
         userLives = user.data.numberOfLives
@@ -80,9 +87,8 @@
         let randomCountryKeys = data.keys.shuffled()
         
         let correctCountryKey = randomCountryKeys.first(where: {
-            !userChoices.keys.contains($0) &&
-            !dataAsked.keys.contains($0)
-            
+            !userChoices.keys.contains($0) &&   // Avoid duplicated countries
+            !dataAsked.keys.contains($0)        // Avoid countries already asked
         })
         
         // Unwrap correct answer
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GeoQuiz/DatasetView-ViewModel.swift	Thu Nov 10 11:51:52 2022 +0100
@@ -0,0 +1,23 @@
+//
+//  DatasetView-ViewModel.swift
+//  GeoQuiz
+//
+//  Created by Dennis Concepción Martín on 10/11/22.
+//
+
+import Foundation
+
+extension DatasetView {
+    class ViewModel {
+        let countries: Set<String>
+        let cities: Set<String>
+        
+        init() {
+            let countryData: CountryModel = Bundle.main.decode("countries.json")
+            let cityData: CityModel = Bundle.main.decode("cities.json")
+            
+            self.countries = Set(countryData.countries.keys)
+            self.cities = Set(cityData.cities.keys)
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GeoQuiz/DatasetView.swift	Thu Nov 10 11:51:52 2022 +0100
@@ -0,0 +1,31 @@
+//
+//  DatasetView.swift
+//  GeoQuiz
+//
+//  Created by Dennis Concepción Martín on 10/11/22.
+//
+
+import SwiftUI
+
+struct DatasetView: View {
+    let viewModel = ViewModel()
+    
+    var body: some View {
+        List {
+            Section {
+                Text("Countries: \(viewModel.countries.count.formattedWithSeparator)")
+                Text("Cities: \(viewModel.cities.count.formattedWithSeparator)")
+            }
+        }
+        .navigationTitle("Dataset")
+        .navigationBarTitleDisplayMode(.inline)
+    }
+}
+
+struct DatasetView_Previews: PreviewProvider {
+    static var previews: some View {
+        NavigationStack {
+            DatasetView()
+        }
+    }
+}
--- a/GeoQuiz/Helpers/SettingsRow.swift	Thu Nov 10 10:27:28 2022 +0100
+++ b/GeoQuiz/Helpers/SettingsRow.swift	Thu Nov 10 11:51:52 2022 +0100
@@ -11,25 +11,22 @@
     var color: Color
     var symbol: String
     var text: String
-    var url: URL
     
-    @Environment(\.openURL) var openURL
     
     var body: some View {
-        Link(destination: url) {
-            HStack(alignment: .center, spacing: 20) {
-                RoundedRectangle(cornerRadius: 5)
-                    .frame(width: 30, height: 30)
-                    .foregroundColor(color)
-                    .overlay(
-                        Image(systemName: symbol)
-                            .foregroundColor(.white)
-                    )
-                
-                Text(text)
-                    .foregroundColor(.primary)
-            }
+        HStack(alignment: .center, spacing: 20) {
+            RoundedRectangle(cornerRadius: 5)
+                .frame(width: 30, height: 30)
+                .foregroundColor(color)
+                .overlay(
+                    Image(systemName: symbol)
+                        .foregroundColor(.white)
+                )
+            
+            Text(text)
+                .foregroundColor(.primary)
         }
+        
     }
 }
 
@@ -38,8 +35,7 @@
         SettingsRow(
             color: .mayaBlue,
             symbol: "info",
-            text: "About",
-            url: URL(string: "https://dennistech.io")!
+            text: "About"
         )
     }
 }
--- a/GeoQuiz/SettingsModalView.swift	Thu Nov 10 10:27:28 2022 +0100
+++ b/GeoQuiz/SettingsModalView.swift	Thu Nov 10 11:51:52 2022 +0100
@@ -38,6 +38,11 @@
                 }
                 
                 Section {
+                    Toggle("Haptics", isOn: $userController.data.haptics)
+                    Toggle("Sound effects", isOn: $userController.data.sound)
+                }
+                
+                Section {
                     Picker("Flag shape", selection: $userController.data.guessTheFlagShape) {
                         ForEach(GuessTheFlagShape.allCases, id: \.self) { shape in
                             Text(shape.localizedName)
@@ -49,35 +54,37 @@
                 }
                 
                 Section {
-                    Toggle("Haptics", isOn: $userController.data.haptics)
-                    Toggle("Sound effects", isOn: $userController.data.sound)
-                } header: {
-                    Text("Effects")
-                }
-                
-                Section {
-                    SettingsRow(
-                        color: .mayaBlue,
-                        symbol: "person.fill",
-                        text: "About",
-                        url: URL(string: "https://dennistech.io")!
-                    )
+                    Link(destination: URL(string: "https://dennistech.io")!) {
+                        SettingsRow(
+                            color: .mayaBlue,
+                            symbol: "person.fill",
+                            text: "About"
+                        )
+                    }
+                    
+                    NavigationLink(destination: DatasetView()) {
+                        SettingsRow(
+                            color: .atomicTangerine,
+                            symbol: "square.stack.3d.up.fill",
+                            text: "Dataset"
+                        )
+                    }
                     
-                    SettingsRow(
-                        color: .atomicTangerine,
-                        symbol: "ant.fill",
-                        text: "Report bugs",
-                        url: URL(string: "mailto:dmartin@dennistech.io")!
-                    )
+                    Link(destination: URL(string: "mailto:dmartin@dennistech.io")!) {
+                        SettingsRow(
+                            color: .chinaPink,
+                            symbol: "ant.fill",
+                            text: "Report bugs"
+                        )
+                    }
                     
-                    SettingsRow(
-                        color: .blueBell,
-                        symbol: "message.fill",
-                        text: "Twitter",
-                        url: URL(string: "https://twitter.com/dennistech_")!
-                    )
-                } header: {
-                    Text("Get in touch")
+                    Link(destination: URL(string: "https://twitter.com/dennistech_")!) {
+                        SettingsRow(
+                            color: .blueBell,
+                            symbol: "message.fill",
+                            text: "Twitter"
+                        )
+                    }
                 } footer: {
                     HStack {
                         Spacer()