remove unecessary july 2024 download

clean up some debug methods
sync2
Raz 9 months ago
parent 8efa0307f7
commit e5c113ddad
  1. 5
      PadelClub/Data/Federal/FederalPlayer.swift
  2. 92
      PadelClub/Data/PlayerRegistration.swift
  3. 2
      PadelClub/Data/TeamRegistration.swift
  4. 58
      PadelClub/Data/Tournament.swift
  5. 49
      PadelClub/Utils/FileImportManager.swift
  6. 8
      PadelClub/Utils/SourceFileManager.swift
  7. 2
      PadelClub/Views/Components/StepperView.swift
  8. 44
      PadelClub/Views/Navigation/MainView.swift
  9. 170
      PadelClub/Views/Navigation/Umpire/PadelClubView.swift

@ -197,8 +197,6 @@ class FederalPlayer: Decodable {
}
lastPlayerFetch.predicate = predicate
let count = try? context.count(for: lastPlayerFetch)
print("count", count)
do {
if let lr = try context.fetch(lastPlayerFetch).first?.rank {
let fetch = ImportedPlayer.fetchRequest()
@ -207,8 +205,9 @@ class FederalPlayer: Decodable {
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 {

@ -44,7 +44,7 @@ final class PlayerRegistration: ModelObject, Storable {
func localizedSourceLabel() -> String {
switch source {
case .frenchFederation, .onlineRegistration:
case .frenchFederation:
return "base fédérale"
case .beachPadel:
return "beach-padel"
@ -262,82 +262,87 @@ final class PlayerRegistration: ModelObject, Storable {
}
func updateRank(from sources: [CSVParser], lastRank: Int) async throws {
#if DEBUG_TIME //DEBUGING TIME
let start = Date()
defer {
let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
print("func updateRank()", id, duration.formatted(.units(allowed: [.seconds, .milliseconds])))
}
#endif
#if DEBUG_TIME
let start = Date()
defer {
let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
print("func updateRank()", id, duration.formatted(.units(allowed: [.seconds, .milliseconds])))
}
#endif
if let dataFound = try await history(from: sources) {
rank = dataFound.rankValue?.toInt()
points = dataFound.points
tournamentPlayed = dataFound.tournamentCountValue?.toInt()
} else if let dataFound = try await historyFromName(from: sources) {
rank = dataFound.rankValue?.toInt()
points = dataFound.points
tournamentPlayed = dataFound.tournamentCountValue?.toInt()
} else {
rank = lastRank
}
}
func history(from sources: [CSVParser]) async throws -> Line? {
#if DEBUG_TIME //DEBUGING TIME
let start = Date()
defer {
let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
print("func history()", id, duration.formatted(.units(allowed: [.seconds, .milliseconds])))
}
#endif
#if DEBUG_TIME
let start = Date()
defer {
let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
print("func history()", id, duration.formatted(.units(allowed: [.seconds, .milliseconds])))
}
#endif
guard let license = licenceId?.strippedLicense else {
return try await historyFromName(from: sources)
return nil // Do NOT call historyFromName here, let updateRank handle it
}
let filteredSources = sources.filter { $0.maleData == isMalePlayer() }
return await withTaskGroup(of: Line?.self) { group in
for source in sources.filter({ $0.maleData == isMalePlayer() }) {
for source in filteredSources {
group.addTask {
guard !Task.isCancelled else { print("Cancelled"); return nil }
return try? await source.first(where: { line in
line.rawValue.contains(";\(license);")
})
return try? await source.first { $0.rawValue.contains(";\(license);") }
}
}
if let first = await group.first(where: { $0 != nil }) {
group.cancelAll()
return first
} else {
return nil
}
return nil
}
}
func historyFromName(from sources: [CSVParser]) async throws -> Line? {
#if DEBUG_TIME //DEBUGING TIME
let start = Date()
defer {
let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
print("func historyFromName()", id, duration.formatted(.units(allowed: [.seconds, .milliseconds])))
}
#endif
#if DEBUG_TIME
let start = Date()
defer {
let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
print("func historyFromName()", id, duration.formatted(.units(allowed: [.seconds, .milliseconds])))
}
#endif
let filteredSources = sources.filter { $0.maleData == isMalePlayer() }
let normalizedLastName = lastName.canonicalVersionWithPunctuation
let normalizedFirstName = firstName.canonicalVersionWithPunctuation
return await withTaskGroup(of: Line?.self) { group in
for source in sources.filter({ $0.maleData == isMalePlayer() }) {
group.addTask { [lastName, firstName] in
for source in filteredSources {
group.addTask {
guard !Task.isCancelled else { print("Cancelled"); return nil }
return try? await source.first(where: { line in
line.rawValue.canonicalVersionWithPunctuation.contains(";\(lastName.canonicalVersionWithPunctuation);\(firstName.canonicalVersionWithPunctuation);")
})
return try? await source.first {
let lineValue = $0.rawValue.canonicalVersionWithPunctuation
return lineValue.contains(";\(normalizedLastName);\(normalizedFirstName);")
}
}
}
if let first = await group.first(where: { $0 != nil }) {
group.cancelAll()
return first
} else {
return nil
}
return nil
}
}
@ -347,7 +352,7 @@ defer {
return
}
let currentRank = rank ?? tournament.unrankValue(for: isMalePlayer()) ?? 70_000
let currentRank = rank ?? tournament.unrankValue(for: isMalePlayer()) ?? 90_000
switch tournament.tournamentCategory {
case .men:
computedRank = isMalePlayer() ? currentRank : currentRank + PlayerRegistration.addon(for: currentRank, manMax: tournament.maleUnrankedValue ?? 0, womanMax: tournament.femaleUnrankedValue ?? 0)
@ -473,7 +478,6 @@ defer {
enum PlayerDataSource: Int, Codable {
case frenchFederation = 0
case beachPadel = 1
case onlineRegistration = 2
}
enum PlayerSexType: Int, Hashable, CaseIterable, Identifiable, Codable {

@ -551,7 +551,7 @@ final class TeamRegistration: ModelObject, Storable {
}
func unrankValue(for malePlayer: Bool) -> Int {
return tournamentObject()?.unrankValue(for: malePlayer) ?? 70_000
return tournamentObject()?.unrankValue(for: malePlayer) ?? 90_000
}
func groupStageObject() -> GroupStage? {

@ -1511,43 +1511,53 @@ defer {
func updateRank(to newDate: Date?) async throws {
#if DEBUG_TIME //DEBUGING TIME
let start = Date()
defer {
let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
print("func updateRank()", id, duration.formatted(.units(allowed: [.seconds, .milliseconds])))
}
#endif
#if DEBUG_TIME
let start = Date()
defer {
let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
print("func updateRank()", id, duration.formatted(.units(allowed: [.seconds, .milliseconds])))
}
#endif
guard let newDate else { return }
rankSourceDate = newDate
// Fetch current month data only once
let monthData = currentMonthData()
if currentMonthData() == nil {
let lastRankWoman = SourceFileManager.shared.getUnrankValue(forMale: false, rankSourceDate: rankSourceDate)
let lastRankMan = SourceFileManager.shared.getUnrankValue(forMale: true, rankSourceDate: rankSourceDate)
await MainActor.run {
let formatted: String = URL.importDateFormatter.string(from: newDate)
let monthData: MonthData = MonthData(monthKey: formatted)
monthData.maleUnrankedValue = lastRankMan
monthData.femaleUnrankedValue = lastRankWoman
do {
try DataStore.shared.monthData.addOrUpdate(instance: monthData)
} catch {
Logger.error(error)
}
if monthData == nil {
async let lastRankWoman = SourceFileManager.shared.getUnrankValue(forMale: false, rankSourceDate: rankSourceDate)
async let lastRankMan = SourceFileManager.shared.getUnrankValue(forMale: true, rankSourceDate: rankSourceDate)
let formatted = URL.importDateFormatter.string(from: newDate)
let newMonthData = MonthData(monthKey: formatted)
newMonthData.maleUnrankedValue = await lastRankMan
newMonthData.femaleUnrankedValue = await lastRankWoman
do {
try DataStore.shared.monthData.addOrUpdate(instance: newMonthData)
} catch {
Logger.error(error)
}
}
let lastRankMan = currentMonthData()?.maleUnrankedValue
let lastRankWoman = currentMonthData()?.femaleUnrankedValue
let lastRankMan = monthData?.maleUnrankedValue ?? 0
let lastRankWoman = monthData?.femaleUnrankedValue ?? 0
// Fetch only the required files
let dataURLs = SourceFileManager.shared.allFiles.filter { $0.dateFromPath == newDate }
guard !dataURLs.isEmpty else { return } // Early return if no files found
let sources = dataURLs.map { CSVParser(url: $0) }
let players = unsortedPlayers()
try await players.concurrentForEach { player in
try await player.updateRank(from: sources, lastRank: (player.sex == .female ? lastRankWoman : lastRankMan) ?? 0)
let lastRank = (player.sex == .female) ? lastRankWoman : lastRankMan
try await player.updateRank(from: sources, lastRank: lastRank)
}
}
func missingUnrankedValue() -> Bool {
return maleUnrankedValue == nil || femaleUnrankedValue == nil
}

@ -28,9 +28,6 @@ class ImportObserver {
func currentlyImportingLabel() -> String {
guard let currentImportDate else { return "import en cours" }
if URL.importDateFormatter.string(from: currentImportDate) == "07-2024" {
return "consolidation des données"
}
return "import " + currentImportDate.monthYearFormatted
}
@ -44,32 +41,38 @@ class ImportObserver {
class FileImportManager {
static let shared = FileImportManager()
func updatePlayers(isMale: Bool, players: inout [FederalPlayer]) {
let replacements: [(Character, Character)] = [("Á", "ç"), ("", "à"), ("Ù", "ô"), ("Ë", "è"), ("Ó", "î"), ("Î", "ë"), ("", "É"), ("Ô", "ï"), ("È", "é"), ("«", "Ç"), ("»", "È")]
var playersLeft = players
SourceFileManager.shared.allFilesSortedByDate(isMale).forEach({ url in
if playersLeft.isEmpty == false {
let federalPlayers = readCSV(inputFile: url)
let replacementsCharacters = url.dateFromPath.monthYearFormatted != "04-2024" ? [] : replacements
var playersLeft = Dictionary(uniqueKeysWithValues: players.map { ($0.license, $0) })
SourceFileManager.shared.allFilesSortedByDate(isMale).forEach { url in
if playersLeft.isEmpty { return }
let federalPlayers = readCSV(inputFile: url)
let replacementsCharacters = url.dateFromPath.monthYearFormatted != "04-2024" ? [] : replacements
let federalPlayersDict = Dictionary(uniqueKeysWithValues: federalPlayers.map { ($0.license, $0) })
for (license, importedPlayer) in playersLeft {
guard let federalPlayer = federalPlayersDict[license] else { continue }
playersLeft.forEach { importedPlayer in
if let federalPlayer = federalPlayers.first(where: { $0.license == importedPlayer.license }) {
var lastName = federalPlayer.lastName
lastName.replace(characters: replacementsCharacters)
var firstName = federalPlayer.firstName
firstName.replace(characters: replacementsCharacters)
importedPlayer.lastName = lastName.trimmed.uppercased()
importedPlayer.firstName = firstName.trimmed.capitalized
}
}
var lastName = federalPlayer.lastName
var firstName = federalPlayer.firstName
lastName.replace(characters: replacementsCharacters)
firstName.replace(characters: replacementsCharacters)
importedPlayer.lastName = lastName.trimmed.uppercased()
importedPlayer.firstName = firstName.trimmed.capitalized
playersLeft.removeValue(forKey: license) // Remove processed player
}
})
}
players = playersLeft
players = Array(playersLeft.values)
}
func foundInWomenData(license: String?) -> Bool {
guard let license = license?.strippedLicense else {
return false
@ -148,7 +151,7 @@ class FileImportManager {
}
let significantPlayerCount = 2
let pl = players.prefix(significantPlayerCount).map { $0.computedRank }
let missingPl = (missing.map { tournament.unrankValue(for: $0 == 1 ? true : false ) ?? ($0 == 1 ? 70_000 : 10_000) }).prefix(significantPlayerCount)
let missingPl = (missing.map { tournament.unrankValue(for: $0 == 1 ? true : false ) ?? ($0 == 1 ? 90_000 : 10_000) }).prefix(significantPlayerCount)
self.weight = pl.reduce(0,+) + missingPl.reduce(0,+)
} else {
self.weight = players.map { $0.computedRank }.reduce(0,+)

@ -16,6 +16,7 @@ class SourceFileManager {
}
let rankingSourceDirectory : URL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appending(path: "rankings")
let anonymousSourceDirectory : URL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appending(path: "anonymous")
func createDirectoryIfNeeded() {
let fileManager = FileManager.default
@ -193,6 +194,13 @@ class SourceFileManager {
}
}
func anonymousFiles() -> [URL] {
let allJSONFiles = try! FileManager.default.contentsOfDirectory(at: anonymousSourceDirectory, includingPropertiesForKeys: nil).filter({ url in
url.pathExtension == "csv"
})
return allJSONFiles
}
func jsonFiles() -> [URL] {
let allJSONFiles = try! FileManager.default.contentsOfDirectory(at: rankingSourceDirectory, includingPropertiesForKeys: nil).filter({ url in
url.pathExtension == "json"

@ -88,7 +88,7 @@ struct StepperView: View {
}
fileprivate func _plusIsDisabled() -> Bool {
count >= (maximum ?? 70_000)
count >= (maximum ?? 90_000)
}
fileprivate func _add() {

@ -185,11 +185,6 @@ struct MainView: View {
importObserver.checkingFilesAttempt += 1
importObserver.checkingFiles = false
if lastDataSource == nil || (dataStore.monthData.first(where: { $0.monthKey == "07-2024" }) == nil) {
// await _downloadPreviousDate()
await _importMandatoryData()
}
if let mostRecentDateAvailable = SourceFileManager.shared.mostRecentDateAvailable, mostRecentDateAvailable > SourceFileManager.shared.lastDataSourceDate() ?? .distantPast {
print("importing \(mostRecentDateAvailable)")
@ -222,17 +217,6 @@ struct MainView: View {
await SourceFileManager.shared.getAllFiles(initialDate: "05-2024")
}
private func _importMandatoryData() async {
let mandatoryKey = "07-2024"
if dataStore.monthData.first(where: { $0.monthKey == mandatoryKey }) == nil, let importingDate = URL.importDateFormatter.date(from: mandatoryKey) {
print("importing mandatory july data")
dataStore.appSettings.lastDataSource = mandatoryKey
dataStore.appSettingsStorage.write()
await SourceFileManager.shared.getAllFiles(initialDate: "07-2024")
await _calculateMonthData(dataSource: mandatoryKey)
}
}
private func _checkingDataIntegrity() {
guard importObserver.checkingFiles == false, importObserver.isImportingFile() == false else {
return
@ -245,27 +229,21 @@ struct MainView: View {
Task {
await self._checkSourceFileAvailability()
}
} else if let lastDataSource, let mostRecentDateImported = URL.importDateFormatter.date(from: lastDataSource), SourceFileManager.isDateAfterUrlImportDate(date:mostRecentDateImported, dateString: "07-2024") {
} else if let lastDataSource, let mostRecentDateImported = URL.importDateFormatter.date(from: lastDataSource) {
let monthData = dataStore.monthData.sorted(by: \.creationDate)
if monthData.first(where: { $0.monthKey == "07-2024" }) == nil {
if let current = monthData.last {
Task {
await _checkSourceFileAvailability()
}
} else {
if let current = monthData.last {
Task {
let updated = await SourceFileManager.shared.fetchData(fromDate: mostRecentDateImported)
let fileURL = SourceFileManager.shared.allFiles(true).first(where: { $0.dateFromPath == mostRecentDateImported && $0.index == 0 })
print("file updated", updated)
if let updated, updated == 1 {
await _startImporting(importingDate: mostRecentDateImported)
} else if current.dataModelIdentifier != PersistenceController.getModelVersion() && current.fileModelIdentifier != fileURL?.fileModelIdentifier() {
await _startImporting(importingDate: mostRecentDateImported)
} else if updated == 0 {
await _calculateMonthData(dataSource: current.monthKey)
}
let updated = await SourceFileManager.shared.fetchData(fromDate: mostRecentDateImported)
let fileURL = SourceFileManager.shared.allFiles(true).first(where: { $0.dateFromPath == mostRecentDateImported && $0.index == 0 })
print("file updated", updated)
if let updated, updated == 1 {
await _startImporting(importingDate: mostRecentDateImported)
} else if current.dataModelIdentifier != PersistenceController.getModelVersion() && current.fileModelIdentifier != fileURL?.fileModelIdentifier() {
await _startImporting(importingDate: mostRecentDateImported)
} else if updated == 0 {
await _calculateMonthData(dataSource: current.monthKey)
}
}
}

@ -40,10 +40,10 @@ struct PadelClubView: View {
if let currentMonth = monthData.first, currentMonth.incompleteMode {
Section {
Text("Attention, depuis Août 2024, les données fédérales publiques des joueurs (messieurs) récupérables sont incomplètes car limité au 40.000 premiers joueurs.")
Text("Attention, depuis Août 2024, les données fédérales publiques des joueurs (messieurs) récupérables sont incomplètes car limité au 80.000 premiers joueurs.")
if currentMonth.maleUnrankedValue == nil {
Text("Le rang d'un joueur non-classé n'est donc pas calculable pour le moment, Padel Club utilisera une valeur par défaut de de 70.000.")
Text("Le rang d'un joueur non-classé n'est donc pas calculable pour le moment, Padel Club utilisera une valeur par défaut de de 90.000.")
}
Text("Un classement souligné comme ci-dessous indiquera que l'information provient d'un mois précédent.")
@ -61,32 +61,22 @@ struct PadelClubView: View {
["36435", "BRUL…", "Romain", "France", "2993139", "15,00", "Non", "2", "NOUVELLE AQUITAINE", "59 33 0447", "SAINT LOUBES TC"]
*/
Section {
RowButtonView("Retry Anonymous") {
await _retryAnonymous()
}
}
Section {
RowButtonView("Write anonymous") {
_writeAnonymous()
}
}
Section {
RowButtonView("Exporter en csv") {
for fileURL in SourceFileManager.shared.jsonFiles() {
let decoder = JSONDecoder()
decoder.userInfo[.maleData] = fileURL.manData
do {
let data = try Data(contentsOf: fileURL)
let players = try decoder.decode([FederalPlayer].self, from: data)
var anonymousPlayers = players.filter { $0.firstName.isEmpty && $0.lastName.isEmpty }
let okPlayers = players.filter { $0.firstName.isEmpty == false && $0.lastName.isEmpty == false }
print("before anonymousPlayers.count", anonymousPlayers.count)
FileImportManager.shared.updatePlayers(isMale: fileURL.manData, players: &anonymousPlayers)
print("after local anonymousPlayers.count", anonymousPlayers.filter { $0.firstName.isEmpty && $0.lastName.isEmpty }.count)
await fetchPlayersDataSequentially(for: &anonymousPlayers)
print("after beach anonymousPlayers.count", anonymousPlayers.filter { $0.firstName.isEmpty && $0.lastName.isEmpty }
.count)
SourceFileManager.shared.exportToCSV(players: okPlayers + anonymousPlayers, sourceFileType: fileURL.manData ? .messieurs : .dames, date: fileURL.dateFromPath)
SourceFileManager.shared.exportToCSV("anonymes", players: anonymousPlayers.filter { $0.firstName.isEmpty && $0.lastName.isEmpty }, sourceFileType: fileURL.manData ? .messieurs : .dames, date: fileURL.dateFromPath)
} catch {
Logger.error(error)
}
}
await _exportCsv()
}
}
#endif
@ -169,7 +159,7 @@ struct PadelClubView: View {
if let maleUnrankedValue = monthData.maleUnrankedValue {
Text(maleUnrankedValue.formatted())
} else {
Text(70_000.formatted())
Text(90_000.formatted())
}
} label: {
Text("Rang d'un non classé")
@ -187,6 +177,11 @@ struct PadelClubView: View {
Text("Rang d'une non classée")
Text("Dames")
}
#if DEBUG
RowButtonView("recalc") {
await _calculateLastRank(dataSource: monthData.monthKey)
}
#endif
} header: {
HStack {
Text(monthData.monthKey)
@ -242,15 +237,110 @@ struct PadelClubView: View {
await SourceFileManager.shared.getAllFiles(initialDate: "08-2022")
self.uuid = UUID()
}
#if DEBUG
private func _calculateMonthData(dataSource: String?) async {
if let dataSource, let mostRecentDate = URL.importDateFormatter.date(from: dataSource) {
await MonthData.calculateCurrentUnrankedValues(fromDate: mostRecentDate)
}
}
private func _calculateLastRank(dataSource: String) async {
await _calculateMonthData(dataSource: dataSource)
}
private func _writeAnonymous() {
for fileURL in SourceFileManager.shared.anonymousFiles() {
let lastDateString = URL.importDateFormatter.string(from: fileURL.dateFromPath)
let sourceType = fileURL.manData ? SourceFile.messieurs : SourceFile.dames
let dateString = ["CLASSEMENT-PADEL", sourceType.rawValue, lastDateString].filter({ $0.isEmpty == false }).joined(separator: "-") + "." + "csv"
let documentsUrl:URL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL?)!
let destinationFileUrl = documentsUrl.appendingPathComponent("rankings").appendingPathComponent("\(dateString)")
updateCSVFile(sourceCSVURL: destinationFileUrl, updatedCSVURL: fileURL)
}
}
private func _retryAnonymous() async {
for fileURL in SourceFileManager.shared.anonymousFiles() {
let players = FileImportManager.shared.readCSV(inputFile: fileURL)
var anonymousPlayers = players
print("before anonymousPlayers.count", anonymousPlayers.count)
await fetchPlayersDataSequentially(for: &anonymousPlayers)
print("after beach anonymousPlayers.count", anonymousPlayers.filter { $0.firstName.isEmpty && $0.lastName.isEmpty }
.count)
SourceFileManager.shared.exportToCSV("anonymes", players: anonymousPlayers, sourceFileType: fileURL.manData ? .messieurs : .dames, date: fileURL.dateFromPath)
}
}
private func _exportCsv() async {
for fileURL in SourceFileManager.shared.jsonFiles() {
let decoder = JSONDecoder()
decoder.userInfo[.maleData] = fileURL.manData
do {
let data = try Data(contentsOf: fileURL)
let players = try decoder.decode([FederalPlayer].self, from: data)
var anonymousPlayers = players.filter { $0.firstName.isEmpty && $0.lastName.isEmpty }
let okPlayers = players.filter { $0.firstName.isEmpty == false && $0.lastName.isEmpty == false }
print("before anonymousPlayers.count", anonymousPlayers.count)
FileImportManager.shared.updatePlayers(isMale: fileURL.manData, players: &anonymousPlayers)
print("after local anonymousPlayers.count", anonymousPlayers.filter { $0.firstName.isEmpty && $0.lastName.isEmpty }.count)
await fetchPlayersDataSequentially(for: &anonymousPlayers)
print("after beach anonymousPlayers.count", anonymousPlayers.filter { $0.firstName.isEmpty && $0.lastName.isEmpty }
.count)
SourceFileManager.shared.exportToCSV(players: okPlayers + anonymousPlayers, sourceFileType: fileURL.manData ? .messieurs : .dames, date: fileURL.dateFromPath)
SourceFileManager.shared.exportToCSV("anonymes", players: anonymousPlayers.filter { $0.firstName.isEmpty && $0.lastName.isEmpty }, sourceFileType: fileURL.manData ? .messieurs : .dames, date: fileURL.dateFromPath)
} catch {
Logger.error(error)
}
}
}
#endif
}
//#Preview {
// PadelClubView()
//}
func updateCSVFile(sourceCSVURL: URL, updatedCSVURL: URL) {
do {
let sourceCSVContent = try String(contentsOf: sourceCSVURL, encoding: .utf8)
var sourceCSVLines = sourceCSVContent.components(separatedBy: "\n")
let delimiter = ";"
let updatedCSVContent = try String(contentsOf: updatedCSVURL, encoding: .utf8)
let updatedCSVLines = updatedCSVContent.components(separatedBy: "\n")
// Create a dictionary of updated player data by licenseId
var updatedPlayerDict: [String: String] = [:]
for line in updatedCSVLines {
let components = line.components(separatedBy: delimiter)
if let licenseId = components.dropFirst(5).first {
updatedPlayerDict[licenseId] = line
}
}
// Update the source CSV lines if licenseId matches
for (index, line) in sourceCSVLines.enumerated() {
let components = line.components(separatedBy: delimiter)
if let licenseId = components.dropFirst(5).first, let updatedLine = updatedPlayerDict[licenseId] {
sourceCSVLines[index] = updatedLine
}
}
// Write back to the file
let finalCSVContent = sourceCSVLines.joined(separator: "\n")
try finalCSVContent.write(to: sourceCSVURL, atomically: true, encoding: .utf8)
print("CSV file updated successfully.")
} catch {
print("Error updating CSV file: \(error)")
}
}
// Function to fetch data for a single license ID
func fetchPlayerData(for licenseID: String) async throws -> [Player]? {
guard let url = URL(string: "https://beach-padel.app.fft.fr/beachja/rechercheJoueur/licencies?idHomologation=82469282&numeroLicence=\(licenseID)") else {
func fetchPlayerData(for licenseID: String, idHomologation: String, sessionId: String) async throws -> [Player]? {
guard let url = URL(string: "https://beach-padel.app.fft.fr/beachja/rechercheJoueur/licencies?idHomologation=\(idHomologation)&numeroLicence=\(licenseID)") else {
throw URLError(.badURL)
}
@ -268,7 +358,7 @@ func fetchPlayerData(for licenseID: String) async throws -> [Player]? {
request.setValue("XMLHttpRequest", forHTTPHeaderField: "X-Requested-With")
// Add cookies if needed (example cookie header value shown, replace with valid cookies)
request.setValue("JSESSIONID=48C272263C9454774F0DA95F491C3765; AWSALB=nNF/fDwCSmsO9PQD5jkXNUuoMuAzziHTeIkno1uRkNDkKfaOT7VVbh0KOdvGZ5afMw3epLw0p9J+4Ih6cpwqW+XdcLUrr9kJhpQEgP1oeLPRsi/4Yn9uCLCRgPKI; AWSALBCORS=nNF/fDwCSmsO9PQD5jkXNUuoMuAzziHTeIkno1uRkNDkKfaOT7VVbh0KOdvGZ5afMw3epLw0p9J+4Ih6cpwqW+XdcLUrr9kJhpQEgP1oeLPRsi/4Yn9uCLCRgPKI; datadome=3T1lKPP7j_r9MhBRIq_5sBwcCuhI0lfYgQ414DuY7BdYm3jpvHECT05w6Ohl0xMvGVJi3XayxoRsnsKvPti_TIZ90B~boSu2LYs2lm_OssxFSoDGEHTFOf4HTjVkM6i8; TCID=125221542552726081269; TCSESSION=125221542558139099625; TCPID=125221535336434794787; incap_ses_2224_2712217=T+1ySNxxGx/yVRcIdDzdHrUlomcAAAAAAWv/NX2ushG21NP0K9l10g==; nlbi_2712217=Wd9XXxrrXQSWKZBPb9lUTgAAAADRjV4zuALYepgab2n0ra/7; xtan=-; xtant=1; xtvrn=$548419$; visid_incap_2712217=PSfJngzoSuiowsuXXhvOu5K+7mUAAAAAQUIPAAAAAAAleL9ldvN/FC1VykkU9ret; SessionStatId=10.91.140.42.1662124965429001", forHTTPHeaderField: "Cookie")
request.setValue(sessionId, forHTTPHeaderField: "Cookie")
let (data, _) = try await URLSession.shared.data(for: request)
let decoder = JSONDecoder()
@ -288,9 +378,21 @@ func fetchPlayerData(for licenseID: String) async throws -> [Player]? {
// Function to fetch data for multiple license IDs using TaskGroup
func fetchPlayersDataSequentially(for licenseIDs: inout [FederalPlayer]) async {
var idHomologation: String = "82469282"
if let _idHomologation = PListReader.readString(plist: "local", key: "idHomologation") {
idHomologation = _idHomologation
}
var sessionId: String = ""
if let _sessionId = PListReader.readString(plist: "local", key: "JSESSIONID") {
sessionId = _sessionId
}
for licenseID in licenseIDs.filter({ $0.firstName.isEmpty && $0.lastName.isEmpty }) {
do {
if let playerData = try await fetchPlayerData(for: licenseID.license)?.first {
if let playerData = try await fetchPlayerData(for: licenseID.license, idHomologation: idHomologation, sessionId: sessionId)?.first {
licenseID.lastName = playerData.nom
licenseID.firstName = playerData.prenom
}

Loading…
Cancel
Save