|
|
|
|
@ -66,6 +66,58 @@ class Match: ModelObject, Storable { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func isSeededBy(team: TeamRegistration, inTeamPosition teamPosition: TeamPosition) -> Bool { |
|
|
|
|
guard let bracketPosition = team.bracketPosition else { return false } |
|
|
|
|
return index * 2 + teamPosition.rawValue == bracketPosition |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func resetMatch() { |
|
|
|
|
losingTeamId = nil |
|
|
|
|
winningTeamId = nil |
|
|
|
|
endDate = nil |
|
|
|
|
court = nil |
|
|
|
|
servingTeamId = nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func teamWillBeWalkOut(_ team: TeamRegistration) { |
|
|
|
|
resetMatch() |
|
|
|
|
let previousScores = teamScores.filter({ $0.luckyLoser != nil }) |
|
|
|
|
try? DataStore.shared.teamScores.delete(contentOfs: previousScores) |
|
|
|
|
|
|
|
|
|
if let existingTeamScore = teamScore(ofTeam: team) { |
|
|
|
|
try? DataStore.shared.teamScores.delete(instance: existingTeamScore) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let teamScoreWalkout = TeamScore(match: id, teamRegistration: team.id) |
|
|
|
|
teamScoreWalkout.walkOut = 1 |
|
|
|
|
try? DataStore.shared.teamScores.addOrUpdate(instance: teamScoreWalkout) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func luckyLosers() -> [TeamRegistration] { |
|
|
|
|
roundObject?.previousRound()?.losers() ?? [] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func isWalkOutSpot(_ teamPosition: TeamPosition) -> Bool { |
|
|
|
|
teamScore(teamPosition)?.walkOut == 1 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func setLuckyLoser(team: TeamRegistration, teamPosition: TeamPosition) { |
|
|
|
|
resetMatch() |
|
|
|
|
let previousScores = teamScores.filter({ $0.luckyLoser != nil }) |
|
|
|
|
try? DataStore.shared.teamScores.delete(contentOfs: previousScores) |
|
|
|
|
|
|
|
|
|
if let existingTeamScore = teamScore(ofTeam: team) { |
|
|
|
|
try? DataStore.shared.teamScores.delete(instance: existingTeamScore) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let matchIndex = index |
|
|
|
|
let seedRound = RoundRule.roundIndex(fromMatchIndex: matchIndex) |
|
|
|
|
let position = matchIndex * 2 + teamPosition.rawValue |
|
|
|
|
let teamScoreLuckyLoser = TeamScore(match: id, teamRegistration: team.id) |
|
|
|
|
teamScoreLuckyLoser.luckyLoser = position |
|
|
|
|
try? DataStore.shared.teamScores.addOrUpdate(instance: teamScoreLuckyLoser) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func disableMatch() { |
|
|
|
|
_toggleMatchDisableState(true) |
|
|
|
|
} |
|
|
|
|
@ -121,8 +173,16 @@ class Match: ModelObject, Storable { |
|
|
|
|
}.sorted(by: \.index).first |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func previousMatch(_ teamPosition: Int) -> Match? { |
|
|
|
|
if teamPosition == 0 { |
|
|
|
|
func upperBracketMatch(_ teamPosition: TeamPosition) -> Match? { |
|
|
|
|
if teamPosition == .one { |
|
|
|
|
return roundObject?.upperBracketTopMatch(ofMatchIndex: index) |
|
|
|
|
} else { |
|
|
|
|
return roundObject?.upperBracketBottomMatch(ofMatchIndex: index) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func previousMatch(_ teamPosition: TeamPosition) -> Match? { |
|
|
|
|
if teamPosition == .one { |
|
|
|
|
return topPreviousRoundMatch() |
|
|
|
|
} else { |
|
|
|
|
return bottomPreviousRoundMatch() |
|
|
|
|
@ -146,10 +206,10 @@ class Match: ModelObject, Storable { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func setWalkOut(_ whichTeam: TeamData) { |
|
|
|
|
let teamScoreWalkout = teamScore(whichTeam) ?? TeamScore(match: id, teamRegistration: team(whichTeam)?.id) |
|
|
|
|
func setWalkOut(_ teamPosition: TeamPosition) { |
|
|
|
|
let teamScoreWalkout = teamScore(teamPosition) ?? TeamScore(match: id, teamRegistration: team(teamPosition)?.id) |
|
|
|
|
teamScoreWalkout.walkOut = 0 |
|
|
|
|
let teamScoreWinning = teamScore(whichTeam.otherTeam) ?? TeamScore(match: id, teamRegistration: team(whichTeam.otherTeam)?.id) |
|
|
|
|
let teamScoreWinning = teamScore(teamPosition.otherTeam) ?? TeamScore(match: id, teamRegistration: team(teamPosition.otherTeam)?.id) |
|
|
|
|
teamScoreWinning.walkOut = nil |
|
|
|
|
try? DataStore.shared.teamScores.addOrUpdate(contentOfs: [teamScoreWalkout, teamScoreWinning]) |
|
|
|
|
|
|
|
|
|
@ -301,10 +361,10 @@ class Match: ModelObject, Storable { |
|
|
|
|
return [roundProjectedTeam(.one), roundProjectedTeam(.two)].compactMap { $0 } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func scoreDifference(_ whichTeam: Int) -> (set: Int, game: Int)? { |
|
|
|
|
func scoreDifference(_ teamPosition: Int) -> (set: Int, game: Int)? { |
|
|
|
|
guard let teamScoreTeam = teamScore(.one), let teamScoreOtherTeam = teamScore(.two) else { return nil } |
|
|
|
|
var reverseValue = 1 |
|
|
|
|
if whichTeam == team(.two)?.groupStagePosition { |
|
|
|
|
if teamPosition == team(.two)?.groupStagePosition { |
|
|
|
|
reverseValue = -1 |
|
|
|
|
} |
|
|
|
|
let endedSetsOne = teamScoreTeam.score?.components(separatedBy: ",").compactMap({ Int($0) }) ?? matchFormat.defaultWalkOutScore(teamScoreTeam.isWalkOut()) |
|
|
|
|
@ -320,76 +380,14 @@ class Match: ModelObject, Storable { |
|
|
|
|
return (setDifference * reverseValue, gameDifference * reverseValue) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func groupStageProjectedTeam(_ team: TeamData) -> TeamRegistration? { |
|
|
|
|
func groupStageProjectedTeam(_ team: TeamPosition) -> TeamRegistration? { |
|
|
|
|
guard let groupStageObject else { return nil } |
|
|
|
|
return groupStageObject.team(whichTeam: team, inMatchIndex: index) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func seed(_ team: TeamData) -> TeamRegistration? { |
|
|
|
|
guard let roundObject else { return nil } |
|
|
|
|
return Store.main.filter(isIncluded: { |
|
|
|
|
$0.tournament == roundObject.tournament && $0.bracketPosition != nil |
|
|
|
|
}).first(where: { |
|
|
|
|
($0.bracketPosition! / 2) == self.index |
|
|
|
|
&& ($0.bracketPosition! % 2) == team.rawValue |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func isBye() -> Bool { |
|
|
|
|
guard let roundObject else { return false } |
|
|
|
|
return topPreviousRoundMatch()?.disabled == true || bottomPreviousRoundMatch()?.disabled == true |
|
|
|
|
return groupStageObject.team(teamPosition: team, inMatchIndex: index) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func upperBracketTopMatch() -> Match? { |
|
|
|
|
guard let roundObject else { return nil } |
|
|
|
|
let indexInRound = RoundRule.matchIndexWithinRound(fromMatchIndex: index) |
|
|
|
|
if roundObject.isLoserBracket(), roundObject.previousRound() == nil, let parentRound = roundObject.parentRound, let upperBracketTopMatch = parentRound.getMatch(atMatchIndexInRound: indexInRound * 2) { |
|
|
|
|
return upperBracketTopMatch |
|
|
|
|
} |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func upperBracketBottomMatch() -> Match? { |
|
|
|
|
guard let roundObject else { return nil } |
|
|
|
|
let indexInRound = RoundRule.matchIndexWithinRound(fromMatchIndex: index) |
|
|
|
|
if roundObject.isLoserBracket(), roundObject.previousRound() == nil, let parentRound = roundObject.parentRound, let upperBracketBottomMatch = parentRound.getMatch(atMatchIndexInRound: indexInRound * 2 + 1) { |
|
|
|
|
return upperBracketBottomMatch |
|
|
|
|
} |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func roundProjectedTeam(_ team: TeamData) -> TeamRegistration? { |
|
|
|
|
func roundProjectedTeam(_ team: TeamPosition) -> TeamRegistration? { |
|
|
|
|
guard let roundObject else { return nil } |
|
|
|
|
return roundObject.roundProjectedTeam(team, inMatch: self) |
|
|
|
|
|
|
|
|
|
if roundObject.isLoserBracket() == false, let seed = seed(team) { |
|
|
|
|
return seed |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
switch team { |
|
|
|
|
case .one: |
|
|
|
|
if let loser = upperBracketTopMatch()?.losingTeamId { |
|
|
|
|
return Store.main.findById(loser) |
|
|
|
|
} else if let match = topPreviousRoundMatch() { |
|
|
|
|
if let teamId = match.winningTeamId { |
|
|
|
|
return Store.main.findById(teamId) |
|
|
|
|
} else if match.disabled { |
|
|
|
|
return match.teams().first |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
case .two: |
|
|
|
|
if let loser = upperBracketBottomMatch()?.losingTeamId { |
|
|
|
|
return Store.main.findById(loser) |
|
|
|
|
} else if let match = bottomPreviousRoundMatch() { |
|
|
|
|
if let teamId = match.winningTeamId { |
|
|
|
|
return Store.main.findById(teamId) |
|
|
|
|
} else if match.disabled { |
|
|
|
|
return match.teams().first |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func teamWon(_ team: TeamRegistration?) -> Bool { |
|
|
|
|
@ -397,7 +395,7 @@ class Match: ModelObject, Storable { |
|
|
|
|
return winningTeamId == team?.id |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func team(_ team: TeamData) -> TeamRegistration? { |
|
|
|
|
func team(_ team: TeamPosition) -> TeamRegistration? { |
|
|
|
|
if groupStage != nil { |
|
|
|
|
switch team { |
|
|
|
|
case .one: |
|
|
|
|
@ -423,7 +421,7 @@ class Match: ModelObject, Storable { |
|
|
|
|
teamScore(ofTeam: team)?.isWalkOut() == true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func teamScore(_ team: TeamData) -> TeamScore? { |
|
|
|
|
func teamScore(_ team: TeamPosition) -> TeamScore? { |
|
|
|
|
teamScore(ofTeam: self.team(team)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|