|
|
|
@ -347,9 +347,24 @@ final class Tournament : ModelObject, Storable { |
|
|
|
|
|
|
|
|
|
|
|
override func deleteDependencies() throws { |
|
|
|
override func deleteDependencies() throws { |
|
|
|
let store = self.tournamentStore |
|
|
|
let store = self.tournamentStore |
|
|
|
store.teamRegistrations.deleteDependencies(self.unsortedTeams()) |
|
|
|
let teams = self.unsortedTeams() |
|
|
|
store.groupStages.deleteDependencies(self.groupStages()) |
|
|
|
for team in teams { |
|
|
|
store.rounds.deleteDependencies(self.rounds()) |
|
|
|
try team.deleteDependencies() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
store.teamRegistrations.deleteDependencies(teams) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let groups = self.groupStages() |
|
|
|
|
|
|
|
for group in groups { |
|
|
|
|
|
|
|
try group.deleteDependencies() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
store.groupStages.deleteDependencies(groups) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let rounds = self.rounds() |
|
|
|
|
|
|
|
for round in rounds { |
|
|
|
|
|
|
|
try round.deleteDependencies() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
store.rounds.deleteDependencies(rounds) |
|
|
|
|
|
|
|
|
|
|
|
store.matchSchedulers.deleteDependencies(self._matchSchedulers()) |
|
|
|
store.matchSchedulers.deleteDependencies(self._matchSchedulers()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -792,6 +807,12 @@ defer { |
|
|
|
return teams + waitingListTeams(in: teams) |
|
|
|
return teams + waitingListTeams(in: teams) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func waitingListSortedTeams() -> [TeamRegistration] { |
|
|
|
|
|
|
|
let teams = selectedSortedTeams() |
|
|
|
|
|
|
|
return waitingListTeams(in: teams) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func selectedSortedTeams() -> [TeamRegistration] { |
|
|
|
func selectedSortedTeams() -> [TeamRegistration] { |
|
|
|
#if DEBUG_TIME //DEBUGING TIME |
|
|
|
#if DEBUG_TIME //DEBUGING TIME |
|
|
|
let start = Date() |
|
|
|
let start = Date() |
|
|
|
@ -860,7 +881,7 @@ defer { |
|
|
|
return waitingList.filter { $0.walkOut == false }.sorted(using: _defaultSorting(), order: .ascending) + waitingList.filter { $0.walkOut == true }.sorted(using: _defaultSorting(), order: .ascending) |
|
|
|
return waitingList.filter { $0.walkOut == false }.sorted(using: _defaultSorting(), order: .ascending) + waitingList.filter { $0.walkOut == true }.sorted(using: _defaultSorting(), order: .ascending) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func bracketCut() -> Int { |
|
|
|
func bracketCut(teamCount: Int) -> Int { |
|
|
|
return max(0, teamCount - groupStageCut()) |
|
|
|
return max(0, teamCount - groupStageCut()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -868,10 +889,12 @@ defer { |
|
|
|
return groupStageSpots() |
|
|
|
return groupStageSpots() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func cutLabel(index: Int) -> String { |
|
|
|
func cutLabel(index: Int, teamCount: Int?) -> String { |
|
|
|
if index < bracketCut() { |
|
|
|
let _teamCount = teamCount ?? selectedSortedTeams().count |
|
|
|
|
|
|
|
let bracketCut = bracketCut(teamCount: _teamCount) |
|
|
|
|
|
|
|
if index < bracketCut { |
|
|
|
return "Tableau" |
|
|
|
return "Tableau" |
|
|
|
} else if index - bracketCut() < groupStageCut() { |
|
|
|
} else if index - bracketCut < groupStageCut() && _teamCount > 0 { |
|
|
|
return "Poule" |
|
|
|
return "Poule" |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return "Attente" |
|
|
|
return "Attente" |
|
|
|
@ -1172,12 +1195,12 @@ defer { |
|
|
|
let disabledIds = playedMatches.flatMap({ $0.teamScores.compactMap({ $0.teamRegistration }) }).filter({ ids.contains($0) == false }) |
|
|
|
let disabledIds = playedMatches.flatMap({ $0.teamScores.compactMap({ $0.teamRegistration }) }).filter({ ids.contains($0) == false }) |
|
|
|
if disabledIds.isEmpty == false { |
|
|
|
if disabledIds.isEmpty == false { |
|
|
|
_removeStrings(from: &teams, stringsToRemove: disabledIds) |
|
|
|
_removeStrings(from: &teams, stringsToRemove: disabledIds) |
|
|
|
teams[interval.computedLast] = disabledIds |
|
|
|
teams[interval.last] = disabledIds |
|
|
|
let teamNames : [String] = disabledIds.compactMap { |
|
|
|
let teamNames : [String] = disabledIds.compactMap { |
|
|
|
let t : TeamRegistration? = Store.main.findById($0) |
|
|
|
let t : TeamRegistration? = Store.main.findById($0) |
|
|
|
return t |
|
|
|
return t |
|
|
|
}.map { $0.canonicalName } |
|
|
|
}.map { $0.canonicalName } |
|
|
|
print("winners.isEmpty", "\(interval.computedLast) : ", teamNames) |
|
|
|
print("winners.isEmpty", "\(interval.last) : ", teamNames) |
|
|
|
disabledIds.forEach { |
|
|
|
disabledIds.forEach { |
|
|
|
ids.insert($0) |
|
|
|
ids.insert($0) |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1185,23 +1208,23 @@ defer { |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if winners.isEmpty == false { |
|
|
|
if winners.isEmpty == false { |
|
|
|
_removeStrings(from: &teams, stringsToRemove: winners) |
|
|
|
_removeStrings(from: &teams, stringsToRemove: winners) |
|
|
|
teams[interval.computedFirst + winners.count - 1] = winners |
|
|
|
teams[interval.first + winners.count - 1] = winners |
|
|
|
let teamNames : [String] = winners.compactMap { |
|
|
|
let teamNames : [String] = winners.compactMap { |
|
|
|
let t: TeamRegistration? = Store.main.findById($0) |
|
|
|
let t: TeamRegistration? = Store.main.findById($0) |
|
|
|
return t |
|
|
|
return t |
|
|
|
}.map { $0.canonicalName } |
|
|
|
}.map { $0.canonicalName } |
|
|
|
print("winners", "\(interval.computedFirst + winners.count - 1) : ", teamNames) |
|
|
|
print("winners", "\(interval.last + winners.count - 1) : ", teamNames) |
|
|
|
winners.forEach { ids.insert($0) } |
|
|
|
winners.forEach { ids.insert($0) } |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if losers.isEmpty == false { |
|
|
|
if losers.isEmpty == false { |
|
|
|
_removeStrings(from: &teams, stringsToRemove: losers) |
|
|
|
_removeStrings(from: &teams, stringsToRemove: losers) |
|
|
|
teams[interval.computedLast] = losers |
|
|
|
teams[interval.last] = losers |
|
|
|
let loserTeamNames : [String] = losers.compactMap { |
|
|
|
let loserTeamNames : [String] = losers.compactMap { |
|
|
|
let t: TeamRegistration? = Store.main.findById($0) |
|
|
|
let t: TeamRegistration? = Store.main.findById($0) |
|
|
|
return t |
|
|
|
return t |
|
|
|
}.map { $0.canonicalName } |
|
|
|
}.map { $0.canonicalName } |
|
|
|
print("losers", "\(interval.computedLast) : ", loserTeamNames) |
|
|
|
print("losers", "\(interval.last) : ", loserTeamNames) |
|
|
|
losers.forEach { ids.insert($0) } |
|
|
|
losers.forEach { ids.insert($0) } |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1514,6 +1537,7 @@ defer { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func deleteAndBuildEverything() { |
|
|
|
func deleteAndBuildEverything() { |
|
|
|
|
|
|
|
resetBracketPosition() |
|
|
|
deleteStructure() |
|
|
|
deleteStructure() |
|
|
|
deleteGroupStages() |
|
|
|
deleteGroupStages() |
|
|
|
buildGroupStages() |
|
|
|
buildGroupStages() |
|
|
|
@ -1527,7 +1551,7 @@ defer { |
|
|
|
|
|
|
|
|
|
|
|
var _groupStages = [GroupStage]() |
|
|
|
var _groupStages = [GroupStage]() |
|
|
|
for index in 0..<groupStageCount { |
|
|
|
for index in 0..<groupStageCount { |
|
|
|
let groupStage = GroupStage(tournament: id, index: index, size: teamsPerGroupStage, matchFormat: groupStageMatchFormat) |
|
|
|
let groupStage = GroupStage(tournament: id, index: index, size: teamsPerGroupStage, matchFormat: groupStageSmartMatchFormat()) |
|
|
|
_groupStages.append(groupStage) |
|
|
|
_groupStages.append(groupStage) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -1550,7 +1574,7 @@ defer { |
|
|
|
let roundCount = RoundRule.numberOfRounds(forTeams: bracketTeamCount()) |
|
|
|
let roundCount = RoundRule.numberOfRounds(forTeams: bracketTeamCount()) |
|
|
|
|
|
|
|
|
|
|
|
let rounds = (0..<roundCount).map { //index 0 is the final |
|
|
|
let rounds = (0..<roundCount).map { //index 0 is the final |
|
|
|
Round(tournament: id, index: $0) |
|
|
|
return Round(tournament: id, index: $0, matchFormat: roundSmartMatchFormat($0)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
do { |
|
|
|
do { |
|
|
|
@ -1563,7 +1587,7 @@ defer { |
|
|
|
let matches = (0..<matchCount).map { //0 is final match |
|
|
|
let matches = (0..<matchCount).map { //0 is final match |
|
|
|
let roundIndex = RoundRule.roundIndex(fromMatchIndex: $0) |
|
|
|
let roundIndex = RoundRule.roundIndex(fromMatchIndex: $0) |
|
|
|
let round = rounds[roundIndex] |
|
|
|
let round = rounds[roundIndex] |
|
|
|
return Match(round: round.id, index: $0, matchFormat: matchFormat, name: Match.setServerTitle(upperRound: round, matchIndex: RoundRule.matchIndexWithinRound(fromMatchIndex: $0))) |
|
|
|
return Match(round: round.id, index: $0, matchFormat: round.matchFormat, name: Match.setServerTitle(upperRound: round, matchIndex: RoundRule.matchIndexWithinRound(fromMatchIndex: $0))) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
print(matches.map { |
|
|
|
print(matches.map { |
|
|
|
@ -1576,7 +1600,7 @@ defer { |
|
|
|
Logger.error(error) |
|
|
|
Logger.error(error) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
self.rounds().forEach { round in |
|
|
|
rounds.forEach { round in |
|
|
|
round.buildLoserBracket() |
|
|
|
round.buildLoserBracket() |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1609,6 +1633,9 @@ defer { |
|
|
|
} catch { |
|
|
|
} catch { |
|
|
|
Logger.error(error) |
|
|
|
Logger.error(error) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func resetBracketPosition() { |
|
|
|
unsortedTeams().forEach({ $0.bracketPosition = nil }) |
|
|
|
unsortedTeams().forEach({ $0.bracketPosition = nil }) |
|
|
|
do { |
|
|
|
do { |
|
|
|
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: unsortedTeams()) |
|
|
|
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: unsortedTeams()) |
|
|
|
@ -1623,16 +1650,6 @@ defer { |
|
|
|
} catch { |
|
|
|
} catch { |
|
|
|
Logger.error(error) |
|
|
|
Logger.error(error) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
|
|
|
unsortedTeams().forEach({ |
|
|
|
|
|
|
|
$0.groupStage = nil |
|
|
|
|
|
|
|
$0.groupStagePosition = nil |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
try self.tournamentStore.teamRegistrations.addOrUpdate(contentOfs: unsortedTeams()) |
|
|
|
|
|
|
|
} catch { |
|
|
|
|
|
|
|
Logger.error(error) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func refreshGroupStages() { |
|
|
|
func refreshGroupStages() { |
|
|
|
@ -1774,7 +1791,7 @@ defer { |
|
|
|
teamSorting = newValue.defaultTeamSortingType |
|
|
|
teamSorting = newValue.defaultTeamSortingType |
|
|
|
groupStageMatchFormat = groupStageSmartMatchFormat() |
|
|
|
groupStageMatchFormat = groupStageSmartMatchFormat() |
|
|
|
loserBracketMatchFormat = loserBracketSmartMatchFormat(1) |
|
|
|
loserBracketMatchFormat = loserBracketSmartMatchFormat(1) |
|
|
|
matchFormat = roundSmartMatchFormat(1) |
|
|
|
matchFormat = roundSmartMatchFormat(5) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|