Raz 8 months ago
parent fdfe9b92ee
commit 289056bcd0
  1. 4
      PadelClub.xcodeproj/project.pbxproj
  2. 16
      PadelClub/Data/GroupStage.swift
  3. 12
      PadelClub/Views/Calling/CallView.swift
  4. 81
      PadelClub/Views/GroupStage/GroupStagesView.swift
  5. 2
      PadelClub/Views/Tournament/Screen/TableStructureView.swift

@ -3318,7 +3318,7 @@
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements; CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 2;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
@ -3364,7 +3364,7 @@
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements; CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 2;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6; DEVELOPMENT_TEAM = BQ3Y44M3Q6;

@ -438,7 +438,7 @@ final class GroupStage: ModelObject, Storable {
unsortedTeams().flatMap({ $0.unsortedPlayers() }) unsortedTeams().flatMap({ $0.unsortedPlayers() })
} }
fileprivate typealias TeamScoreAreInIncreasingOrder = (TeamGroupStageScore, TeamGroupStageScore) -> Bool typealias TeamScoreAreInIncreasingOrder = (TeamGroupStageScore, TeamGroupStageScore) -> Bool
typealias TeamGroupStageScore = (team: TeamRegistration, wins: Int, loses: Int, setDifference: Int, gameDifference: Int) typealias TeamGroupStageScore = (team: TeamRegistration, wins: Int, loses: Int, setDifference: Int, gameDifference: Int)
@ -492,11 +492,7 @@ final class GroupStage: ModelObject, Storable {
var scoreCache: [Int: TeamGroupStageScore] = [:] var scoreCache: [Int: TeamGroupStageScore] = [:]
func teams(_ sortedByScore: Bool = false, scores: [TeamGroupStageScore]? = nil) -> [TeamRegistration] { func computedScore(forTeam team: TeamRegistration, step: Int = 0) -> TeamGroupStageScore? {
if sortedByScore {
return unsortedTeams().compactMap({ team in
// Check cache or use provided scores, otherwise calculate and store in cache
scores?.first(where: { $0.team.id == team.id }) ?? {
if let cachedScore = scoreCache[team.groupStagePositionAtStep(step)!] { if let cachedScore = scoreCache[team.groupStagePositionAtStep(step)!] {
return cachedScore return cachedScore
} else { } else {
@ -506,6 +502,14 @@ final class GroupStage: ModelObject, Storable {
} }
return score return score
} }
}
func teams(_ sortedByScore: Bool = false, scores: [TeamGroupStageScore]? = nil) -> [TeamRegistration] {
if sortedByScore {
return unsortedTeams().compactMap({ team in
// Check cache or use provided scores, otherwise calculate and store in cache
scores?.first(where: { $0.team.id == team.id }) ?? {
return computedScore(forTeam: team, step: step)
}() }()
}).sorted { (lhs, rhs) in }).sorted { (lhs, rhs) in
let predicates: [TeamScoreAreInIncreasingOrder] = [ let predicates: [TeamScoreAreInIncreasingOrder] = [

@ -199,14 +199,16 @@ struct CallView: View {
let uncalledTeams = teams.filter { $0.getPhoneNumbers().isEmpty } let uncalledTeams = teams.filter { $0.getPhoneNumbers().isEmpty }
if networkMonitor.connected == false { if networkMonitor.connected == false {
if uncalledTeams.isEmpty == false { if uncalledTeams.isEmpty == false, calledTeams.isEmpty == false {
self.sentError = .uncalledTeams(uncalledTeams) self.sentError = .uncalledTeams(uncalledTeams)
} else { } else {
self.sentError = .messageNotSent self.sentError = .messageNotSent
} }
} else { } else {
if uncalledTeams.isEmpty == false { if uncalledTeams.isEmpty == false, calledTeams.isEmpty == false {
self.sentError = .uncalledTeams(uncalledTeams) self.sentError = .uncalledTeams(uncalledTeams)
} else if uncalledTeams.isEmpty == false, calledTeams.isEmpty {
self._called(uncalledTeams, true)
} }
self._called(calledTeams, true) self._called(calledTeams, true)
} }
@ -228,14 +230,16 @@ struct CallView: View {
if networkMonitor.connected == false { if networkMonitor.connected == false {
self.contactType = nil self.contactType = nil
if uncalledTeams.isEmpty == false { if uncalledTeams.isEmpty == false, calledTeams.isEmpty == false {
self.sentError = .uncalledTeams(uncalledTeams) self.sentError = .uncalledTeams(uncalledTeams)
} else { } else {
self.sentError = .mailNotSent self.sentError = .mailNotSent
} }
} else { } else {
if uncalledTeams.isEmpty == false { if uncalledTeams.isEmpty == false, calledTeams.isEmpty == false {
self.sentError = .uncalledTeams(uncalledTeams) self.sentError = .uncalledTeams(uncalledTeams)
} else if uncalledTeams.isEmpty == false, calledTeams.isEmpty {
self._called(uncalledTeams, true)
} }
self._called(calledTeams, true) self._called(calledTeams, true)
} }

@ -106,6 +106,80 @@ struct GroupStagesView: View {
return allDestinations return allDestinations
} }
func sortedTeams(missingQualifiedFromGroupStages: [TeamRegistration]) -> [GroupStage.TeamGroupStageScore] {
let sortedTeams = missingQualifiedFromGroupStages.compactMap({ team in
team.groupStageObject()?.computedScore(forTeam: team)
}).sorted { (lhs, rhs) in
let predicates: [GroupStage.TeamScoreAreInIncreasingOrder] = [
{ $0.wins < $1.wins },
{ $0.setDifference < $1.setDifference },
{ $0.gameDifference < $1.gameDifference},
]
for predicate in predicates {
if !predicate(lhs, rhs) && !predicate(rhs, lhs) {
continue
}
return predicate(lhs, rhs)
}
return false
}
return sortedTeams
}
func _sortedAdditionnalTeams(missingQualifiedFromGroupStages: [TeamRegistration]) -> some View {
Section {
let teamGroupStageScores = self.sortedTeams(missingQualifiedFromGroupStages: missingQualifiedFromGroupStages).reversed()
ForEach(teamGroupStageScores, id: \.team.id) { teamGroupStageScore in
let team = teamGroupStageScore.team
let groupStage = team.groupStageObject()!
let groupStagePosition = team.groupStagePosition!
NavigationLink {
GroupStageTeamView(groupStage: groupStage, team: team)
.environment(self.tournament)
} label: {
HStack {
VStack(alignment: .leading) {
if let teamName = team.name, teamName.isEmpty == false {
Text(teamName).foregroundStyle(.secondary).font(.footnote)
}
ForEach(team.players()) { player in
Text(player.playerLabel()).lineLimit(1)
}
}
Spacer()
if let score = groupStage.scoreLabel(forGroupStagePosition: groupStagePosition, score: teamGroupStageScore) {
VStack(alignment: .trailing) {
HStack(spacing: 0.0) {
Text(score.wins)
Text("/")
Text(score.losses)
}.font(.headline).monospacedDigit()
if let setsDifference = score.setsDifference {
HStack(spacing: 4.0) {
Text(setsDifference)
}.font(.footnote)
}
if let gamesDifference = score.gamesDifference {
HStack(spacing: 4.0) {
Text(gamesDifference)
}.font(.footnote)
}
}
}
}
}
}
} header: {
let name = "\((tournament.qualifiedPerGroupStage + 1).ordinalFormatted())"
Text("Meilleurs \(name) de poule")
}
}
var body: some View { var body: some View {
VStack(spacing: 0) { VStack(spacing: 0) {
GenericDestinationPickerView(selectedDestination: $selectedDestination, destinations: allDestinations(), nilDestinationIsValid: true) GenericDestinationPickerView(selectedDestination: $selectedDestination, destinations: allDestinations(), nilDestinationIsValid: true)
@ -116,9 +190,8 @@ struct GroupStagesView: View {
List { List {
if tournament.groupStageAdditionalQualified > 0 { if tournament.groupStageAdditionalQualified > 0 {
let missingQualifiedFromGroupStages = tournament.missingQualifiedFromGroupStages() let missingQualifiedFromGroupStages = tournament.missingQualifiedFromGroupStages()
Section {
let name = "\((tournament.qualifiedPerGroupStage + 1).ordinalFormatted())" let name = "\((tournament.qualifiedPerGroupStage + 1).ordinalFormatted())"
Section {
NavigationLink { NavigationLink {
SpinDrawView(drawees: ["Qualification d'un \(name) de poule"], segments: missingQualifiedFromGroupStages) { results in SpinDrawView(drawees: ["Qualification d'un \(name) de poule"], segments: missingQualifiedFromGroupStages) { results in
results.forEach { drawResult in results.forEach { drawResult in
@ -134,6 +207,8 @@ struct GroupStagesView: View {
Text("Qualifier un \(name) de poule par tirage au sort") Text("Qualifier un \(name) de poule par tirage au sort")
} }
.disabled(tournament.moreQualifiedToDraw() == 0 || missingQualifiedFromGroupStages.isEmpty) .disabled(tournament.moreQualifiedToDraw() == 0 || missingQualifiedFromGroupStages.isEmpty)
} header: {
Text("Tirage au sort d'un \(name) de poule")
} footer: { } footer: {
if tournament.moreQualifiedToDraw() == 0 { if tournament.moreQualifiedToDraw() == 0 {
Text("Aucune équipe supplémentaire à qualifier. Vous pouvez en rajouter en modifier le paramètre dans structure.") Text("Aucune équipe supplémentaire à qualifier. Vous pouvez en rajouter en modifier le paramètre dans structure.")
@ -141,6 +216,8 @@ struct GroupStagesView: View {
Text("Aucune équipe supplémentaire à tirer au sort. Attendez la fin des poules.") Text("Aucune équipe supplémentaire à tirer au sort. Attendez la fin des poules.")
} }
} }
_sortedAdditionnalTeams(missingQualifiedFromGroupStages: missingQualifiedFromGroupStages)
} }
let runningMatches = Tournament.runningMatches(allMatches) let runningMatches = Tournament.runningMatches(allMatches)

@ -45,7 +45,7 @@ struct TableStructureView: View {
var moreQualifiedLabel: String { var moreQualifiedLabel: String {
if groupStageAdditionalQualified == 0 { return "Aucun" } if groupStageAdditionalQualified == 0 { return "Aucun" }
return (groupStageAdditionalQualified > 1 ? "les \(groupStageAdditionalQualified)" : "le") + " meilleur\(groupStageAdditionalQualified.pluralSuffix) " + (qualifiedPerGroupStage + 1).ordinalFormatted() return (groupStageAdditionalQualified > 1 ? "les \(groupStageAdditionalQualified)" : "le") + " " + (qualifiedPerGroupStage + 1).ordinalFormatted()
} }
var maxGroupStages: Int { var maxGroupStages: Int {

Loading…
Cancel
Save