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