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.
246 lines
9.0 KiB
246 lines
9.0 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
|
|
var birthYear: Int?
|
|
var progression: Int
|
|
var bestRank: Int?
|
|
|
|
|
|
// MARK: - Nationnalite
|
|
struct Nationnalite: Hashable, Codable {
|
|
let code, codeFov: String
|
|
}
|
|
|
|
required init(from decoder: Decoder) throws {
|
|
/*
|
|
"classement": 9,
|
|
"evolution": 2,
|
|
"nom": "PEREZ LE TIEC",
|
|
"prenom": "Pierre",
|
|
"meilleurClassement": null,
|
|
"nationalite": "FRA",
|
|
"ageSportif": 30,
|
|
"points": 14210,
|
|
"nombreTournoisJoues": 24,
|
|
"ligue": "ILE DE FRANCE",
|
|
"assimilation": false
|
|
*/
|
|
enum CodingKeys: String, CodingKey {
|
|
case nom
|
|
case prenom
|
|
case licence
|
|
case meilleurClassement
|
|
case nationalite
|
|
case codeClub
|
|
case nomClub
|
|
case ligue
|
|
case classement
|
|
case evolution
|
|
case points
|
|
case nombreTournoisJoues
|
|
case assimilation
|
|
case ageSportif
|
|
}
|
|
|
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
|
|
isMale = (decoder.userInfo[.maleData] as? Bool) == true
|
|
|
|
let _lastName = try container.decodeIfPresent(String.self, forKey: .nom)
|
|
let _firstName = try container.decodeIfPresent(String.self, forKey: .prenom)
|
|
lastName = _lastName ?? ""
|
|
firstName = _firstName ?? ""
|
|
if let lic = try? container.decodeIfPresent(Int.self, forKey: .licence) {
|
|
license = String(lic)
|
|
} else {
|
|
license = ""
|
|
}
|
|
|
|
country = try container.decodeIfPresent(String.self, forKey: .nationalite) ?? ""
|
|
bestRank = try container.decodeIfPresent(Int.self, forKey: .meilleurClassement)
|
|
|
|
let ageSportif = try container.decodeIfPresent(Int.self, forKey: .ageSportif)
|
|
if let ageSportif {
|
|
let month = Calendar.current.component(.month, from: Date())
|
|
if month > 8 {
|
|
birthYear = Calendar.current.component(.year, from: Date()) + 1 - ageSportif
|
|
} else {
|
|
birthYear = Calendar.current.component(.year, from: Date()) - ageSportif
|
|
}
|
|
}
|
|
clubCode = try container.decodeIfPresent(String.self, forKey: .codeClub) ?? ""
|
|
club = try container.decodeIfPresent(String.self, forKey: .nomClub) ?? ""
|
|
ligue = try container.decodeIfPresent(String.self, forKey: .ligue) ?? ""
|
|
rank = try container.decode(Int.self, forKey: .classement)
|
|
progression = (try? container.decodeIfPresent(Int.self, forKey: .evolution)) ?? 0
|
|
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: .nombreTournoisJoues)
|
|
let assimile = try container.decode(Bool.self, forKey: .assimilation)
|
|
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);\(progression.formattedAsRawString());\(bestRank?.formattedAsRawString() ?? "");\(birthYear?.formattedAsRawString() ?? "");"
|
|
return line
|
|
}
|
|
|
|
func formatNumbers(_ input: String) -> String {
|
|
if input.isEmpty { return input }
|
|
// 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]
|
|
progression = result[safe: 11]?.toInt() ?? 0
|
|
bestRank = result[safe: 12]?.toInt()
|
|
birthYear = result[safe: 13]?.toInt()
|
|
}
|
|
|
|
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
|
|
print(fetch.predicate)
|
|
let lastPlayersCount = try context.count(for: fetch)
|
|
print(Int(lr), Int(lastPlayersCount) - 1, count)
|
|
return (Int(lr) + Int(lastPlayersCount) - 1, count)
|
|
}
|
|
} catch {
|
|
print("ImportedPlayer.fetchRequest", error)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
}
|
|
|
|
extension CodingUserInfoKey {
|
|
static let maleData = Self(rawValue: "maleData")!
|
|
}
|
|
|