Mercurial > public > geoquiz
changeset 34:6ec51a4ca897
fix crash when asking new questions
author | Dennis C. M. <dennis@denniscm.com> |
---|---|
date | Sat, 12 Nov 2022 14:23:05 +0100 |
parents | 6d574bd1644f |
children | 1b36c022f138 |
files | GeoQuiz.xcodeproj/project.pbxproj GeoQuiz.xcodeproj/xcshareddata/xcschemes/GeoQuiz.xcscheme GeoQuiz/Controllers/CityGameController.swift GeoQuiz/Controllers/CountryGameController.swift GeoQuiz/Controllers/GameProtocol+Extension.swift GeoQuizTests/GeoQuizTests.swift |
diffstat | 6 files changed, 233 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/GeoQuiz.xcodeproj/project.pbxproj Sat Nov 12 11:18:30 2022 +0100 +++ b/GeoQuiz.xcodeproj/project.pbxproj Sat Nov 12 14:23:05 2022 +0100 @@ -257,6 +257,7 @@ 957822482918F445005F2D50 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 957822472918F445005F2D50 /* Extensions.swift */; }; 9590359528E098FF00B24560 /* ProfileModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9590359428E098FF00B24560 /* ProfileModalView.swift */; }; 95919DBC28F08D0600F21F8F /* SettingsRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95919DBB28F08D0600F21F8F /* SettingsRow.swift */; }; + 959C3DB1291FC193003A3FD1 /* GeoQuizTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 959C3DB0291FC193003A3FD1 /* GeoQuizTests.swift */; }; 95A4F42B29043DC00018DFAC /* UserImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A4F42A29043DC00018DFAC /* UserImage.swift */; }; 95AF322A28DF293900023ACC /* GuessTheCountryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95AF322928DF293900023ACC /* GuessTheCountryView.swift */; }; 95BC392D28EC42570049AB49 /* CityMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BC392C28EC42570049AB49 /* CityMap.swift */; }; @@ -277,6 +278,16 @@ 95FA409A28D9876B00129B60 /* GuessTheFlagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FA409928D9876B00129B60 /* GuessTheFlagView.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 959C3DB2291FC193003A3FD1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9539828728C51EDE00B70973 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9539828E28C51EDE00B70973; + remoteInfo = GeoQuiz; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ 95030CE928D1BA4D001AA3A1 /* AnswerButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnswerButton.swift; sourceTree = "<group>"; }; 9509A8DD28E5A19A00CFCDBA /* countries.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = countries.json; sourceTree = "<group>"; }; @@ -529,6 +540,8 @@ 957822472918F445005F2D50 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; }; 9590359428E098FF00B24560 /* ProfileModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileModalView.swift; sourceTree = "<group>"; }; 95919DBB28F08D0600F21F8F /* SettingsRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsRow.swift; sourceTree = "<group>"; }; + 959C3DAE291FC193003A3FD1 /* GeoQuizTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GeoQuizTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 959C3DB0291FC193003A3FD1 /* GeoQuizTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoQuizTests.swift; sourceTree = "<group>"; }; 95A4F42A29043DC00018DFAC /* UserImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserImage.swift; sourceTree = "<group>"; }; 95AF322928DF293900023ACC /* GuessTheCountryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuessTheCountryView.swift; sourceTree = "<group>"; }; 95BC392C28EC42570049AB49 /* CityMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityMap.swift; sourceTree = "<group>"; }; @@ -560,6 +573,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 959C3DAB291FC193003A3FD1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -827,6 +847,7 @@ isa = PBXGroup; children = ( 9539829128C51EDE00B70973 /* GeoQuiz */, + 959C3DAF291FC193003A3FD1 /* GeoQuizTests */, 9539829028C51EDE00B70973 /* Products */, 950C535728F3178B00179C78 /* Frameworks */, ); @@ -836,6 +857,7 @@ isa = PBXGroup; children = ( 9539828F28C51EDE00B70973 /* GeoQuiz.app */, + 959C3DAE291FC193003A3FD1 /* GeoQuizTests.xctest */, ); name = Products; sourceTree = "<group>"; @@ -911,6 +933,14 @@ path = Helpers; sourceTree = "<group>"; }; + 959C3DAF291FC193003A3FD1 /* GeoQuizTests */ = { + isa = PBXGroup; + children = ( + 959C3DB0291FC193003A3FD1 /* GeoQuizTests.swift */, + ); + path = GeoQuizTests; + sourceTree = "<group>"; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -934,6 +964,24 @@ productReference = 9539828F28C51EDE00B70973 /* GeoQuiz.app */; productType = "com.apple.product-type.application"; }; + 959C3DAD291FC193003A3FD1 /* GeoQuizTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 959C3DB4291FC193003A3FD1 /* Build configuration list for PBXNativeTarget "GeoQuizTests" */; + buildPhases = ( + 959C3DAA291FC193003A3FD1 /* Sources */, + 959C3DAB291FC193003A3FD1 /* Frameworks */, + 959C3DAC291FC193003A3FD1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 959C3DB3291FC193003A3FD1 /* PBXTargetDependency */, + ); + name = GeoQuizTests; + productName = GeoQuizTests; + productReference = 959C3DAE291FC193003A3FD1 /* GeoQuizTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -941,12 +989,16 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1340; + LastSwiftUpdateCheck = 1410; LastUpgradeCheck = 1340; TargetAttributes = { 9539828E28C51EDE00B70973 = { CreatedOnToolsVersion = 13.4.1; }; + 959C3DAD291FC193003A3FD1 = { + CreatedOnToolsVersion = 14.1; + TestTargetID = 9539828E28C51EDE00B70973; + }; }; }; buildConfigurationList = 9539828A28C51EDE00B70973 /* Build configuration list for PBXProject "GeoQuiz" */; @@ -966,6 +1018,7 @@ projectRoot = ""; targets = ( 9539828E28C51EDE00B70973 /* GeoQuiz */, + 959C3DAD291FC193003A3FD1 /* GeoQuizTests */, ); }; /* End PBXProject section */ @@ -1201,6 +1254,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 959C3DAC291FC193003A3FD1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -1254,8 +1314,24 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 959C3DAA291FC193003A3FD1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 959C3DB1291FC193003A3FD1 /* GeoQuizTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 959C3DB3291FC193003A3FD1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9539828E28C51EDE00B70973 /* GeoQuiz */; + targetProxy = 959C3DB2291FC193003A3FD1 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ 9539829B28C51EDF00B70973 /* Debug */ = { isa = XCBuildConfiguration; @@ -1443,6 +1519,52 @@ }; name = Release; }; + 959C3DB5291FC193003A3FD1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = MTX83R5H8X; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.1; + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.dennistech.GeoQuizTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GeoQuiz.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/GeoQuiz"; + }; + name = Debug; + }; + 959C3DB6291FC193003A3FD1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = MTX83R5H8X; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.1; + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.dennistech.GeoQuizTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GeoQuiz.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/GeoQuiz"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -1464,6 +1586,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 959C3DB4291FC193003A3FD1 /* Build configuration list for PBXNativeTarget "GeoQuizTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 959C3DB5291FC193003A3FD1 /* Debug */, + 959C3DB6291FC193003A3FD1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */
--- a/GeoQuiz.xcodeproj/xcshareddata/xcschemes/GeoQuiz.xcscheme Sat Nov 12 11:18:30 2022 +0100 +++ b/GeoQuiz.xcodeproj/xcshareddata/xcschemes/GeoQuiz.xcscheme Sat Nov 12 14:23:05 2022 +0100 @@ -28,6 +28,17 @@ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> <Testables> + <TestableReference + skipped = "NO" + parallelizable = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "959C3DAD291FC193003A3FD1" + BuildableName = "GeoQuizTests.xctest" + BlueprintName = "GeoQuizTests" + ReferencedContainer = "container:GeoQuiz.xcodeproj"> + </BuildableReference> + </TestableReference> </Testables> </TestAction> <LaunchAction
--- a/GeoQuiz/Controllers/CityGameController.swift Sat Nov 12 11:18:30 2022 +0100 +++ b/GeoQuiz/Controllers/CityGameController.swift Sat Nov 12 14:23:05 2022 +0100 @@ -21,7 +21,7 @@ @Published var userScore = 0 @Published var userLives = 3 - @Published var correctAnswer = (key: String(), value: T(country: String(), lat: Double(), lon: Double())) + @Published var correctAnswer = (key: "", value: T(country: "", lat: Double(), lon: Double())) @Published var correctAnswers = [String: T]() @Published var wrongAnswers = [String: T]() @@ -45,7 +45,7 @@ let shuffledCities = data.cities.shuffled() var cities = [String: T]() - for _ in 1...10 { + for _ in 1...100 { let countryNames = cities.map { $0.value.country } let city = shuffledCities.first(where: { !countryNames.contains($0.value.country)
--- a/GeoQuiz/Controllers/CountryGameController.swift Sat Nov 12 11:18:30 2022 +0100 +++ b/GeoQuiz/Controllers/CountryGameController.swift Sat Nov 12 14:23:05 2022 +0100 @@ -8,29 +8,28 @@ import Foundation import AVFAudio -class CountryGameController: Game, ObservableObject { +@MainActor class CountryGameController: Game, ObservableObject { - // Define type of generics + // Define generic type typealias T = CountryModel.Country + // Game var data: [String: T] var dataAsked = [String: T]() - @Published var correctAnswer = ( - key: String(), - value: T(flag: String(), currency: String(), population: Int(), capital: String()) - ) - // User @Published var userChoices = [String: T]() @Published var userScore = 0 @Published var userLives = 3 + + @Published var correctAnswer = (key: "", value: T(flag: "", currency: "", population: Int(), capital: "")) @Published var correctAnswers = [String: T]() @Published var wrongAnswers = [String: T]() // Alerts @Published var alertTitle = String() @Published var alertMessage = String() + @Published var showingEndGameAlert = false @Published var showingWrongAnswerAlert = false @Published var showingExitGameAlert = false @@ -44,7 +43,7 @@ init() { let data: CountryModel = Bundle.main.decode("countries.json") - let shuffledCountries = data.countries.shuffled().prefix(5) + let shuffledCountries = data.countries.shuffled().prefix(100) var countries = [String: T]() for shuffledCountry in shuffledCountries { @@ -53,8 +52,6 @@ self.data = countries - print(countries) - let user = UserController() userLives = user.data.numberOfLives
--- a/GeoQuiz/Controllers/GameProtocol+Extension.swift Sat Nov 12 11:18:30 2022 +0100 +++ b/GeoQuiz/Controllers/GameProtocol+Extension.swift Sat Nov 12 14:23:05 2022 +0100 @@ -68,21 +68,16 @@ var userChoices = [String: T]() - while userChoices.count < 2 { + let correctAnswer = data.shuffled().first(where: { !dataAsked.keys.contains($0.key) })! + dataAsked[correctAnswer.key] = correctAnswer.value + userChoices[correctAnswer.key] = correctAnswer.value + + while userChoices.count < 3 { let choice = data.randomElement()! userChoices[choice.key] = choice.value } - let correctKey = data.keys.shuffled().first(where: { - !userChoices.keys.contains($0) && // Avoid duplicated items - !dataAsked.keys.contains($0) // Avoid items already asked - })! - - let correctValue = data[correctKey]! - - userChoices[correctKey] = correctValue - dataAsked[correctKey] = correctValue - correctAnswer = (key: correctKey, value: correctValue) + self.correctAnswer = correctAnswer self.userChoices = userChoices } @@ -105,10 +100,10 @@ haptics.error() playSound("wrongAnswer") -// withAnimation(.easeIn(duration: 0.5)) { -// livesScaleAmount += 1 -// userLives -= 1 -// } + withAnimation(.easeIn(duration: 0.5)) { + livesScaleAmount += 1 + userLives -= 1 + } wrongAnswers[choice.key] = choice.value
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GeoQuizTests/GeoQuizTests.swift Sat Nov 12 14:23:05 2022 +0100 @@ -0,0 +1,71 @@ +// +// GeoQuizTests.swift +// GeoQuizTests +// +// Created by Dennis Concepción Martín on 12/11/22. +// + +import XCTest +@testable import GeoQuiz + +final class GeoQuizTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + measure { + // Put the code you want to measure the time of here. + } + } +} + +final class CountryGameControllerTests: XCTestCase { + var game: CountryGameController! + + @MainActor override func setUpWithError() throws { + game = CountryGameController() + } + + @MainActor func testAsk() throws { + for _ in game.data { + game.ask() + XCTAssertEqual(game.userChoices.count, 3) + XCTAssertEqual(Set(game.userChoices.keys).count, 3) + } + + XCTAssertEqual(game.dataAsked.count, game.data.count) + } +} + +final class CityGameControllerTests: XCTestCase { + var game: CityGameController! + + @MainActor override func setUpWithError() throws { + game = CityGameController() + } + + @MainActor func testAsk() throws { + for _ in game.data { + game.ask() + XCTAssertEqual(game.userChoices.count, 3) + XCTAssertEqual(Set(game.userChoices.keys).count, 3) + } + + XCTAssertEqual(game.dataAsked.count, game.data.count) + } +}