You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
7.8 KiB
217 lines
7.8 KiB
//
|
|
// FederalPlayer.swift
|
|
// PadelClub
|
|
//
|
|
// Created by Razmig Sarkissian on 01/03/2024.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
class FederalPlayer: Decodable {
|
|
var rank: Int
|
|
var lastName: String
|
|
var firstName: String
|
|
var country: String
|
|
var license: String
|
|
var points: Double?
|
|
var assimilation: String
|
|
var tournamentCount: Int?
|
|
var ligue: String
|
|
var clubCode: String
|
|
var club: String
|
|
var isMale: Bool
|
|
|
|
|
|
// MARK: - Nationnalite
|
|
struct Nationnalite: Hashable, Codable {
|
|
let code, codeFov: String
|
|
}
|
|
|
|
required init(from decoder: Decoder) throws {
|
|
enum CodingKeys: String, CodingKey {
|
|
case nom
|
|
case prenom
|
|
case licence
|
|
case meilleurClassement
|
|
case nationnalite
|
|
case anneeNaissance
|
|
case codeClub
|
|
case nomClub
|
|
case nomLigue
|
|
case rang
|
|
case progression
|
|
case points
|
|
case nombreDeTournois
|
|
case assimile
|
|
}
|
|
|
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
|
|
isMale = (decoder.userInfo[.maleData] as? Bool) == true
|
|
|
|
let _lastName = try container.decode(String.self, forKey: .nom)
|
|
let _firstName = try container.decode(String.self, forKey: .prenom)
|
|
lastName = _lastName
|
|
firstName = _firstName
|
|
if let lic = try? container.decodeIfPresent(Int.self, forKey: .licence) {
|
|
license = String(lic)
|
|
} else {
|
|
license = ""
|
|
}
|
|
|
|
let nationnalite = try container.decode(Nationnalite.self, forKey: .nationnalite)
|
|
country = nationnalite.code
|
|
//meilleurClassement = try container.decode(Int.self, forKey: .meilleurClassement)
|
|
//anneeNaissance = try container.decode(Int.self, forKey: .anneeNaissance)
|
|
clubCode = try container.decode(String.self, forKey: .codeClub)
|
|
club = try container.decode(String.self, forKey: .nomClub)
|
|
ligue = try container.decode(String.self, forKey: .nomLigue)
|
|
rank = try container.decode(Int.self, forKey: .rang)
|
|
//progression = try? container.decodeIfPresent(Int.self, forKey: .progression)
|
|
let pointsAsInt = try? container.decodeIfPresent(Int.self, forKey: .points)
|
|
if let pointsAsInt {
|
|
points = Double(pointsAsInt)
|
|
} else {
|
|
points = nil
|
|
}
|
|
tournamentCount = try? container.decodeIfPresent(Int.self, forKey: .nombreDeTournois)
|
|
let assimile = try container.decode(Bool.self, forKey: .assimile)
|
|
assimilation = assimile ? "Oui" : "Non"
|
|
|
|
}
|
|
|
|
func exportToCSV() -> String {
|
|
let pointsString = points != nil ? String(Int(points!)) : ""
|
|
let tournamentCountString = tournamentCount != nil ? String(tournamentCount!) : ""
|
|
let strippedLicense = license.strippedLicense ?? ""
|
|
let line = ";\(rank);\(lastName);\(firstName);\(country);\(strippedLicense);\(pointsString);\(assimilation);\(tournamentCountString);\(ligue);\(formatNumbers(clubCode));\(club);"
|
|
return line
|
|
}
|
|
|
|
func formatNumbers(_ input: String) -> String {
|
|
// Insert spaces at appropriate positions
|
|
let formattedString = insertSeparator(input, separator: " ", every: [2, 4])
|
|
return formattedString
|
|
}
|
|
|
|
func insertSeparator(_ input: String, separator: String, every positions: [Int]) -> String {
|
|
var modifiedString = input
|
|
// Adjust for the index shift caused by inserting characters
|
|
var offset = 0
|
|
// Insert separator at specified positions
|
|
for position in positions {
|
|
let index = modifiedString.index(modifiedString.startIndex, offsetBy: position + offset)
|
|
modifiedString.insert(contentsOf: separator, at: index)
|
|
// Increase offset to adjust for the inserted character
|
|
offset += separator.count
|
|
}
|
|
return modifiedString
|
|
}
|
|
|
|
/*
|
|
;RANG;NOM;PRENOM;Nationalité;N° Licence;POINTS;Assimilation;NB. DE TOURNOIS JOUES;LIGUE;CODE CLUB;CLUB;
|
|
*/
|
|
|
|
var isManPlayer: Bool {
|
|
isMale
|
|
}
|
|
|
|
var isAssimilated: Bool {
|
|
assimilation == "Oui"
|
|
}
|
|
|
|
var currentRank: Int {
|
|
rank
|
|
}
|
|
|
|
init?(_ data: String, isMale: Bool = false) {
|
|
self.isMale = isMale
|
|
|
|
var result = data.components(separatedBy: .newlines).map { $0.trimmed }
|
|
result = result.reversed().drop(while: {
|
|
$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
|
}).reversed() as [String]
|
|
|
|
result = Array(result.drop(while: {
|
|
$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
|
}))
|
|
|
|
//print(result)
|
|
if result.count < 11 {
|
|
return nil
|
|
}
|
|
if let _rank = Int(result[0]) {
|
|
rank = _rank
|
|
} else {
|
|
return nil
|
|
}
|
|
lastName = result[1]
|
|
firstName = result[2]
|
|
|
|
country = result[3]
|
|
license = result[4]
|
|
|
|
// let matches = result[5].matches(of: try! Regex("[0-9]{1,5}\\.00"))
|
|
//
|
|
// if matches.count == 1 {
|
|
// let pts = result[5][matches.first!.range]
|
|
// points = Double(pts.replacingOccurrences(of: ",", with: "."))
|
|
// if pts.count < result[5].count {
|
|
//
|
|
// }
|
|
// }
|
|
//
|
|
points = Double(result[5].replacingOccurrences(of: ",", with: "."))
|
|
assimilation = result[6]
|
|
tournamentCount = Int(result[7])
|
|
ligue = result[8]
|
|
clubCode = result[9]
|
|
club = result[10]
|
|
}
|
|
|
|
static func anonymousCount(mostRecentDateAvailable: Date?) async -> Int? {
|
|
let context = PersistenceController.shared.localContainer.newBackgroundContext()
|
|
let importedPlayerFetchRequest = ImportedPlayer.fetchRequest()
|
|
var predicate = NSPredicate(format: "lastName == %@ && firstName == %@", "", "")
|
|
if let mostRecentDateAvailable {
|
|
predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, NSPredicate(format: "importDate == %@", mostRecentDateAvailable as CVarArg)])
|
|
}
|
|
importedPlayerFetchRequest.predicate = predicate
|
|
let count = try? context.count(for: importedPlayerFetchRequest)
|
|
return count
|
|
}
|
|
|
|
static func lastRank(mostRecentDateAvailable: Date?, man: Bool) async -> (Int, Int?)? {
|
|
let context = PersistenceController.shared.localContainer.newBackgroundContext()
|
|
let lastPlayerFetch = ImportedPlayer.fetchRequest()
|
|
lastPlayerFetch.sortDescriptors = [NSSortDescriptor(keyPath: \ImportedPlayer.rank, ascending: false)]
|
|
var predicate = NSPredicate(format: "male == \(man)")
|
|
if let mostRecentDateAvailable {
|
|
predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, NSPredicate(format: "importDate == %@", mostRecentDateAvailable as CVarArg)])
|
|
}
|
|
lastPlayerFetch.predicate = predicate
|
|
let count = try? context.count(for: lastPlayerFetch)
|
|
do {
|
|
if let lr = try context.fetch(lastPlayerFetch).first?.rank {
|
|
let fetch = ImportedPlayer.fetchRequest()
|
|
var rankPredicate = NSPredicate(format: "rank == %i", lr)
|
|
if let mostRecentDateAvailable {
|
|
rankPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [rankPredicate, NSPredicate(format: "importDate == %@", mostRecentDateAvailable as CVarArg)])
|
|
}
|
|
fetch.predicate = rankPredicate
|
|
|
|
let lastPlayersCount = try context.count(for: fetch)
|
|
return (Int(lr) + Int(lastPlayersCount) - 1, count)
|
|
}
|
|
} catch {
|
|
print("ImportedPlayer.fetchRequest", error)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
}
|
|
|
|
extension CodingUserInfoKey {
|
|
static let maleData = Self(rawValue: "maleData")!
|
|
}
|
|
|