multistore
Razmig Sarkissian 1 year ago
parent d5adf5d83b
commit 689d7e6d8d
  1. 8
      PadelClub.xcodeproj/project.pbxproj
  2. 5
      PadelClub/Data/Match.swift
  3. 15
      PadelClub/Data/Round.swift
  4. 19
      PadelClub/Data/TeamRegistration.swift
  5. 24
      PadelClub/Data/Tournament.swift
  6. 31
      PadelClub/Views/Round/LoserRoundSettingsView.swift
  7. 4
      PadelClub/Views/Round/LoserRoundView.swift
  8. 13
      PadelClub/Views/Round/LoserRoundsView.swift
  9. 2
      PadelClub/Views/Round/RoundView.swift
  10. 16
      PadelClub/Views/Team/EditingTeamView.swift
  11. 3
      PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift

@ -157,6 +157,7 @@
FF4AB6BF2B92577A0002987F /* ImportedPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF4AB6BE2B92577A0002987F /* ImportedPlayerView.swift */; };
FF4C7F022BBBD7150031B6A3 /* TabItemModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF4C7F012BBBD7150031B6A3 /* TabItemModifier.swift */; };
FF53FBB82BFB302B0051D4C3 /* ClubCourtSetupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF53FBB72BFB302B0051D4C3 /* ClubCourtSetupView.swift */; };
FF5647132C0B6F390081F995 /* LoserRoundSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF5647122C0B6F380081F995 /* LoserRoundSettingsView.swift */; };
FF59FFB32B90EFAC0061EFF9 /* EventListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF59FFB22B90EFAC0061EFF9 /* EventListView.swift */; };
FF59FFB72B90EFBF0061EFF9 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF59FFB62B90EFBF0061EFF9 /* MainView.swift */; };
FF59FFB92B90EFD70061EFF9 /* ToolboxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF59FFB82B90EFD70061EFF9 /* ToolboxView.swift */; };
@ -478,6 +479,7 @@
FF4AB6BE2B92577A0002987F /* ImportedPlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportedPlayerView.swift; sourceTree = "<group>"; };
FF4C7F012BBBD7150031B6A3 /* TabItemModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabItemModifier.swift; sourceTree = "<group>"; };
FF53FBB72BFB302B0051D4C3 /* ClubCourtSetupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClubCourtSetupView.swift; sourceTree = "<group>"; };
FF5647122C0B6F380081F995 /* LoserRoundSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoserRoundSettingsView.swift; sourceTree = "<group>"; };
FF59FFB22B90EFAC0061EFF9 /* EventListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventListView.swift; sourceTree = "<group>"; };
FF59FFB62B90EFBF0061EFF9 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
FF59FFB82B90EFD70061EFF9 /* ToolboxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolboxView.swift; sourceTree = "<group>"; };
@ -1235,6 +1237,7 @@
FF5DA1922BB9279B00A33061 /* RoundSettingsView.swift */,
FFC2DCB12BBE75D40046DB9F /* LoserRoundView.swift */,
FFC2DCB32BBE9ECD0046DB9F /* LoserRoundsView.swift */,
FF5647122C0B6F380081F995 /* LoserRoundSettingsView.swift */,
);
path = Round;
sourceTree = "<group>";
@ -1621,6 +1624,7 @@
FF1162872BD004AD000C4809 /* EditingTeamView.swift in Sources */,
FF6EC9062B947A1000EA7F5A /* NetworkManagerError.swift in Sources */,
C4A47D5A2B6D383C00ADC637 /* Tournament.swift in Sources */,
FF5647132C0B6F390081F995 /* LoserRoundSettingsView.swift in Sources */,
FF3795662B9399AA004EA093 /* Persistence.swift in Sources */,
FF1DF49B2BD8D23900822FA0 /* BarButtonView.swift in Sources */,
FFF964502BC25E3700EEF017 /* PlanningView.swift in Sources */,
@ -1935,7 +1939,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 32;
CURRENT_PROJECT_VERSION = 33;
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6;
@ -1973,7 +1977,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 32;
CURRENT_PROJECT_VERSION = 33;
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6;

@ -616,7 +616,7 @@ class Match: ModelObject, Storable {
}
func isReady() -> Bool {
teamScores.count == 2
teamScores.count >= 2
// teams().count == 2
}
@ -638,7 +638,8 @@ class Match: ModelObject, Storable {
}
func walkoutTeam() -> [TeamRegistration] {
scores().filter({ $0.walkOut != nil }).compactMap { $0.team }
//walkout 0 means real walkout, walkout 1 means lucky loser situation
scores().filter({ $0.walkOut == 0 }).compactMap { $0.team }
}
func hasWalkoutTeam() -> Bool {

@ -244,6 +244,10 @@ class Round: ModelObject, Storable {
_matches().allSatisfy({ $0.disabled })
}
func isRankDisabled() -> Bool {
_matches().allSatisfy({ $0.disabled && $0.teamScores.isEmpty })
}
func resetFromRoundAllMatchesStartDate() {
_matches().forEach({
$0.startDate = nil
@ -285,11 +289,12 @@ class Round: ModelObject, Storable {
_matches.forEach { match in
match.disabled = disable
match.resetMatch()
do {
try DataStore.shared.teamScores.delete(contentOfs: match.teamScores)
} catch {
Logger.error(error)
}
//we need to keep teamscores to handle disable ranking match round stuff
// do {
// try DataStore.shared.teamScores.delete(contentOfs: match.teamScores)
// } catch {
// Logger.error(error)
// }
}
do {
try DataStore.shared.matches.addOrUpdate(contentOfs: _matches)

@ -220,12 +220,25 @@ class TeamRegistration: ModelObject, Storable {
bracketPosition != nil
}
func resetPositions() {
func resetGroupeStagePosition() {
groupStageObject()?._matches().forEach({ $0.updateTeamScores() })
groupStage = nil
groupStagePosition = nil
tournamentObject()?.resetTeamScores(in: bracketPosition)
bracketPosition = nil
}
func resetBracketPosition() {
guard let bracketPosition else { return }
guard let tournamentObject = tournamentObject() else { return }
if let match = tournamentObject.match(for: bracketPosition) {
let teamScores = match.teamScores.filter({ $0.teamRegistration != self.id })
tournamentObject.resetTeamScores(in: bracketPosition, outsideOf: teamScores)
}
self.bracketPosition = nil
}
func resetPositions() {
resetGroupeStagePosition()
resetBracketPosition()
}
func pasteData() -> String {

@ -1014,27 +1014,37 @@ class Tournament : ModelObject, Storable {
func finalRanking() -> [Int: [String]] {
var teams: [Int: [String]] = [:]
var ids: Set<String> = Set<String>()
let rounds = rounds()
let final = rounds.last?.playedMatches().last
if let winner = final?.winningTeamId {
teams[1] = [winner]
ids.insert(winner)
}
if let finalist = final?.losingTeamId {
teams[2] = [finalist]
ids.insert(finalist)
}
let others : [Round] = rounds.flatMap { round in
round.loserRoundsAndChildren().filter { $0.isDisabled() == false && $0.hasNextRound() == false }
round.loserRoundsAndChildren().filter { $0.isRankDisabled() == false && $0.hasNextRound() == false }
}.compactMap({ $0 })
others.forEach { round in
if let interval = round.seedInterval() {
let playedMatches = round.playedMatches().filter { $0.disabled == false }
let winners = playedMatches.compactMap({ $0.winningTeamId })
let losers = playedMatches.compactMap({ $0.losingTeamId })
let playedMatches = round.playedMatches().filter { $0.disabled == false || $0.isReady() }
let winners = playedMatches.compactMap({ $0.winningTeamId }).filter({ ids.contains($0) == false })
let losers = playedMatches.compactMap({ $0.losingTeamId }).filter({ ids.contains($0) == false })
if winners.isEmpty {
let disabledIds = playedMatches.flatMap({ $0.teamScores.compactMap({ $0.teamRegistration }) }).filter({ ids.contains($0) == false })
teams[interval.last] = disabledIds
disabledIds.forEach { ids.insert($0) }
} else {
teams[interval.first + winners.count - 1] = winners
winners.forEach { ids.insert($0) }
teams[interval.last] = losers
losers.forEach { ids.insert($0) }
}
}
}
@ -1381,9 +1391,9 @@ class Tournament : ModelObject, Storable {
return nil
}
func resetTeamScores(in matchOfBracketPosition: Int?) {
func resetTeamScores(in matchOfBracketPosition: Int?, outsideOf: [TeamScore] = []) {
guard let match = match(for: matchOfBracketPosition) else { return }
match.resetTeamScores(outsideOf: [])
match.resetTeamScores(outsideOf: outsideOf)
}
func updateTeamScores(in matchOfBracketPosition: Int?) {

@ -0,0 +1,31 @@
//
// LoserRoundSettingsView.swift
// PadelClub
//
// Created by Razmig Sarkissian on 01/06/2024.
//
import SwiftUI
import LeStorage
struct LoserRoundSettingsView: View {
@EnvironmentObject var dataStore: DataStore
@Environment(\.isEditingTournamentSeed) private var isEditingTournamentSeed
@Environment(Tournament.self) var tournament: Tournament
var body: some View {
List {
Section {
RowButtonView(isEditingTournamentSeed.wrappedValue == true ? "Terminer l'édition" : "Éditer les tours joués") {
isEditingTournamentSeed.wrappedValue.toggle()
}
}
//todo proposer ici l'impression des matchs de classements peut-être?
}
}
}
#Preview {
LoserRoundSettingsView()
}

@ -25,9 +25,9 @@ struct LoserRoundView: View {
}
ForEach(loserRounds) { loserRound in
if isEditingTournamentSeed || loserRound.isDisabled() == false {
if true {
Section {
let matches = (isEditingTournamentSeed ? loserRound.playedMatches() : loserRound.playedMatches().filter({ $0.disabled == false })).sorted(by: \.index)
let matches = loserRound.playedMatches().sorted(by: \.index)
ForEach(matches) { match in
MatchRowView(match: match, matchViewStyle: .sectionedStandardStyle)
.overlay {

@ -59,7 +59,6 @@ extension LoserRound: Equatable {
struct LoserRoundsView: View {
@Environment(\.isEditingTournamentSeed) private var isEditingTournamentSeed
var upperBracketRound: Round
@State private var selectedRound: LoserRound?
let loserRounds: [Round]
@ -69,8 +68,7 @@ struct LoserRoundsView: View {
self.upperBracketRound = upperBracketRound
let _loserRounds = upperBracketRound.loserRounds()
self.loserRounds = _loserRounds
let enabledLoserRounds = LoserRound.enabledLoserRounds(inLoserRounds: _loserRounds, inUpperBracketRound: upperBracketRound)
let rounds = LoserRound.updateDestinations(fromLoserRounds: enabledLoserRounds, inUpperBracketRound: upperBracketRound)
let rounds = LoserRound.updateDestinations(fromLoserRounds: _loserRounds, inUpperBracketRound: upperBracketRound)
_allDestinations = State(wrappedValue: rounds)
_selectedRound = State(wrappedValue: rounds.first(where: { $0.rounds.anySatisfy({ $0.getActiveLoserRound() != nil }) }) ?? rounds.first)
@ -83,14 +81,5 @@ struct LoserRoundsView: View {
}
.navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.visible, for: .navigationBar)
.onChange(of: isEditingTournamentSeed.wrappedValue) {
_updateDestinations()
}
}
private func _updateDestinations() {
let enabledLoserRounds = isEditingTournamentSeed.wrappedValue ? loserRounds : LoserRound.enabledLoserRounds(inLoserRounds: loserRounds, inUpperBracketRound: upperBracketRound)
self.allDestinations = LoserRound.updateDestinations(fromLoserRounds: enabledLoserRounds, inUpperBracketRound: upperBracketRound)
}
}

@ -168,7 +168,7 @@ struct RoundView: View {
SpinDrawView(drawees: [team], segments: spaceLeft) { results in
Task {
results.forEach { drawResult in
team.setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: false)
team.setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: true)
}
await _save()
if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty {

@ -25,6 +25,22 @@ struct EditingTeamView: View {
} header: {
Text("Date d'inscription")
}
Section {
RowButtonView("Retirer des poules", role: .destructive) {
team.resetGroupeStagePosition()
_save()
}
.disabled(team.inGroupStage() == false)
}
Section {
RowButtonView("Retirer du tableau", role: .destructive) {
team.resetBracketPosition()
_save()
}
.disabled(team.inRound() == false)
}
}
.onChange(of: registrationDate) {
team.registrationDate = registrationDate

@ -184,8 +184,10 @@ struct InscriptionManagerView: View {
} else if tournament.unsortedTeams().isEmpty {
_inscriptionTipsView()
}
if _isEditingTeam() == false {
_teamRegisteredView()
}
}
.onAppear {
_getTeams()
}
@ -961,6 +963,7 @@ struct InscriptionManagerView: View {
}
}
}
.headerProminence(.increased)
.onReceive(fetchPlayers.publisher.count()) { _ in // <-- here
if let pasteString, count == 2, autoSelect == true {
fetchPlayers.filter { $0.hitForSearch(pasteString) >= hitTarget }.sorted(by: { $0.hitForSearch(pasteString) > $1.hitForSearch(pasteString) }).forEach { player in

Loading…
Cancel
Save