online_reg^2
Raz 12 months ago
parent 58ffb56ef5
commit 7a4628208c
  1. 4
      PadelClub.xcodeproj/project.pbxproj
  2. 6
      PadelClub/Data/GroupStage.swift
  3. 2
      PadelClub/Data/Match.swift
  4. 50
      PadelClub/Data/MatchScheduler.swift
  5. 7
      PadelClub/ViewModel/SearchViewModel.swift
  6. 8
      PadelClub/Views/Planning/PlanningSettingsView.swift

@ -3286,7 +3286,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.32;
MARKETING_VERSION = 1.0.33;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -3330,7 +3330,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.32;
MARKETING_VERSION = 1.0.33;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

@ -203,6 +203,10 @@ final class GroupStage: ModelObject, Storable {
}
}
func orderedIndexOfMatch(_ match: Match) -> Int {
_matchOrder()[safe: match.index] ?? match.index
}
func updateGroupStageState() {
clearScoreCache()
@ -368,7 +372,7 @@ final class GroupStage: ModelObject, Storable {
_matchOrder().firstIndex(of: matchIndex) ?? matchIndex
}
private func _matchUp(for matchIndex: Int) -> [Int] {
func _matchUp(for matchIndex: Int) -> [Int] {
let combinations = Array((0..<size).combinations(ofCount: 2))
return combinations[safe: matchIndex%matchCount] ?? []
}

@ -738,7 +738,7 @@ defer {
func canBeStarted(inMatches matches: [Match], checkCanPlay: Bool) -> Bool {
let teams = teamScores
guard teams.count == 2 else {
print("teams.count != 2")
//print("teams.count != 2")
return false
}
guard hasEnded() == false else { return false }

@ -32,6 +32,7 @@ final class MatchScheduler : ModelObject, Storable {
var overrideCourtsUnavailability: Bool = false
var shouldTryToFillUpCourtsAvailable: Bool = true
var courtsAvailable: Set<Int> = Set<Int>()
var simultaneousStart: Bool = true
init(tournament: String,
timeDifferenceLimit: Int = 5,
@ -46,7 +47,8 @@ final class MatchScheduler : ModelObject, Storable {
groupStageChunkCount: Int? = nil,
overrideCourtsUnavailability: Bool = false,
shouldTryToFillUpCourtsAvailable: Bool = true,
courtsAvailable: Set<Int> = Set<Int>()) {
courtsAvailable: Set<Int> = Set<Int>(),
simultaneousStart: Bool = true) {
self.tournament = tournament
self.timeDifferenceLimit = timeDifferenceLimit
self.loserBracketRotationDifference = loserBracketRotationDifference
@ -61,6 +63,7 @@ final class MatchScheduler : ModelObject, Storable {
self.overrideCourtsUnavailability = overrideCourtsUnavailability
self.shouldTryToFillUpCourtsAvailable = shouldTryToFillUpCourtsAvailable
self.courtsAvailable = courtsAvailable
self.simultaneousStart = simultaneousStart
}
enum CodingKeys: String, CodingKey {
@ -79,6 +82,7 @@ final class MatchScheduler : ModelObject, Storable {
case _overrideCourtsUnavailability = "overrideCourtsUnavailability"
case _shouldTryToFillUpCourtsAvailable = "shouldTryToFillUpCourtsAvailable"
case _courtsAvailable = "courtsAvailable"
case _simultaneousStart = "simultaneousStart"
}
var courtsUnavailability: [DateInterval]? {
@ -185,14 +189,18 @@ final class MatchScheduler : ModelObject, Storable {
// Get the maximum count of matches in any group
let maxMatchesCount = _groupStages.map { $0._matches().count }.max() ?? 0
// Flatten matches in a round-robin order by cycling through each group
let flattenedMatches = (0..<maxMatchesCount).flatMap { index in
_groupStages.compactMap { group in
// Safely access matches, return nil if index is out of bounds
let playedMatches = group.playedMatches()
return playedMatches.indices.contains(index) ? playedMatches[index] : nil
var flattenedMatches = [Match]()
if simultaneousStart {
// Flatten matches in a round-robin order by cycling through each group
flattenedMatches = (0..<maxMatchesCount).flatMap { index in
_groupStages.compactMap { group in
// Safely access matches, return nil if index is out of bounds
let playedMatches = group.playedMatches()
return playedMatches.indices.contains(index) ? playedMatches[index] : nil
}
}
} else {
flattenedMatches = _groupStages.flatMap({ $0.playedMatches() })
}
var slots = [GroupStageTimeMatch]()
@ -214,17 +222,21 @@ final class MatchScheduler : ModelObject, Storable {
let counts = Dictionary(previousRotationBracketIndexes, uniquingKeysWith: +)
var rotationMatches = Array(availableMatches.filter({ match in
// Check if all teams from the match are not already scheduled in the current rotation
let teamsAvailable = teamsPerRotation[rotationIndex]!.allSatisfy({ !match.containsTeamId($0) })
let teamsAvailable = teamsPerRotation[rotationIndex]!.allSatisfy({ !match.containsTeamIndex($0) })
if !teamsAvailable {
print("Match \(match.roundAndMatchTitle()) has teams already scheduled in rotation \(rotationIndex)")
}
return teamsAvailable
}).prefix(courtsAvailable.count))
}))
if rotationIndex > 0 {
rotationMatches = rotationMatches.sorted(by: {
if counts[$0.groupStageObject!.index] ?? 0 == counts[$1.groupStageObject!.index] ?? 0 {
return $0.groupStageObject!.index < $1.groupStageObject!.index
if simultaneousStart {
return $0.groupStageObject!.orderedIndexOfMatch($0) < $1.groupStageObject!.orderedIndexOfMatch($1)
} else {
return $0.groupStageObject!.index < $1.groupStageObject!.index
}
} else {
return counts[$0.groupStageObject!.index] ?? 0 < counts[$1.groupStageObject!.index] ?? 0
}
@ -245,7 +257,7 @@ final class MatchScheduler : ModelObject, Storable {
return false
}
let teamsAvailable = teamsPerRotation[rotationIndex]!.allSatisfy({ !match.containsTeamId($0) })
let teamsAvailable = teamsPerRotation[rotationIndex]!.allSatisfy({ !match.containsTeamIndex($0) })
if !teamsAvailable {
print("Teams from match \(match.roundAndMatchTitle()) are already scheduled in this rotation")
return false
@ -259,7 +271,7 @@ final class MatchScheduler : ModelObject, Storable {
print("Scheduled match: \(first.roundAndMatchTitle()) on court \(courtIndex) at rotation \(rotationIndex)")
slots.append(timeMatch)
teamsPerRotation[rotationIndex]!.append(contentsOf: first.teamIds())
teamsPerRotation[rotationIndex]!.append(contentsOf: first.matchUp())
rotationMatches.removeAll(where: { $0.id == first.id })
availableMatches.removeAll(where: { $0.id == first.id })
@ -891,4 +903,16 @@ extension Match {
func containsTeamId(_ id: String) -> Bool {
return teamIds().contains(id)
}
func containsTeamIndex(_ id: String) -> Bool {
matchUp().contains(id)
}
func matchUp() -> [String] {
guard let groupStageObject else {
return []
}
return groupStageObject._matchUp(for: index).map { groupStageObject.id + "_\($0)" }
}
}

@ -69,9 +69,6 @@ class SearchViewModel: ObservableObject, Identifiable {
var message = ["Vérifiez l'ortographe ou lancez une nouvelle recherche."]
if tokens.isEmpty {
message.append("Il est possible que cette personne n'est joué aucun tournoi depuis les 12 derniers mois, dans ce cas, Padel Club ne pourra pas le trouver.")
if filterOption == .male {
message.append("Depuis août 2024, le classement fédérale disponible est limité aux 40.000 premiers joueurs. Si le joueur n'a pas encore assez de points pour être visible, Padel Club ne pourra pas non plus le trouver.")
}
}
return message.joined(separator: "\n")
}
@ -231,7 +228,7 @@ class SearchViewModel: ObservableObject, Identifiable {
]
if let mostRecentDate {
//predicates.append(NSPredicate(format: "importDate == %@", mostRecentDate as CVarArg))
predicates.append(NSPredicate(format: "importDate == %@", mostRecentDate as CVarArg))
}
if hideAssimilation {
@ -344,7 +341,7 @@ class SearchViewModel: ObservableObject, Identifiable {
}
if let mostRecentDate {
//andPredicates.append(NSPredicate(format: "importDate == %@", mostRecentDate as CVarArg))
andPredicates.append(NSPredicate(format: "importDate == %@", mostRecentDate as CVarArg))
}
if nameComponents.count > 1 {

@ -385,6 +385,14 @@ struct PlanningSettingsView: View {
} footer: {
Text("Vous pouvez indiquer le nombre de poule démarrant en même temps.")
}
Section {
Toggle(isOn: $matchScheduler.simultaneousStart) {
Text("Démarrage simultané")
}
} footer: {
Text("En simultané, un match de chaque poule d'un groupe de poule sera joué avant de passer à la suite de la programmation. Si l'option est désactivée, un maximum de matchs simultanés d'une poule sera programmé avant de passer à la poule suivante.")
}
}
Section {

Loading…
Cancel
Save