Mercurial > public > geoquiz
comparison GeoQuiz/Controllers/GameProtocol+Extension.swift @ 33:6d574bd1644f
refactor controllers
author | Dennis C. M. <dennis@denniscm.com> |
---|---|
date | Sat, 12 Nov 2022 11:18:30 +0100 |
parents | f5a2c2dab208 |
children | 6ec51a4ca897 |
comparison
equal
deleted
inserted
replaced
32:c62d6f92709d | 33:6d574bd1644f |
---|---|
16 case guessTheCapital | 16 case guessTheCapital |
17 case guessTheCountry | 17 case guessTheCountry |
18 case guessThePopulation | 18 case guessThePopulation |
19 } | 19 } |
20 | 20 |
21 protocol Game: ObservableObject { | 21 @MainActor protocol Game: ObservableObject { |
22 | 22 |
23 // Define generic type | 23 // Define generic type |
24 associatedtype T: Equatable | 24 associatedtype T: Equatable |
25 | 25 |
26 // Game | 26 // Game |
27 var data: [String: T] { get set} | 27 var data: [String: T] { get set} |
28 var dataAsked: [String: T] { get set } | 28 var dataAsked: [String: T] { get set } |
29 var correctAnswer: (key: String, value: T) { get set } | |
30 | 29 |
31 // User | |
32 var userChoices: [String: T] { get set } | 30 var userChoices: [String: T] { get set } |
33 var userScore: Int { get set } | 31 var userScore: Int { get set } |
34 var userLives: Int { get set } | 32 var userLives: Int { get set } |
33 | |
34 var correctAnswer: (key: String, value: T) { get set } | |
35 var correctAnswers: [String: T] { get set } | 35 var correctAnswers: [String: T] { get set } |
36 var wrongAnswers: [String: T] { get set } | 36 var wrongAnswers: [String: T] { get set } |
37 | 37 |
38 // Alerts | 38 // Alerts |
39 var alertTitle: String { get set } | 39 var alertTitle: String { get set } |
40 var alertMessage: String { get set } | 40 var alertMessage: String { get set } |
41 | |
41 var showingEndGameAlert: Bool { get set } | 42 var showingEndGameAlert: Bool { get set } |
42 var showingWrongAnswerAlert: Bool { get set } | 43 var showingWrongAnswerAlert: Bool { get set } |
43 var showingExitGameAlert: Bool { get set } | 44 var showingExitGameAlert: Bool { get set } |
44 | 45 |
45 // Animations | 46 // Animations |
46 var scoreScaleAmount: Double { get set } | 47 var scoreScaleAmount: Double { get set } |
47 var livesScaleAmount: Double { get set } | 48 var livesScaleAmount: Double { get set } |
48 | 49 |
49 // Sound effects | 50 // Sound effects |
50 var player: AVAudioPlayer? { get set } | 51 var player: AVAudioPlayer? { get set } |
51 | |
52 func selector() | |
53 } | 52 } |
54 | 53 |
55 extension Game { | 54 extension Game { |
56 var questionCounter: Int { | 55 var questionCounter: Int { |
57 dataAsked.count | 56 dataAsked.count |
58 } | 57 } |
59 | 58 |
60 func askQuestion(selector: () -> Void) { | 59 // MARK: - Ask new question |
60 func ask() { | |
61 guard questionCounter < data.count else { | 61 guard questionCounter < data.count else { |
62 alertTitle = "⭐️ Congratulations ⭐️" | 62 alertTitle = "⭐️ Congratulations ⭐️" |
63 alertMessage = "You completed the game." | 63 alertMessage = "You completed the game." |
64 showingEndGameAlert = true | 64 showingEndGameAlert = true |
65 | 65 |
66 return | 66 return |
67 } | 67 } |
68 | 68 |
69 selector() | 69 var userChoices = [String: T]() |
70 | |
71 while userChoices.count < 2 { | |
72 let choice = data.randomElement()! | |
73 userChoices[choice.key] = choice.value | |
74 } | |
75 | |
76 let correctKey = data.keys.shuffled().first(where: { | |
77 !userChoices.keys.contains($0) && // Avoid duplicated items | |
78 !dataAsked.keys.contains($0) // Avoid items already asked | |
79 })! | |
80 | |
81 let correctValue = data[correctKey]! | |
82 | |
83 userChoices[correctKey] = correctValue | |
84 dataAsked[correctKey] = correctValue | |
85 correctAnswer = (key: correctKey, value: correctValue) | |
86 self.userChoices = userChoices | |
70 } | 87 } |
71 | 88 |
72 func answer(choice: (key: String, value: T), wrongMessage: String, selector: () -> Void) { | 89 // MARK: - Answer question |
90 func answer(choice: (key: String, value: T), wrongMessage: String) { | |
73 let haptics = HapticsController() | 91 let haptics = HapticsController() |
74 | 92 |
75 if correctAnswer == choice { | 93 if correctAnswer == choice { |
76 haptics.success() | 94 haptics.success() |
77 playSound("correctAnswer") | 95 playSound("correctAnswer") |
80 scoreScaleAmount += 1 | 98 scoreScaleAmount += 1 |
81 userScore += 1 | 99 userScore += 1 |
82 } | 100 } |
83 | 101 |
84 correctAnswers[correctAnswer.key] = correctAnswer.value | 102 correctAnswers[correctAnswer.key] = correctAnswer.value |
85 askQuestion { | 103 ask() |
86 selector() | |
87 } | |
88 } else { | 104 } else { |
89 haptics.error() | 105 haptics.error() |
90 playSound("wrongAnswer") | 106 playSound("wrongAnswer") |
91 | 107 |
92 withAnimation(.easeIn(duration: 0.5)) { | 108 // withAnimation(.easeIn(duration: 0.5)) { |
93 livesScaleAmount += 1 | 109 // livesScaleAmount += 1 |
94 userLives -= 1 | 110 // userLives -= 1 |
95 } | 111 // } |
96 | 112 |
97 wrongAnswers[choice.key] = choice.value | 113 wrongAnswers[choice.key] = choice.value |
98 | 114 |
99 if userLives == 0 { | 115 if userLives == 0 { |
100 alertTitle = "🤕 Game over 🤕" | 116 alertTitle = "🤕 Game over 🤕" |
113 livesScaleAmount = 1 | 129 livesScaleAmount = 1 |
114 } | 130 } |
115 } | 131 } |
116 } | 132 } |
117 | 133 |
134 // MARK: - Save game | |
118 func save(_ gameType: GameType, with moc: NSManagedObjectContext) { | 135 func save(_ gameType: GameType, with moc: NSManagedObjectContext) { |
119 let playedGame = PlayedGame(context: moc) | 136 let playedGame = PlayedGame(context: moc) |
120 | 137 |
121 playedGame.type = gameType | 138 playedGame.type = gameType |
122 playedGame.date = Date() | 139 playedGame.date = Date() |
129 } catch { | 146 } catch { |
130 print("Couldn't save object to CoreData: \(error)") | 147 print("Couldn't save object to CoreData: \(error)") |
131 } | 148 } |
132 } | 149 } |
133 | 150 |
151 // MARK: - Play sound effect | |
134 private func playSound(_ filename: String) { | 152 private func playSound(_ filename: String) { |
135 let user = UserController() | 153 let user = UserController() |
136 | 154 |
137 if user.data.sound { | 155 if user.data.sound { |
138 guard let soundFileURL = Bundle.main.url(forResource: filename, withExtension: "wav") else { | 156 guard let soundFileURL = Bundle.main.url(forResource: filename, withExtension: "wav") else { |