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. 48
      PadelClub/Data/PlayerRegistration.swift
  3. 2
      PadelClub/Data/TeamRegistration.swift
  4. 38
      PadelClub/Data/Tournament.swift
  5. 31
      PadelClub/Utils/FileImportManager.swift
  6. 8
      PadelClub/Utils/SourceFileManager.swift
  7. 2
      PadelClub/Views/Components/StepperView.swift
  8. 24
      PadelClub/Views/Navigation/MainView.swift
  9. 166
      PadelClub/Views/Navigation/Umpire/PadelClubView.swift

@ -197,8 +197,6 @@ class FederalPlayer: Decodable {
} }
lastPlayerFetch.predicate = predicate lastPlayerFetch.predicate = predicate
let count = try? context.count(for: lastPlayerFetch) let count = try? context.count(for: lastPlayerFetch)
print("count", count)
do { do {
if let lr = try context.fetch(lastPlayerFetch).first?.rank { if let lr = try context.fetch(lastPlayerFetch).first?.rank {
let fetch = ImportedPlayer.fetchRequest() let fetch = ImportedPlayer.fetchRequest()
@ -207,8 +205,9 @@ class FederalPlayer: Decodable {
rankPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [rankPredicate, NSPredicate(format: "importDate == %@", mostRecentDateAvailable as CVarArg)]) rankPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [rankPredicate, NSPredicate(format: "importDate == %@", mostRecentDateAvailable as CVarArg)])
} }
fetch.predicate = rankPredicate fetch.predicate = rankPredicate
print(fetch.predicate)
let lastPlayersCount = try context.count(for: fetch) let lastPlayersCount = try context.count(for: fetch)
print(Int(lr), Int(lastPlayersCount) - 1, count)
return (Int(lr) + Int(lastPlayersCount) - 1, count) return (Int(lr) + Int(lastPlayersCount) - 1, count)
} }
} catch { } catch {

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

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

@ -1511,7 +1511,7 @@ defer {
func updateRank(to newDate: Date?) async throws { func updateRank(to newDate: Date?) async throws {
#if DEBUG_TIME //DEBUGING TIME #if DEBUG_TIME
let start = Date() let start = Date()
defer { defer {
let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000) let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
@ -1522,32 +1522,42 @@ defer {
guard let newDate else { return } guard let newDate else { return }
rankSourceDate = newDate rankSourceDate = newDate
if currentMonthData() == nil { // Fetch current month data only once
let lastRankWoman = SourceFileManager.shared.getUnrankValue(forMale: false, rankSourceDate: rankSourceDate) let monthData = currentMonthData()
let lastRankMan = SourceFileManager.shared.getUnrankValue(forMale: true, rankSourceDate: rankSourceDate)
await MainActor.run { if monthData == nil {
let formatted: String = URL.importDateFormatter.string(from: newDate) async let lastRankWoman = SourceFileManager.shared.getUnrankValue(forMale: false, rankSourceDate: rankSourceDate)
let monthData: MonthData = MonthData(monthKey: formatted) async let lastRankMan = SourceFileManager.shared.getUnrankValue(forMale: true, rankSourceDate: rankSourceDate)
monthData.maleUnrankedValue = lastRankMan
monthData.femaleUnrankedValue = lastRankWoman let formatted = URL.importDateFormatter.string(from: newDate)
let newMonthData = MonthData(monthKey: formatted)
newMonthData.maleUnrankedValue = await lastRankMan
newMonthData.femaleUnrankedValue = await lastRankWoman
do { do {
try DataStore.shared.monthData.addOrUpdate(instance: monthData) try DataStore.shared.monthData.addOrUpdate(instance: newMonthData)
} catch { } catch {
Logger.error(error) Logger.error(error)
} }
} }
}
let lastRankMan = currentMonthData()?.maleUnrankedValue let lastRankMan = monthData?.maleUnrankedValue ?? 0
let lastRankWoman = currentMonthData()?.femaleUnrankedValue let lastRankWoman = monthData?.femaleUnrankedValue ?? 0
// Fetch only the required files
let dataURLs = SourceFileManager.shared.allFiles.filter { $0.dateFromPath == newDate } 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 sources = dataURLs.map { CSVParser(url: $0) }
let players = unsortedPlayers() let players = unsortedPlayers()
try await players.concurrentForEach { player in 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 { func missingUnrankedValue() -> Bool {
return maleUnrankedValue == nil || femaleUnrankedValue == nil return maleUnrankedValue == nil || femaleUnrankedValue == nil
} }

@ -28,9 +28,6 @@ class ImportObserver {
func currentlyImportingLabel() -> String { func currentlyImportingLabel() -> String {
guard let currentImportDate else { return "import en cours" } 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 return "import " + currentImportDate.monthYearFormatted
} }
@ -44,30 +41,36 @@ class ImportObserver {
class FileImportManager { class FileImportManager {
static let shared = FileImportManager() static let shared = FileImportManager()
func updatePlayers(isMale: Bool, players: inout [FederalPlayer]) { func updatePlayers(isMale: Bool, players: inout [FederalPlayer]) {
let replacements: [(Character, Character)] = [("Á", "ç"), ("", "à"), ("Ù", "ô"), ("Ë", "è"), ("Ó", "î"), ("Î", "ë"), ("", "É"), ("Ô", "ï"), ("È", "é"), ("«", "Ç"), ("»", "È")] let replacements: [(Character, Character)] = [("Á", "ç"), ("", "à"), ("Ù", "ô"), ("Ë", "è"), ("Ó", "î"), ("Î", "ë"), ("", "É"), ("Ô", "ï"), ("È", "é"), ("«", "Ç"), ("»", "È")]
var playersLeft = players var playersLeft = Dictionary(uniqueKeysWithValues: players.map { ($0.license, $0) })
SourceFileManager.shared.allFilesSortedByDate(isMale).forEach({ url in
if playersLeft.isEmpty == false { SourceFileManager.shared.allFilesSortedByDate(isMale).forEach { url in
if playersLeft.isEmpty { return }
let federalPlayers = readCSV(inputFile: url) let federalPlayers = readCSV(inputFile: url)
let replacementsCharacters = url.dateFromPath.monthYearFormatted != "04-2024" ? [] : replacements let replacementsCharacters = url.dateFromPath.monthYearFormatted != "04-2024" ? [] : replacements
playersLeft.forEach { importedPlayer in let federalPlayersDict = Dictionary(uniqueKeysWithValues: federalPlayers.map { ($0.license, $0) })
if let federalPlayer = federalPlayers.first(where: { $0.license == importedPlayer.license }) {
for (license, importedPlayer) in playersLeft {
guard let federalPlayer = federalPlayersDict[license] else { continue }
var lastName = federalPlayer.lastName var lastName = federalPlayer.lastName
lastName.replace(characters: replacementsCharacters)
var firstName = federalPlayer.firstName var firstName = federalPlayer.firstName
lastName.replace(characters: replacementsCharacters)
firstName.replace(characters: replacementsCharacters) firstName.replace(characters: replacementsCharacters)
importedPlayer.lastName = lastName.trimmed.uppercased() importedPlayer.lastName = lastName.trimmed.uppercased()
importedPlayer.firstName = firstName.trimmed.capitalized importedPlayer.firstName = firstName.trimmed.capitalized
playersLeft.removeValue(forKey: license) // Remove processed player
} }
} }
}
})
players = playersLeft players = Array(playersLeft.values)
} }
func foundInWomenData(license: String?) -> Bool { func foundInWomenData(license: String?) -> Bool {
@ -148,7 +151,7 @@ class FileImportManager {
} }
let significantPlayerCount = 2 let significantPlayerCount = 2
let pl = players.prefix(significantPlayerCount).map { $0.computedRank } 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,+) self.weight = pl.reduce(0,+) + missingPl.reduce(0,+)
} else { } else {
self.weight = players.map { $0.computedRank }.reduce(0,+) 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 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() { func createDirectoryIfNeeded() {
let fileManager = FileManager.default 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] { func jsonFiles() -> [URL] {
let allJSONFiles = try! FileManager.default.contentsOfDirectory(at: rankingSourceDirectory, includingPropertiesForKeys: nil).filter({ url in let allJSONFiles = try! FileManager.default.contentsOfDirectory(at: rankingSourceDirectory, includingPropertiesForKeys: nil).filter({ url in
url.pathExtension == "json" url.pathExtension == "json"

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

@ -185,11 +185,6 @@ struct MainView: View {
importObserver.checkingFilesAttempt += 1 importObserver.checkingFilesAttempt += 1
importObserver.checkingFiles = false 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 { if let mostRecentDateAvailable = SourceFileManager.shared.mostRecentDateAvailable, mostRecentDateAvailable > SourceFileManager.shared.lastDataSourceDate() ?? .distantPast {
print("importing \(mostRecentDateAvailable)") print("importing \(mostRecentDateAvailable)")
@ -222,17 +217,6 @@ struct MainView: View {
await SourceFileManager.shared.getAllFiles(initialDate: "05-2024") 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() { private func _checkingDataIntegrity() {
guard importObserver.checkingFiles == false, importObserver.isImportingFile() == false else { guard importObserver.checkingFiles == false, importObserver.isImportingFile() == false else {
return return
@ -245,15 +229,10 @@ struct MainView: View {
Task { Task {
await self._checkSourceFileAvailability() 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) let monthData = dataStore.monthData.sorted(by: \.creationDate)
if monthData.first(where: { $0.monthKey == "07-2024" }) == nil {
Task {
await _checkSourceFileAvailability()
}
} else {
if let current = monthData.last { if let current = monthData.last {
Task { Task {
let updated = await SourceFileManager.shared.fetchData(fromDate: mostRecentDateImported) let updated = await SourceFileManager.shared.fetchData(fromDate: mostRecentDateImported)
@ -271,7 +250,6 @@ struct MainView: View {
} }
} }
} }
}
//#Preview { //#Preview {
// MainView() // MainView()

@ -40,10 +40,10 @@ struct PadelClubView: View {
if let currentMonth = monthData.first, currentMonth.incompleteMode { if let currentMonth = monthData.first, currentMonth.incompleteMode {
Section { 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 { 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.") 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"] ["36435", "BRUL…", "Romain", "France", "2993139", "15,00", "Non", "2", "NOUVELLE AQUITAINE", "59 33 0447", "SAINT LOUBES TC"]
*/ */
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) Section {
RowButtonView("Retry Anonymous") {
await _retryAnonymous()
}
}
print("after beach anonymousPlayers.count", anonymousPlayers.filter { $0.firstName.isEmpty && $0.lastName.isEmpty } Section {
.count) RowButtonView("Write anonymous") {
SourceFileManager.shared.exportToCSV(players: okPlayers + anonymousPlayers, sourceFileType: fileURL.manData ? .messieurs : .dames, date: fileURL.dateFromPath) _writeAnonymous()
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)
} }
} }
Section {
RowButtonView("Exporter en csv") {
await _exportCsv()
} }
} }
#endif #endif
@ -169,7 +159,7 @@ struct PadelClubView: View {
if let maleUnrankedValue = monthData.maleUnrankedValue { if let maleUnrankedValue = monthData.maleUnrankedValue {
Text(maleUnrankedValue.formatted()) Text(maleUnrankedValue.formatted())
} else { } else {
Text(70_000.formatted()) Text(90_000.formatted())
} }
} label: { } label: {
Text("Rang d'un non classé") Text("Rang d'un non classé")
@ -187,6 +177,11 @@ struct PadelClubView: View {
Text("Rang d'une non classée") Text("Rang d'une non classée")
Text("Dames") Text("Dames")
} }
#if DEBUG
RowButtonView("recalc") {
await _calculateLastRank(dataSource: monthData.monthKey)
}
#endif
} header: { } header: {
HStack { HStack {
Text(monthData.monthKey) Text(monthData.monthKey)
@ -242,15 +237,110 @@ struct PadelClubView: View {
await SourceFileManager.shared.getAllFiles(initialDate: "08-2022") await SourceFileManager.shared.getAllFiles(initialDate: "08-2022")
self.uuid = UUID() 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
}
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
}
} }
//#Preview { // Update the source CSV lines if licenseId matches
// PadelClubView() 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 // Function to fetch data for a single license ID
func fetchPlayerData(for licenseID: String) async throws -> [Player]? { 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=82469282&numeroLicence=\(licenseID)") else { guard let url = URL(string: "https://beach-padel.app.fft.fr/beachja/rechercheJoueur/licencies?idHomologation=\(idHomologation)&numeroLicence=\(licenseID)") else {
throw URLError(.badURL) throw URLError(.badURL)
} }
@ -268,7 +358,7 @@ func fetchPlayerData(for licenseID: String) async throws -> [Player]? {
request.setValue("XMLHttpRequest", forHTTPHeaderField: "X-Requested-With") request.setValue("XMLHttpRequest", forHTTPHeaderField: "X-Requested-With")
// Add cookies if needed (example cookie header value shown, replace with valid cookies) // 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 (data, _) = try await URLSession.shared.data(for: request)
let decoder = JSONDecoder() 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 // Function to fetch data for multiple license IDs using TaskGroup
func fetchPlayersDataSequentially(for licenseIDs: inout [FederalPlayer]) async { 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 }) { for licenseID in licenseIDs.filter({ $0.firstName.isEmpty && $0.lastName.isEmpty }) {
do { 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.lastName = playerData.nom
licenseID.firstName = playerData.prenom licenseID.firstName = playerData.prenom
} }

Loading…
Cancel
Save