parent
82a0f40cc2
commit
29dbb7e53f
@ -0,0 +1,9 @@
|
||||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
/*.xcodeproj
|
||||
xcuserdata/
|
||||
DerivedData/
|
||||
.swiftpm/config/registries.json
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||
.netrc
|
@ -0,0 +1,29 @@
|
||||
// swift-tools-version: 5.7
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "GamePersistance",
|
||||
products: [
|
||||
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
||||
.library(
|
||||
name: "GamePersistance",
|
||||
targets: ["GamePersistance"]),
|
||||
],
|
||||
dependencies: [
|
||||
// Dependencies declare other packages that this package depends on.
|
||||
// .package(url: /* package url */, from: "1.0.0"),
|
||||
.package(path: "../Model"),
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
||||
.target(
|
||||
name: "GamePersistance",
|
||||
dependencies: ["Model"]),
|
||||
.testTarget(
|
||||
name: "GamePersistanceTests",
|
||||
dependencies: ["GamePersistance", "Model"]),
|
||||
]
|
||||
)
|
@ -0,0 +1,3 @@
|
||||
# GamePersistance
|
||||
|
||||
A description of this package.
|
@ -0,0 +1,29 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Louis Dufour on 16/02/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Model
|
||||
|
||||
extension Board: Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case nbRows, nbColumns, grid
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
let decodedGrid = try container.decode([[Cell]].self, forKey: .grid)
|
||||
|
||||
try self.init(withGrid: decodedGrid)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(nbRows, forKey: .nbRows)
|
||||
try container.encode(nbColumns, forKey: .nbColumns)
|
||||
try container.encode(grid, forKey: .grid)
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import Foundation
|
||||
import Model
|
||||
|
||||
extension Cell: Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case cellType, initialOwner, piece
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
let cellType = try container.decode(CellType.self, forKey: .cellType)
|
||||
let initialOwner = try container.decode(Owner.self, forKey: .initialOwner)
|
||||
let piece = try container.decodeIfPresent(Piece.self, forKey: .piece)
|
||||
|
||||
self.init(ofType: cellType, ownedBy: initialOwner, withPiece: piece)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(cellType, forKey: .cellType)
|
||||
try container.encode(initialOwner, forKey: .initialOwner)
|
||||
try container.encode(piece, forKey: .piece)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Louis Dufour on 16/02/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Model
|
||||
|
||||
extension Game: Codable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case rules, board, players, currentPlayerIndex
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(rules, forKey: .rules)
|
||||
try container.encode(board, forKey: .board)
|
||||
try container.encode(players.map { $0.toPlayerData() }, forKey: .players)
|
||||
try container.encode(currentPlayerIndex, forKey: .currentPlayerIndex)
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
// Décodez directement les propriétés.
|
||||
let rules = try container.decode(VerySimpleRules.self, forKey: .rules)
|
||||
let board = try container.decode(Board.self, forKey: .board)
|
||||
let currentPlayerIndex = try container.decode(Int.self, forKey: .currentPlayerIndex)
|
||||
|
||||
// Décodez chaque PlayerData en une instance de Player.
|
||||
let playersData = try container.decode([PlayerData].self, forKey: .players)
|
||||
let players = try playersData.map { data -> Player in
|
||||
switch data.type {
|
||||
case "HumanPlayer":
|
||||
guard let humanPlayer = HumanPlayer.from(data: data) else {
|
||||
throw DecodingError.dataCorruptedError(forKey: .players,
|
||||
in: container,
|
||||
debugDescription: "Cannot decode HumanPlayer")
|
||||
}
|
||||
return humanPlayer
|
||||
case "RandomPlayer":
|
||||
guard let randomPlayer = RandomPlayer.from(data: data) else {
|
||||
throw DecodingError.dataCorruptedError(forKey: .players,
|
||||
in: container,
|
||||
debugDescription: "Cannot decode RandomPlayer")
|
||||
}
|
||||
return randomPlayer
|
||||
default:
|
||||
throw DecodingError.dataCorruptedError(forKey: .players,
|
||||
in: container,
|
||||
debugDescription: "Unrecognized player type")
|
||||
}
|
||||
}
|
||||
|
||||
self.init(rules: rules, board: board, players: players, currentPlayerIndex: currentPlayerIndex)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Louis Dufour on 16/02/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Model
|
||||
|
||||
extension HumanPlayer {
|
||||
static func from(data: PlayerData) -> HumanPlayer? {
|
||||
guard data.type == "HumanPlayer" else { return nil }
|
||||
return HumanPlayer(name: data.name, id: data.id, inputMethod: { _ in nil })
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Louis Dufour on 16/02/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Model
|
||||
|
||||
extension Move: Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case owner, rowOrigin, columnOrigin, rowDestination, columnDestination
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
let owner = try container.decode(Owner.self, forKey: .owner)
|
||||
let rowOrigin = try container.decode(Int.self, forKey: .rowOrigin)
|
||||
let columnOrigin = try container.decode(Int.self, forKey: .columnOrigin)
|
||||
let rowDestination = try container.decode(Int.self, forKey: .rowDestination)
|
||||
let columnDestination = try container.decode(Int.self, forKey: .columnDestination)
|
||||
|
||||
self.init(owner: owner, rowOrigin: rowOrigin, columnOrigin: columnOrigin, rowDestination: rowDestination, columnDestination: columnDestination)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(owner, forKey: .owner)
|
||||
try container.encode(rowOrigin, forKey: .rowOrigin)
|
||||
try container.encode(columnOrigin, forKey: .columnOrigin)
|
||||
try container.encode(rowDestination, forKey: .rowDestination)
|
||||
try container.encode(columnDestination, forKey: .columnDestination)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Louis Dufour on 16/02/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Model
|
||||
|
||||
public struct PersistenceManager {
|
||||
|
||||
public static let shared = PersistenceManager()
|
||||
|
||||
private let fileName = "savedGame.json"
|
||||
|
||||
public func getDocumentsDirectory() -> URL {
|
||||
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
|
||||
return paths[0]
|
||||
}
|
||||
|
||||
public func saveGame(game: Game) {
|
||||
let encoder = JSONEncoder()
|
||||
encoder.outputFormatting = .prettyPrinted
|
||||
do {
|
||||
let data = try encoder.encode(game)
|
||||
let url = getDocumentsDirectory().appendingPathComponent(fileName)
|
||||
try data.write(to: url)
|
||||
print("Game saved successfully.")
|
||||
} catch {
|
||||
print("Failed to save game: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
public func loadGame() -> Game? {
|
||||
let url = getDocumentsDirectory().appendingPathComponent(fileName)
|
||||
do {
|
||||
let data = try Data(contentsOf: url)
|
||||
let decoder = JSONDecoder()
|
||||
let game = try decoder.decode(Game.self, from: data)
|
||||
print("Game loaded successfully.")
|
||||
return game
|
||||
} catch {
|
||||
print("Failed to load game: \(error)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Louis Dufour on 16/02/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Model
|
||||
extension Player {
|
||||
func toPlayerData() -> PlayerData {
|
||||
return PlayerData(id: self.id, name: self.name, type: type(of: self) == HumanPlayer.self ? "HumanPlayer" : "RandomPlayer")
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Louis Dufour on 16/02/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Model
|
||||
|
||||
struct PlayerData: Codable {
|
||||
let id: Owner
|
||||
let name: String
|
||||
let type: String // Pour distinguer HumanPlayer de RandomPlayer
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Louis Dufour on 16/02/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Model
|
||||
extension RandomPlayer {
|
||||
static func from(data: PlayerData) -> RandomPlayer? {
|
||||
guard data.type == "RandomPlayer" else { return nil }
|
||||
return RandomPlayer(withName: data.name, andId: data.id)
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Louis Dufour on 16/02/2024.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Model
|
||||
|
||||
extension VerySimpleRules: Codable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case occurences, historic
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(occurences, forKey: .occurences)
|
||||
try container.encode(historic, forKey: .historic)
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
let decodedOccurences = try container.decode(Dictionary<Board, Int>.self, forKey: .occurences)
|
||||
let decodedHistoric = try container.decode([Move].self, forKey: .historic)
|
||||
|
||||
self.init(occurences: decodedOccurences, historic: decodedHistoric)
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
import XCTest
|
||||
@testable import GamePersistance
|
||||
|
Loading…
Reference in new issue