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 {