comparison GeoQuiz/Models/Controllers/GameProtocol+Extension.swift @ 26:425078c01194

refactor code
author Dennis C. M. <dennis@denniscm.com>
date Wed, 09 Nov 2022 10:30:01 +0100
parents GeoQuiz/Logic/GameProtocol+Extension.swift@e281791e0494
children 3f4b366d476d
comparison
equal deleted inserted replaced
25:b3df0f5dc750 26:425078c01194
1 //
2 // GameProtocol+Extension.swift
3 // GeoQuiz
4 //
5 // Created by Dennis Concepción Martín on 18/9/22.
6 //
7
8 import Foundation
9 import SwiftUI
10 import AVFAudio
11 import CoreData
12
13 @objc
14 public enum GameType: Int16, CaseIterable {
15 case guessTheFlag
16 case guessTheCapital
17 case guessTheCountry
18 case guessThePopulation
19 }
20
21 protocol Game: ObservableObject {
22
23 // Define generic type
24 associatedtype T: Equatable
25
26 // Game
27 var data: [String: T] { get set}
28 var dataAsked: [String: T] { get set }
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 }
35 var correctAnswers: [String: T] { get set }
36 var wrongAnswers: [String: T] { get set }
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 }
43 var showingExitGameAlert: Bool { get set }
44
45 // Animations
46 var scoreScaleAmount: Double { get set }
47 var livesScaleAmount: Double { get set }
48
49 // Sound effects
50 var player: AVAudioPlayer? { get set }
51
52 func selector()
53 }
54
55 extension Game {
56 var questionCounter: Int {
57 dataAsked.count
58 }
59
60 func askQuestion(selector: () -> Void) {
61 guard questionCounter < data.count else {
62 alertTitle = "⭐️ Congratulations ⭐️"
63 alertMessage = "You completed the game."
64 showingEndGameAlert = true
65
66 return
67 }
68
69 selector()
70 }
71
72 func answer(choice: (key: String, value: T), wrongMessage: String, selector: () -> Void) {
73 let haptics = HapticsController()
74
75 if correctAnswer == choice {
76 haptics.success()
77 playSound("correctAnswer")
78
79 withAnimation(.easeIn(duration: 0.5)) {
80 scoreScaleAmount += 1
81 userScore += 1
82 }
83
84 correctAnswers[correctAnswer.key] = correctAnswer.value
85 askQuestion {
86 selector()
87 }
88 } else {
89 haptics.error()
90 playSound("wrongAnswer")
91
92 withAnimation(.easeIn(duration: 0.5)) {
93 livesScaleAmount += 1
94 userLives -= 1
95 }
96
97 wrongAnswers[choice.key] = choice.value
98
99 if userLives == 0 {
100 alertTitle = "🤕 Game over 🤕"
101 alertMessage = "Get up and try again."
102 showingEndGameAlert = true
103 } else {
104 alertTitle = "🔴 Wrong 🔴"
105 alertMessage = "\(wrongMessage). You have \(userLives) lives left."
106 showingWrongAnswerAlert = true
107 }
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 }
117
118 func save(_ gameType: GameType, with moc: NSManagedObjectContext) {
119 let playedGame = PlayedGame(context: moc)
120
121 playedGame.type = gameType
122 playedGame.date = Date()
123 playedGame.score = Int32(userScore)
124 playedGame.correctAnswers = Array(correctAnswers.keys)
125 playedGame.wrongAnswers = Array(wrongAnswers.keys)
126
127 do {
128 try moc.save()
129 } catch {
130 print("Couldn't save object to CoreData: \(error)")
131 }
132 }
133
134 private func playSound(_ filename: String) {
135 let user = UserController()
136
137 if user.data.sound {
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 {
143 try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.ambient)
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 }
155 }
156 }
157 }