multistore
Razmig Sarkissian 2 years ago
parent 0a3110967a
commit 588c7e8868
  1. 2
      PadelClub.xcodeproj/project.pbxproj
  2. 18
      PadelClub/Data/Federal/FederalPlayer.swift
  3. 20
      PadelClub/Data/MonthData.swift
  4. 2
      PadelClub/Data/Tournament.swift
  5. 15
      PadelClub/Utils/FileImportManager.swift
  6. 5
      PadelClub/Views/Navigation/MainView.swift
  7. 4
      PadelClub/Views/Navigation/Organizer/TournamentOrganizerView.swift
  8. 65
      PadelClub/Views/Navigation/Umpire/PadelClubView.swift
  9. 15
      PadelClub/Views/Team/Components/TeamHeaderView.swift
  10. 4
      PadelClub/Views/Tournament/FileImportView.swift
  11. 8
      PadelClub/Views/Tournament/Shared/TournamentCellView.swift

@ -958,7 +958,6 @@
FF025AE62BD1111000A86CF8 /* GlobalSettingsView.swift */,
FF025AEE2BD1AE9400A86CF8 /* DurationSettingsView.swift */,
FF025AF02BD1AEBD00A86CF8 /* MatchFormatStorageView.swift */,
FFD783FE2B91BA42000F62A6 /* PadelClubView.swift */,
);
path = Toolbox;
sourceTree = "<group>";
@ -967,6 +966,7 @@
isa = PBXGroup;
children = (
FF3F74F52B919E45004CFE0E /* UmpireView.swift */,
FFD783FE2B91BA42000F62A6 /* PadelClubView.swift */,
);
path = Umpire;
sourceTree = "<group>";

@ -169,7 +169,19 @@ class FederalPlayer: Decodable {
club = result[10]
}
static func lastRank(mostRecentDateAvailable: Date?, man: Bool) async -> Int? {
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)]
@ -178,7 +190,7 @@ class FederalPlayer: Decodable {
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()
@ -189,7 +201,7 @@ class FederalPlayer: Decodable {
fetch.predicate = rankPredicate
let lastPlayersCount = try context.count(for: fetch)
return Int(lr) + Int(lastPlayersCount) - 1
return (Int(lr) + Int(lastPlayersCount) - 1, count)
}
} catch {
print("ImportedPlayer.fetchRequest", error)

@ -21,21 +21,32 @@ class MonthData : ModelObject, Storable {
var maleUnrankedValue: Int? = nil
var femaleUnrankedValue: Int? = nil
var maleCount: Int? = nil
var femaleCount: Int? = nil
var anonymousCount: Int? = nil
init(monthKey: String) {
self.monthKey = monthKey
self.creationDate = Date()
}
func total() -> Int {
(maleCount ?? 0) + (femaleCount ?? 0)
}
static func calculateCurrentUnrankedValues(mostRecentDateAvailable: Date) async {
let lastDataSourceMaleUnranked = await FederalPlayer.lastRank(mostRecentDateAvailable: mostRecentDateAvailable, man: true)
let lastDataSourceFemaleUnranked = await FederalPlayer.lastRank(mostRecentDateAvailable: mostRecentDateAvailable, man: false)
let anonymousCount = await FederalPlayer.anonymousCount(mostRecentDateAvailable: mostRecentDateAvailable)
await MainActor.run {
if let lastDataSource = DataStore.shared.appSettings.lastDataSource {
let currentMonthData : MonthData = Store.main.filter(isIncluded: { $0.monthKey == lastDataSource }).first ?? MonthData(monthKey: lastDataSource)
currentMonthData.maleUnrankedValue = lastDataSourceMaleUnranked
currentMonthData.femaleUnrankedValue = lastDataSourceFemaleUnranked
currentMonthData.maleUnrankedValue = lastDataSourceMaleUnranked?.0
currentMonthData.maleCount = lastDataSourceMaleUnranked?.1
currentMonthData.femaleUnrankedValue = lastDataSourceFemaleUnranked?.0
currentMonthData.femaleCount = lastDataSourceFemaleUnranked?.1
currentMonthData.anonymousCount = anonymousCount
try? DataStore.shared.monthData.addOrUpdate(instance: currentMonthData)
}
}
@ -50,5 +61,8 @@ class MonthData : ModelObject, Storable {
case _creationDate = "creationDate"
case _maleUnrankedValue = "maleUnrankedValue"
case _femaleUnrankedValue = "femaleUnrankedValue"
case _maleCount = "maleCount"
case _femaleCount = "femaleCount"
case _anonymousCount = "anonymousCount"
}
}

@ -562,7 +562,7 @@ class Tournament : ModelObject, Storable {
let defaultSorting : [MySortDescriptor<TeamRegistration>] = _defaultSorting()
let _completeTeams = _teams.sorted(using: defaultSorting, order: .ascending).filter { $0.isWildCard() == false}
let _completeTeams = _teams.sorted(using: defaultSorting, order: .ascending).filter { $0.isWildCard() == false }.prefix(teamCount).sorted(by: \.initialWeight)
let wcGroupStage = _teams.filter { $0.wildCardGroupStage }.sorted(using: _currentSelectionSorting, order: .ascending)

@ -106,7 +106,9 @@ class FileImportManager {
}
}
let significantPlayerCount = 2
self.weight = (players.prefix(significantPlayerCount).map { $0.computedRank } + missing.map { tournament.unrankValue(for: $0 == 1 ? true : false ) ?? 0 }).prefix(significantPlayerCount).reduce(0,+)
let pl = players.prefix(significantPlayerCount).map { $0.computedRank }
let missingPl = (missing.map { tournament.unrankValue(for: $0 == 1 ? true : false ) ?? ($0 == 1 ? 100_000 : 10_000) }).prefix(significantPlayerCount)
self.weight = pl.reduce(0,+) + missingPl.reduce(0,+)
} else {
self.weight = players.map { $0.computedRank }.reduce(0,+)
}
@ -307,6 +309,13 @@ class FileImportManager {
}
private func _getPadelClubTeams(from fileContent: String, tournament: Tournament) async -> [TeamHolder] {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "fr_FR")
// Set the date format to match the input string
dateFormatter.dateFormat = "EEE dd MMM yyyy 'à' HH:mm"
var lines = fileContent.components(separatedBy: "\n\n")
var results: [TeamHolder] = []
let fetchRequest = ImportedPlayer.fetchRequest()
@ -324,8 +333,8 @@ class FileImportManager {
})
if let registeredPlayers, registeredPlayers.isEmpty == false {
var registrationDate: Date? {
if let registrationDateData = data[safe:2]?.replacingOccurrences(of: "inscrit le ", with: "") {
return try? Date(registrationDateData, strategy: .dateTime.weekday().day().month().hour().minute())
if let registrationDateData = data[safe:2]?.replacingOccurrences(of: "Inscrit le ", with: "") {
return dateFormatter.date(from: registrationDateData)
}
return nil
}

@ -59,6 +59,11 @@ struct MainView: View {
// PadelClubView()
// .tabItem(for: .padelClub)
}
.id(Store.main.currentUserUUID)
.onChange(of: Store.main.currentUserUUID) {
navigation.tournament = nil
navigation.path.removeLast(navigation.path.count)
}
.environmentObject(dataStore)
.task {
await self._checkSourceFileAvailability()

@ -6,6 +6,7 @@
//
import SwiftUI
import LeStorage
struct TournamentOrganizerView: View {
@EnvironmentObject var dataStore: DataStore
@ -46,6 +47,9 @@ struct TournamentOrganizerView: View {
}
}
}
.onChange(of: Store.main.currentUserUUID) {
selectedTournamentId = nil
}
}
}

@ -26,12 +26,6 @@ struct PadelClubView: View {
animation: .default)
private var players: FetchedResults<ImportedPlayer>
@FetchRequest(
sortDescriptors: [],
predicate: NSPredicate(format: "lastName == %@ && firstName == %@", "", ""),
animation: .default)
private var anonymousPlayers: FetchedResults<ImportedPlayer>
var _mostRecentDateAvailable: Date? {
SourceFileManager.shared.mostRecentDateAvailable
}
@ -96,27 +90,6 @@ struct PadelClubView: View {
}
}
}
Section {
LabeledContent {
Text(players.filter{ $0.male }.count.formatted())
} label: {
Text("Messieurs")
}
LabeledContent {
Text(players.filter{ $0.male == false }.count.formatted())
} label: {
Text("Dames")
}
LabeledContent {
Text(anonymousPlayers.count.formatted())
} label: {
Text("Joueurs anonymes")
}
} header: {
Text(players.count.formatted() + " joueurs")
}
}
if importingFiles {
@ -136,6 +109,29 @@ struct PadelClubView: View {
let monthData = dataStore.monthData.sorted(by: \.creationDate).reversed()
ForEach(monthData) { monthData in
Section {
LabeledContent {
if let maleCount = monthData.maleCount {
Text(maleCount.formatted())
}
} label: {
Text("Messieurs")
}
LabeledContent {
if let femaleCount = monthData.femaleCount {
Text(femaleCount.formatted())
}
} label: {
Text("Dames")
}
LabeledContent {
if let anonymousCount = monthData.anonymousCount {
Text(anonymousCount.formatted())
}
} label: {
Text("Joueurs anonymes")
}
LabeledContent {
if let maleUnrankedValue = monthData.maleUnrankedValue {
Text(maleUnrankedValue.formatted())
@ -153,7 +149,22 @@ struct PadelClubView: View {
Text("Dames")
}
} header: {
HStack {
Text(monthData.monthKey)
Spacer()
Text(monthData.total().formatted() + " joueurs")
}
} footer: {
HStack {
Spacer()
FooterButtonView("recalculer") {
Task {
if let monthKeyDate = URL.importDateFormatter.date(from: monthData.monthKey) {
await MonthData.calculateCurrentUnrankedValues(mostRecentDateAvailable: monthKeyDate)
}
}
}
}
}
}
}

@ -19,23 +19,34 @@ struct TeamHeaderView: View {
private func _teamHeaderView(_ team: TeamRegistration, teamIndex: Int?) -> some View {
HStack {
if let teamIndex {
VStack(alignment: .leading, spacing: 0) {
Text("rang").font(.caption)
Text("#" + (teamIndex + 1).formatted())
}
}
if team.unsortedPlayers().isEmpty == false {
VStack(alignment: .leading, spacing: 0) {
Text("poids").font(.caption)
Text(team.weight.formatted())
}
if team.isWildCard() {
Text("wildcard").italic().font(.caption)
}
Spacer()
VStack(alignment: .trailing, spacing: 0) {
if team.walkOut {
Text("").font(.caption)
Text("WO")
} else if let teamIndex, let tournament {
if team.isWildCard() {
Text("wildcard").font(.caption).italic()
} else {
Text("").font(.caption)
}
Text(tournament.cutLabel(index: teamIndex))
}
}
}
}
}
#Preview {

@ -246,6 +246,10 @@ struct FileImportView: View {
errorMessage = nil
teams.removeAll()
}
if let rankSourceDate = tournament.rankSourceDate, tournament.unrankValue(for: false) == nil || tournament.unrankValue(for: true) == nil {
await MonthData.calculateCurrentUnrankedValues(mostRecentDateAvailable: rankSourceDate)
}
self.teams = await FileImportManager.shared.createTeams(from: fileContent, tournament: tournament, fileProvider: fileProvider)
await MainActor.run {
convertingFile = false

@ -69,7 +69,9 @@ struct TournamentCellView: View {
}
Spacer()
if let tournament = tournament as? Tournament, displayStyle == .wide {
Text(tournament.sortedTeams().count.formatted())
let hasStarted = tournament.inscriptionClosed() || tournament.hasStarted()
let count = hasStarted ? tournament.selectedSortedTeams().count : tournament.unsortedTeams().count
Text(count.formatted())
} else if let federalTournament = tournament as? FederalTournament {
Button {
_createOrShow(federalTournament: federalTournament, existingTournament: existingTournament, build: build)
@ -89,7 +91,9 @@ struct TournamentCellView: View {
Text(tournament.durationLabel())
Spacer()
if let tournament = tournament as? Tournament {
Text("équipes")
let hasStarted = tournament.inscriptionClosed() || tournament.hasStarted()
let word = hasStarted ? "équipes" : "inscriptions"
Text(word)
}
}
Text(tournament.subtitleLabel())

Loading…
Cancel
Save