Mercurial > public > geoquiz
annotate GeoQuiz/Models/Controllers/GameProtocol+Extension.swift @ 27:3f4b366d476d
add flag layout settings
author | Dennis C. M. <dennis@denniscm.com> |
---|---|
date | Thu, 10 Nov 2022 09:26:48 +0100 |
parents | 425078c01194 |
children |
rev | line source |
---|---|
3 | 1 // |
10
a793f33f05fb
refactor code and fix layout
Dennis C. M. <dennis@denniscm.com>
parents:
9
diff
changeset
|
2 // GameProtocol+Extension.swift |
3 | 3 // GeoQuiz |
4 // | |
5 // Created by Dennis Concepción Martín on 18/9/22. | |
6 // | |
7 | |
8 import Foundation | |
9 import SwiftUI | |
5 | 10 import AVFAudio |
15
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
11 import CoreData |
3 | 12 |
26 | 13 @objc |
14 public enum GameType: Int16, CaseIterable { | |
15 case guessTheFlag | |
16 case guessTheCapital | |
17 case guessTheCountry | |
18 case guessThePopulation | |
19 } | |
20 | |
3 | 21 protocol Game: ObservableObject { |
22 | |
23 // Define generic type | |
24 associatedtype T: Equatable | |
25 | |
26 // Game | |
27 var data: [String: T] { get set} | |
6 | 28 var dataAsked: [String: T] { get set } |
3 | 29 var correctAnswer: (key: String, value: T) { get set } |
30 | |
31 // User | |
32 var userChoices: [String: T] { get set } | |
33 var userScore: Int { get set } | |
34 var userLives: Int { get set } | |
4 | 35 var correctAnswers: [String: T] { get set } |
36 var wrongAnswers: [String: T] { get set } | |
3 | 37 |
38 // Alerts | |
39 var alertTitle: String { get set } | |
40 var alertMessage: String { get set } | |
41 var showingEndGameAlert: Bool { get set } | |
42 var showingWrongAnswerAlert: Bool { get set } | |
4 | 43 var showingExitGameAlert: Bool { get set } |
3 | 44 |
45 // Animations | |
46 var scoreScaleAmount: Double { get set } | |
47 var livesScaleAmount: Double { get set } | |
48 | |
5 | 49 // Sound effects |
50 var player: AVAudioPlayer? { get set } | |
8 | 51 |
52 func selector() | |
3 | 53 } |
54 | |
55 extension Game { | |
56 var questionCounter: Int { | |
57 dataAsked.count | |
58 } | |
59 | |
8 | 60 func askQuestion(selector: () -> Void) { |
3 | 61 guard questionCounter < data.count else { |
7 | 62 alertTitle = "⭐️ Congratulations ⭐️" |
63 alertMessage = "You completed the game." | |
3 | 64 showingEndGameAlert = true |
65 | |
66 return | |
67 } | |
68 | |
8 | 69 selector() |
3 | 70 } |
71 | |
26 | 72 func answer(choice: (key: String, value: T), wrongMessage: String, selector: () -> Void) { |
19 | 73 let haptics = HapticsController() |
9 | 74 |
3 | 75 if correctAnswer == choice { |
9 | 76 haptics.success() |
6 | 77 playSound("correctAnswer") |
4 | 78 |
3 | 79 withAnimation(.easeIn(duration: 0.5)) { |
80 scoreScaleAmount += 1 | |
4 | 81 userScore += 1 |
3 | 82 } |
83 | |
4 | 84 correctAnswers[correctAnswer.key] = correctAnswer.value |
8 | 85 askQuestion { |
86 selector() | |
87 } | |
3 | 88 } else { |
9 | 89 haptics.error() |
6 | 90 playSound("wrongAnswer") |
3 | 91 |
92 withAnimation(.easeIn(duration: 0.5)) { | |
93 livesScaleAmount += 1 | |
4 | 94 userLives -= 1 |
3 | 95 } |
4 | 96 |
97 wrongAnswers[choice.key] = choice.value | |
7 | 98 |
99 if userLives == 0 { | |
100 alertTitle = "🤕 Game over 🤕" | |
101 alertMessage = "Get up and try again." | |
15
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
102 showingEndGameAlert = true |
7 | 103 } else { |
104 alertTitle = "🔴 Wrong 🔴" | |
26 | 105 alertMessage = "\(wrongMessage). You have \(userLives) lives left." |
7 | 106 showingWrongAnswerAlert = true |
107 } | |
3 | 108 } |
109 | |
110 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [self] in | |
111 withAnimation(.easeIn(duration: 0.5)) { | |
112 scoreScaleAmount = 1 | |
113 livesScaleAmount = 1 | |
114 } | |
115 } | |
116 } | |
5 | 117 |
15
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
118 func save(_ gameType: GameType, with moc: NSManagedObjectContext) { |
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
119 let playedGame = PlayedGame(context: moc) |
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
120 |
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
121 playedGame.type = gameType |
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
122 playedGame.date = Date() |
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
123 playedGame.score = Int32(userScore) |
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
124 playedGame.correctAnswers = Array(correctAnswers.keys) |
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
125 playedGame.wrongAnswers = Array(wrongAnswers.keys) |
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
126 |
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
127 do { |
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
128 try moc.save() |
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
129 } catch { |
f1967f8cc67b
first iteration of core data
Dennis C. M. <dennis@denniscm.com>
parents:
14
diff
changeset
|
130 print("Couldn't save object to CoreData: \(error)") |
8 | 131 } |
7 | 132 } |
133 | |
6 | 134 private func playSound(_ filename: String) { |
19 | 135 let user = UserController() |
5 | 136 |
14 | 137 if user.data.sound { |
9 | 138 guard let soundFileURL = Bundle.main.url(forResource: filename, withExtension: "wav") else { |
139 fatalError("Sound file \(filename) couldn't be found") | |
140 } | |
141 | |
142 do { | |
27 | 143 try AVAudioSession.sharedInstance().setCategory(.ambient) |
9 | 144 try AVAudioSession.sharedInstance().setActive(true) |
145 } catch { | |
146 fatalError("Couldn't activate session") | |
147 } | |
148 | |
149 do { | |
150 player = try AVAudioPlayer(contentsOf: soundFileURL) | |
151 player?.play() | |
152 } catch { | |
153 fatalError("Couldn't play sound effect") | |
154 } | |
5 | 155 } |
156 } | |
3 | 157 } |