diff --git a/DouShouQi_App/DouShouQi_App.xcodeproj/project.pbxproj b/DouShouQi_App/DouShouQi_App.xcodeproj/project.pbxproj index ce28cde..f7a8c5a 100644 --- a/DouShouQi_App/DouShouQi_App.xcodeproj/project.pbxproj +++ b/DouShouQi_App/DouShouQi_App.xcodeproj/project.pbxproj @@ -69,6 +69,8 @@ ECF3FD242C25B83000F5E62B /* SelectFighterSound.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = ECF3FD232C25B83000F5E62B /* SelectFighterSound.mp3 */; }; ECF3FD262C25BDCF00F5E62B /* Start.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = ECF3FD252C25BDCF00F5E62B /* Start.mp3 */; }; ECF3FD282C25C83100F5E62B /* Fight.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = ECF3FD272C25C83100F5E62B /* Fight.mp3 */; }; + ECF3FD312C2722C600F5E62B /* CDHistoriqueExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECF3FD302C2722C600F5E62B /* CDHistoriqueExtension.swift */; }; + ECF3FD332C27238F00F5E62B /* Historique.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECF3FD322C27238F00F5E62B /* Historique.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -163,6 +165,8 @@ ECF3FD232C25B83000F5E62B /* SelectFighterSound.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = SelectFighterSound.mp3; path = ../../../../../../Downloads/SelectFighterSound.mp3; sourceTree = ""; }; ECF3FD252C25BDCF00F5E62B /* Start.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = Start.mp3; path = ../../../../../../Downloads/Start.mp3; sourceTree = ""; }; ECF3FD272C25C83100F5E62B /* Fight.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = Fight.mp3; path = ../../../../../../Downloads/Fight.mp3; sourceTree = ""; }; + ECF3FD302C2722C600F5E62B /* CDHistoriqueExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CDHistoriqueExtension.swift; sourceTree = ""; }; + ECF3FD322C27238F00F5E62B /* Historique.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Historique.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -450,6 +454,7 @@ isa = PBXGroup; children = ( EC62C53E2C1C6D1A0048CD0B /* CDPlayerExtension.swift */, + ECF3FD302C2722C600F5E62B /* CDHistoriqueExtension.swift */, ); path = Extensions; sourceTree = ""; @@ -469,6 +474,7 @@ children = ( ECE7770E2C1C6FB200D354B0 /* CoreData */, EC62C52C2C197ED10048CD0B /* Player.swift */, + ECF3FD322C27238F00F5E62B /* Historique.swift */, ); path = Class; sourceTree = ""; @@ -672,6 +678,7 @@ 649B59A42BF64574002BAE38 /* TitlePageFrame.swift in Sources */, EC0540C42C08A13E0032E9EF /* GameView.swift in Sources */, EC05BFC42C04C3C4000F7B19 /* SettingsView.swift in Sources */, + ECF3FD312C2722C600F5E62B /* CDHistoriqueExtension.swift in Sources */, EC62C53D2C1C69200048CD0B /* DouShouQi_App.xcdatamodeld in Sources */, EC62C50F2C05D06A0048CD0B /* AddPlayerView.swift in Sources */, EC62C53F2C1C6D1A0048CD0B /* CDPlayerExtension.swift in Sources */, @@ -684,6 +691,7 @@ ECE777142C2068F400D354B0 /* EditPlayerView.swift in Sources */, EC62C5382C1C64EE0048CD0B /* CoreManager.swift in Sources */, EC62C5252C0F68830048CD0B /* PlayerVM.swift in Sources */, + ECF3FD332C27238F00F5E62B /* Historique.swift in Sources */, EC62C51B2C09D1790048CD0B /* PlayerStatView.swift in Sources */, 649B59B22BF65392002BAE38 /* TextStyles.swift in Sources */, EC62C5092C0467240048CD0B /* SplashScreenView.swift in Sources */, diff --git a/DouShouQi_App/DouShouQi_App/AppModelAndExtension/Class/CoreData/CoreManager.swift b/DouShouQi_App/DouShouQi_App/AppModelAndExtension/Class/CoreData/CoreManager.swift index 5aa44cc..d4f3ecc 100644 --- a/DouShouQi_App/DouShouQi_App/AppModelAndExtension/Class/CoreData/CoreManager.swift +++ b/DouShouQi_App/DouShouQi_App/AppModelAndExtension/Class/CoreData/CoreManager.swift @@ -72,22 +72,83 @@ class CoreDataManager { print("Failed to fetch player for deletion: \(error)") } } - + func updatePlayer(playerVM: PlayerVM) { - let fetchRequest: NSFetchRequest = CDPlayer.fetchRequest() - fetchRequest.predicate = NSPredicate(format: "name == %@", playerVM.player.name) + let fetchRequest: NSFetchRequest = CDPlayer.fetchRequest() + fetchRequest.predicate = NSPredicate(format: "name == %@", playerVM.player.name) - do { - let players = try context.fetch(fetchRequest) - if let playerToUpdate = players.first { - playerToUpdate.name = playerVM.player.name - playerToUpdate.photo = playerVM.player.photo - saveContext() - } else { - print("Player not found") - } - } catch { - print("Failed to fetch player for update: \(error)") + do { + let players = try context.fetch(fetchRequest) + if let playerToUpdate = players.first { + playerToUpdate.name = playerVM.player.name + playerToUpdate.photo = playerVM.player.photo + saveContext() + } else { + print("Player not found") } + } catch { + print("Failed to fetch player for update: \(error)") } + } + + func saveHistorique(historique: Historique) { + let historiqueEntity = CDHistorique(context: context) + historiqueEntity.player1_name = historique.player1_name + historiqueEntity.player2_name = historique.player2_name + historiqueEntity.time = historique.time + historiqueEntity.result = historique.result + saveContext() + } + + func fetchHistoriques() -> [CDHistorique] { + let fetchRequest: NSFetchRequest = CDHistorique.fetchRequest() + do { + return try context.fetch(fetchRequest) + } catch { + print("Failed to fetch historiques: \(error)") + return [] + } + } + + func deleteHistorique(historique: Historique) { + let fetchRequest: NSFetchRequest = CDHistorique.fetchRequest() + fetchRequest.predicate = NSPredicate(format: "player1_name == %@ AND player2_name == %@ AND time == %@", historique.player1_name, historique.player2_name, historique.time) + + do { + let historiques = try context.fetch(fetchRequest) + if let historiqueToDelete = historiques.first { + context.delete(historiqueToDelete) + saveContext() + } else { + print("Historique not found") + } + } catch { + print("Failed to fetch historique for deletion: \(error)") + } + } + + func countVictories(for player: String) -> Int { + let fetchRequest: NSFetchRequest = CDHistorique.fetchRequest() + fetchRequest.predicate = NSPredicate(format: "(player1_name == %@ AND result == 'win') OR (player2_name == %@ AND result == 'lose')", player, player) + + do { + return try context.fetch(fetchRequest).count + } catch { + print("Failed to fetch victories for player: \(error)") + return 0 + } + } + + func countDefeats(for player: String) -> Int { + let fetchRequest: NSFetchRequest = CDHistorique.fetchRequest() + fetchRequest.predicate = NSPredicate(format: "(player1_name == %@ AND result == 'lose') OR (player2_name == %@ AND result == 'win')", player, player) + + do { + return try context.fetch(fetchRequest).count + } catch { + print("Failed to fetch defeats for player: \(error)") + return 0 + } + } + } diff --git a/DouShouQi_App/DouShouQi_App/AppModelAndExtension/Class/Historique.swift b/DouShouQi_App/DouShouQi_App/AppModelAndExtension/Class/Historique.swift new file mode 100644 index 0000000..13609f3 --- /dev/null +++ b/DouShouQi_App/DouShouQi_App/AppModelAndExtension/Class/Historique.swift @@ -0,0 +1,22 @@ +// +// Historique.swift +// DouShouQi_App +// +// Created by étudiant on 22/06/2024. +// + +import Foundation + +public class Historique{ + var player1_name: String + var player2_name: String + var time: String + var result: String + + init(player1_name: String, player2_name: String, time: String, result: String){ + self.player1_name = player1_name + self.player2_name = player2_name + self.result = result + self.time = time + } +} diff --git a/DouShouQi_App/DouShouQi_App/AppModelAndExtension/Extensions/CDHistoriqueExtension.swift b/DouShouQi_App/DouShouQi_App/AppModelAndExtension/Extensions/CDHistoriqueExtension.swift new file mode 100644 index 0000000..f402e24 --- /dev/null +++ b/DouShouQi_App/DouShouQi_App/AppModelAndExtension/Extensions/CDHistoriqueExtension.swift @@ -0,0 +1,28 @@ +// +// CDHistoriqueExtension.swift +// DouShouQi_App +// +// Created by étudiant on 22/06/2024. +// + +import Foundation +import CoreData + +extension CDHistorique { + func toModel() -> Historique { + return Historique( + player1_name: self.player1_name ?? "", + player2_name: self.player2_name ?? "", + time: self.time ?? "", + result: self.result ?? "" + ) + } + + convenience init(player1_name: String, player2_name: String, time: String, result: String, context: NSManagedObjectContext) { + self.init(context: context) + self.player1_name = player1_name + self.player2_name = player2_name + self.time = time + self.result = result + } +} diff --git a/DouShouQi_App/DouShouQi_App/Components/Game/GameResumeFrame.swift b/DouShouQi_App/DouShouQi_App/Components/Game/GameResumeFrame.swift index 56d49cc..9166b94 100644 --- a/DouShouQi_App/DouShouQi_App/Components/Game/GameResumeFrame.swift +++ b/DouShouQi_App/DouShouQi_App/Components/Game/GameResumeFrame.swift @@ -47,7 +47,7 @@ struct GameResumeFrame_Previews: PreviewProvider { static var previews: some View { do { let game = try Game(withRules: VerySimpleRules(), andPlayer1: HumanPlayer(withName: "Rémi", andId: .player1)!, andPlayer2: HumanPlayer(withName: "Nathan", andId: .player2)!) - return AnyView(GameResumeFrame(gameVM: GameVM(withGame: game))) + return AnyView(GameResumeFrame(gameVM: GameVM(withGame: game, time: "11:01"))) } catch { return AnyView(Text("Erreur lors de la création du jeu : \(error.localizedDescription)")) } diff --git a/DouShouQi_App/DouShouQi_App/Components/Player/PlayerStatView.swift b/DouShouQi_App/DouShouQi_App/Components/Player/PlayerStatView.swift index e3a542b..5cbed56 100644 --- a/DouShouQi_App/DouShouQi_App/Components/Player/PlayerStatView.swift +++ b/DouShouQi_App/DouShouQi_App/Components/Player/PlayerStatView.swift @@ -48,12 +48,12 @@ struct PlayerStatView: View { } HStack { Image(systemName: "chart.line.uptrend.xyaxis") - Text("Win Rate : \(String(format: "%.2f", Double(player.win) / Double(player.win + player.loose) * 100))%") + Text("Win Rate : \(String(format: "%.2f", (Double(player.win) / Double(player.win + player.loose)) * 100))%") .font(.title2) } HStack { Image(systemName: "list.number") - Text("Rank : 3") + Text("Rank : \(player.rank)") .font(.title2) } diff --git a/DouShouQi_App/DouShouQi_App/DouShouQi_App.xcdatamodeld/DouShouQi_App.xcdatamodel/contents b/DouShouQi_App/DouShouQi_App/DouShouQi_App.xcdatamodeld/DouShouQi_App.xcdatamodel/contents index 0d70375..4b87e60 100644 --- a/DouShouQi_App/DouShouQi_App/DouShouQi_App.xcdatamodeld/DouShouQi_App.xcdatamodel/contents +++ b/DouShouQi_App/DouShouQi_App/DouShouQi_App.xcdatamodeld/DouShouQi_App.xcdatamodel/contents @@ -1,5 +1,11 @@ + + + + + + diff --git a/DouShouQi_App/DouShouQi_App/ViewModel/Game/GameVM.swift b/DouShouQi_App/DouShouQi_App/ViewModel/Game/GameVM.swift index ed4cd14..eeadfe6 100644 --- a/DouShouQi_App/DouShouQi_App/ViewModel/Game/GameVM.swift +++ b/DouShouQi_App/DouShouQi_App/ViewModel/Game/GameVM.swift @@ -44,7 +44,7 @@ class GameVM: ObservableObject, Identifiable { } // Init - init(withGame game: Game) { + init(withGame game: Game, time: String) { self.game = game } } diff --git a/DouShouQi_App/DouShouQi_App/ViewModel/Game/HistoricVM.swift b/DouShouQi_App/DouShouQi_App/ViewModel/Game/HistoricVM.swift index 31a862a..34585c8 100644 --- a/DouShouQi_App/DouShouQi_App/ViewModel/Game/HistoricVM.swift +++ b/DouShouQi_App/DouShouQi_App/ViewModel/Game/HistoricVM.swift @@ -18,7 +18,7 @@ class HistoricVM: ObservableObject { gameVMs = [] do { let game = try Game(withRules: VerySimpleRules(), andPlayer1: HumanPlayer(withName: "Rémi", andId: .player1)!, andPlayer2: HumanPlayer(withName: "Nathan", andId: .player2)!) - gameVMs.append(GameVM(withGame: game)) + gameVMs.append(GameVM(withGame: game, time: "11:01")) } catch { // Do nothing } diff --git a/DouShouQi_App/DouShouQi_App/ViewModel/Players/PlayerVM.swift b/DouShouQi_App/DouShouQi_App/ViewModel/Players/PlayerVM.swift index 1d8f262..7fbbbc6 100644 --- a/DouShouQi_App/DouShouQi_App/ViewModel/Players/PlayerVM.swift +++ b/DouShouQi_App/DouShouQi_App/ViewModel/Players/PlayerVM.swift @@ -10,21 +10,30 @@ import DouShouQiModel public class PlayerVM: ObservableObject, Identifiable, Hashable{ public static func == (lhs: PlayerVM, rhs: PlayerVM) -> Bool { - return lhs.id == rhs.id - } - - public func hash(into hasher: inout Hasher) { - hasher.combine(id) - } + return lhs.id == rhs.id + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(id) + } @Published var player: Player - var loose: Int{ - return 0 + var loose: Int { + return CoreDataManager.shared.countDefeats(for: player.name) } - var win: Int{ - return 0 + + var win: Int { + return CoreDataManager.shared.countVictories(for: player.name) } - var rank: Int{ + + var rank: Int { + let allPlayers = CoreDataManager.shared.fetchPlayers() + let allPlayerVMs = allPlayers.map { PlayerVM(player: $0.toModel()) } + + let sortedPlayers = allPlayerVMs.sorted { $0.win > $1.win } + if let rankIndex = sortedPlayers.firstIndex(where: { $0.player.name == self.player.name }) { + return rankIndex + 1 + } return 0 } @@ -39,6 +48,6 @@ public class PlayerVM: ObservableObject, Identifiable, Hashable{ convenience init() { self.init(player: Player(name: "IA", photo: "")) } - + }