|
|
|
|
@ -100,9 +100,9 @@ final class GroupStage: ModelObject, Storable { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func hasEnded() -> Bool { |
|
|
|
|
guard teams().count == size else { return false } |
|
|
|
|
let _matches = _matches() |
|
|
|
|
if _matches.isEmpty { return false } |
|
|
|
|
//guard teams().count == size else { return false } |
|
|
|
|
return _matches.anySatisfy { $0.hasEnded() == false } == false |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -148,6 +148,8 @@ final class GroupStage: ModelObject, Storable { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func updateGroupStageState() { |
|
|
|
|
clearScoreCache() |
|
|
|
|
|
|
|
|
|
if hasEnded(), let tournament = tournamentObject() { |
|
|
|
|
do { |
|
|
|
|
let teams = teams(true) |
|
|
|
|
@ -190,24 +192,24 @@ final class GroupStage: ModelObject, Storable { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func _score(forGroupStagePosition groupStagePosition: Int, nilIfEmpty: Bool = false) -> TeamGroupStageScore? { |
|
|
|
|
guard let team = teamAt(groupStagePosition: groupStagePosition) else { return nil } |
|
|
|
|
let matches = matches(forGroupStagePosition: groupStagePosition).filter({ $0.hasEnded() }) |
|
|
|
|
if matches.isEmpty && nilIfEmpty { return nil } |
|
|
|
|
let wins = matches.filter { $0.winningTeamId == team.id }.count |
|
|
|
|
let loses = matches.filter { $0.losingTeamId == team.id }.count |
|
|
|
|
let differences = matches.compactMap { $0.scoreDifference(groupStagePosition) } |
|
|
|
|
let setDifference = differences.map { $0.set }.reduce(0,+) |
|
|
|
|
let gameDifference = differences.map { $0.game }.reduce(0,+) |
|
|
|
|
return (team, wins, loses, setDifference, gameDifference) |
|
|
|
|
/* |
|
|
|
|
• 2 points par rencontre gagnée |
|
|
|
|
• 1 point par rencontre perdue |
|
|
|
|
• -1 point en cas de rencontre perdue par disqualification (scores de 6/0 6/0 attribués aux trois matchs) |
|
|
|
|
• -2 points en cas de rencontre perdu par WO (scores de 6/0 6/0 attribués aux trois matchs) |
|
|
|
|
*/ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// func _score(forGroupStagePosition groupStagePosition: Int, nilIfEmpty: Bool = false) -> TeamGroupStageScore? { |
|
|
|
|
// guard let team = teamAt(groupStagePosition: groupStagePosition) else { return nil } |
|
|
|
|
// let matches = matches(forGroupStagePosition: groupStagePosition).filter({ $0.hasEnded() }) |
|
|
|
|
// if matches.isEmpty && nilIfEmpty { return nil } |
|
|
|
|
// let wins = matches.filter { $0.winningTeamId == team.id }.count |
|
|
|
|
// let loses = matches.filter { $0.losingTeamId == team.id }.count |
|
|
|
|
// let differences = matches.compactMap { $0.scoreDifference(groupStagePosition, atStep: step) } |
|
|
|
|
// let setDifference = differences.map { $0.set }.reduce(0,+) |
|
|
|
|
// let gameDifference = differences.map { $0.game }.reduce(0,+) |
|
|
|
|
// return (team, wins, loses, setDifference, gameDifference) |
|
|
|
|
// /* |
|
|
|
|
// • 2 points par rencontre gagnée |
|
|
|
|
// • 1 point par rencontre perdue |
|
|
|
|
// • -1 point en cas de rencontre perdue par disqualification (scores de 6/0 6/0 attribués aux trois matchs) |
|
|
|
|
// • -2 points en cas de rencontre perdu par WO (scores de 6/0 6/0 attribués aux trois matchs) |
|
|
|
|
// */ |
|
|
|
|
// } |
|
|
|
|
// |
|
|
|
|
func matches(forGroupStagePosition groupStagePosition: Int) -> [Match] { |
|
|
|
|
let combos = Array((0..<size).combinations(ofCount: 2)) |
|
|
|
|
var matchIndexes = [Int]() |
|
|
|
|
@ -366,10 +368,24 @@ final class GroupStage: ModelObject, Storable { |
|
|
|
|
return self.tournamentStore.teamRegistrations.filter { $0.groupStage == self.id && $0.groupStagePosition != nil } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var scoreCache: [Int: TeamGroupStageScore] = [:] |
|
|
|
|
|
|
|
|
|
func teams(_ sortedByScore: Bool = false, scores: [TeamGroupStageScore]? = nil) -> [TeamRegistration] { |
|
|
|
|
if sortedByScore { |
|
|
|
|
return unsortedTeams().compactMap({ team in |
|
|
|
|
scores?.first(where: { $0.team.id == team.id }) ?? _score(forGroupStagePosition: team.groupStagePositionAtStep(step)!) |
|
|
|
|
// 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)!] { |
|
|
|
|
return cachedScore |
|
|
|
|
} else { |
|
|
|
|
let score = _score(forGroupStagePosition: team.groupStagePositionAtStep(step)!) |
|
|
|
|
if let score = score { |
|
|
|
|
scoreCache[team.groupStagePositionAtStep(step)!] = score |
|
|
|
|
} |
|
|
|
|
return score |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
|
}).sorted { (lhs, rhs) in |
|
|
|
|
let predicates: [TeamScoreAreInIncreasingOrder] = [ |
|
|
|
|
{ $0.wins < $1.wins }, |
|
|
|
|
@ -394,6 +410,71 @@ final class GroupStage: ModelObject, Storable { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func _score(forGroupStagePosition groupStagePosition: Int, nilIfEmpty: Bool = false) -> TeamGroupStageScore? { |
|
|
|
|
// Check if the score for this position is already cached |
|
|
|
|
if let cachedScore = scoreCache[groupStagePosition] { |
|
|
|
|
return cachedScore |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
guard let team = teamAt(groupStagePosition: groupStagePosition) else { return nil } |
|
|
|
|
let matches = matches(forGroupStagePosition: groupStagePosition).filter({ $0.hasEnded() }) |
|
|
|
|
if matches.isEmpty && nilIfEmpty { return nil } |
|
|
|
|
let wins = matches.filter { $0.winningTeamId == team.id }.count |
|
|
|
|
let loses = matches.filter { $0.losingTeamId == team.id }.count |
|
|
|
|
let differences = matches.compactMap { $0.scoreDifference(groupStagePosition, atStep: step) } |
|
|
|
|
let setDifference = differences.map { $0.set }.reduce(0,+) |
|
|
|
|
let gameDifference = differences.map { $0.game }.reduce(0,+) |
|
|
|
|
|
|
|
|
|
// Calculate the score and store it in the cache |
|
|
|
|
let score = (team, wins, loses, setDifference, gameDifference) |
|
|
|
|
scoreCache[groupStagePosition] = score |
|
|
|
|
return score |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Clear the cache if necessary, for example when starting a new step or when matches update |
|
|
|
|
func clearScoreCache() { |
|
|
|
|
scoreCache.removeAll() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// func teams(_ sortedByScore: Bool = false, scores: [TeamGroupStageScore]? = nil) -> [TeamRegistration] { |
|
|
|
|
// if sortedByScore { |
|
|
|
|
// return unsortedTeams().compactMap({ team in |
|
|
|
|
// scores?.first(where: { $0.team.id == team.id }) ?? _score(forGroupStagePosition: team.groupStagePositionAtStep(step)!) |
|
|
|
|
// }).sorted { (lhs, rhs) in |
|
|
|
|
// // Calculate intermediate values once and reuse them |
|
|
|
|
// let lhsWins = lhs.wins |
|
|
|
|
// let rhsWins = rhs.wins |
|
|
|
|
// let lhsSetDifference = lhs.setDifference |
|
|
|
|
// let rhsSetDifference = rhs.setDifference |
|
|
|
|
// let lhsGameDifference = lhs.gameDifference |
|
|
|
|
// let rhsGameDifference = rhs.gameDifference |
|
|
|
|
// let lhsHeadToHead = self._headToHead(lhs.team, rhs.team) |
|
|
|
|
// let rhsHeadToHead = self._headToHead(rhs.team, lhs.team) |
|
|
|
|
// let lhsGroupStagePosition = lhs.team.groupStagePositionAtStep(self.step)! |
|
|
|
|
// let rhsGroupStagePosition = rhs.team.groupStagePositionAtStep(self.step)! |
|
|
|
|
// |
|
|
|
|
// // Define comparison predicates in the same order |
|
|
|
|
// let predicates: [(Bool, Bool)] = [ |
|
|
|
|
// (lhsWins < rhsWins, lhsWins > rhsWins), |
|
|
|
|
// (lhsSetDifference < rhsSetDifference, lhsSetDifference > rhsSetDifference), |
|
|
|
|
// (lhsGameDifference < rhsGameDifference, lhsGameDifference > rhsGameDifference), |
|
|
|
|
// (lhsHeadToHead, rhsHeadToHead), |
|
|
|
|
// (lhsGroupStagePosition > rhsGroupStagePosition, lhsGroupStagePosition < rhsGroupStagePosition) |
|
|
|
|
// ] |
|
|
|
|
// |
|
|
|
|
// // Iterate over predicates and return as soon as a valid comparison is found |
|
|
|
|
// for (lhsPredicate, rhsPredicate) in predicates { |
|
|
|
|
// if lhsPredicate { return true } |
|
|
|
|
// if rhsPredicate { return false } |
|
|
|
|
// } |
|
|
|
|
// |
|
|
|
|
// return false |
|
|
|
|
// }.map({ $0.team }).reversed() |
|
|
|
|
// } else { |
|
|
|
|
// return unsortedTeams().sorted(by: \TeamRegistration.groupStagePosition!) |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
func updateMatchFormat(_ updatedMatchFormat: MatchFormat) { |
|
|
|
|
self.matchFormat = updatedMatchFormat |
|
|
|
|
self.updateAllMatchesFormat() |
|
|
|
|
|