multistore
Razmig Sarkissian 1 year ago
parent 568bd5ff02
commit cc4563b663
  1. 4
      PadelClub.xcodeproj/project.pbxproj
  2. 9
      PadelClub/Data/GroupStage.swift
  3. 18
      PadelClub/Data/Tournament.swift
  4. 14
      PadelClub/Views/Planning/PlanningSettingsView.swift
  5. 85
      PadelClub/Views/Round/RoundView.swift
  6. 9
      PadelClub/Views/Tournament/Screen/InscriptionManagerView.swift
  7. 22
      PadelClub/Views/Tournament/Shared/TournamentCellView.swift

@ -1935,7 +1935,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 29;
CURRENT_PROJECT_VERSION = 30;
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6;
@ -1973,7 +1973,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 29;
CURRENT_PROJECT_VERSION = 30;
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6;

@ -376,7 +376,8 @@ extension GroupStage: Selectable {
}
func badgeValue() -> Int? {
runningMatches(playedMatches: _matches()).count
if teams().count < size { return nil }
return runningMatches(playedMatches: _matches()).count
}
func badgeValueColor() -> Color? {
@ -384,6 +385,10 @@ extension GroupStage: Selectable {
}
func badgeImage() -> Badge? {
hasEnded() ? .checkmark : nil
if teams().count < size {
return .xmark
} else {
return hasEnded() ? .checkmark : nil
}
}
}

@ -1523,7 +1523,6 @@ class Tournament : ModelObject, Storable {
groupStageMatchFormat = groupStageSmartMatchFormat()
loserBracketMatchFormat = loserBracketSmartMatchFormat(1)
matchFormat = roundSmartMatchFormat(1)
}
}
@ -1538,7 +1537,8 @@ class Tournament : ModelObject, Storable {
func loserBracketSmartMatchFormat(_ roundIndex: Int) -> MatchFormat {
let format = tournamentLevel.federalFormatForLoserBracketRound(roundIndex)
if format.rank > loserBracketMatchFormat.rank {
if tournamentLevel == .p25 { return .superTie }
if format.rank < loserBracketMatchFormat.rank {
return format
} else {
return loserBracketMatchFormat
@ -1547,7 +1547,8 @@ class Tournament : ModelObject, Storable {
func groupStageSmartMatchFormat() -> MatchFormat {
let format = tournamentLevel.federalFormatForGroupStage()
if format.rank > groupStageMatchFormat.rank {
if tournamentLevel == .p25 { return .superTie }
if format.rank < groupStageMatchFormat.rank {
return format
} else {
return groupStageMatchFormat
@ -1563,7 +1564,8 @@ class Tournament : ModelObject, Storable {
func roundSmartMatchFormat(_ roundIndex: Int) -> MatchFormat {
let format = tournamentLevel.federalFormatForBracketRound(roundIndex)
if format.rank > matchFormat.rank {
if tournamentLevel == .p25 { return .superTie }
if format.rank < matchFormat.rank {
return format
} else {
return matchFormat
@ -1622,6 +1624,14 @@ class Tournament : ModelObject, Storable {
return final?.playedMatches().first?.winner()
}
func getGroupStageChunkValue() -> Int {
if teamsPerGroupStage >= 2 {
return min(groupStageCount, courtCount / (teamsPerGroupStage / 2))
} else {
return 1
}
}
// MARK: -
func insertOnServer() throws {

@ -22,10 +22,10 @@ struct PlanningSettingsView: View {
self.tournament = tournament
if let matchScheduler = tournament.matchScheduler() {
self.matchScheduler = matchScheduler
self._groupStageChunkCount = State(wrappedValue: matchScheduler.groupStageChunkCount ?? 1)
self._groupStageChunkCount = State(wrappedValue: matchScheduler.groupStageChunkCount ?? tournament.getGroupStageChunkValue())
} else {
self.matchScheduler = MatchScheduler(tournament: tournament.id)
self._groupStageChunkCount = State(wrappedValue: 1)
self._groupStageChunkCount = State(wrappedValue: tournament.getGroupStageChunkValue())
}
}
@ -130,10 +130,14 @@ struct PlanningSettingsView: View {
Text("Des dates de démarrages ont été indiqué pour les manches et seront prises en compte.")
}
RowButtonView("Horaire intelligent", role: .destructive) {
schedulingDone = false
await MainActor.run {
schedulingDone = false
}
await _setupSchedule()
_save()
schedulingDone = true
await MainActor.run {
_save()
schedulingDone = true
}
}
} footer: {
Text("Padel Club programmera tous les matchs de votre tournoi en fonction de différents paramètres, ") + Text("tout en tenant compte des horaires que vous avez fixé.").underline()

@ -28,6 +28,7 @@ struct RoundView: View {
List {
let loserRounds = round.loserRounds()
let availableSeeds = tournament.availableSeeds()
let availableQualifiedTeams = tournament.availableQualifiedTeams()
let displayableMatches = round.displayableMatches().sorted(by: \.index)
let spaceLeft = displayableMatches.filter({ $0.hasSpaceLeft() })
@ -76,46 +77,80 @@ struct RoundView: View {
if availableQualifiedTeams.isEmpty == false && spaceLeft.isEmpty == false {
Section {
ForEach(availableQualifiedTeams) { team in
NavigationLink {
SpinDrawView(drawees: [team], segments: spaceLeft) { results in
Task {
results.forEach { drawResult in
team.setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: true)
}
_save()
if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty {
self.isEditingTournamentSeed.wrappedValue = false
DisclosureGroup {
ForEach(availableQualifiedTeams) { team in
NavigationLink {
SpinDrawView(drawees: [team], segments: spaceLeft) { results in
Task {
results.forEach { drawResult in
team.setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: true)
}
_save()
if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty {
self.isEditingTournamentSeed.wrappedValue = false
}
}
}
} label: {
TeamRowView(team: team, displayCallDate: false)
}
} label: {
TeamRowView(team: team, displayCallDate: false)
}
} label: {
Text("Qualifié\(availableQualifiedTeams.count.pluralSuffix) à placer").badge(availableQualifiedTeams.count)
}
} header: {
} header: {
Text("Tirage au sort visuel d'un qualifié").font(.subheadline)
}
}
if tournament.availableSeeds().isEmpty == false && seedSpaceLeft.isEmpty == false {
if availableSeeds.isEmpty == false && seedSpaceLeft.isEmpty == false {
Section {
ForEach(tournament.availableSeeds()) { team in
NavigationLink {
SpinDrawView(drawees: [team], segments: seedSpaceLeft) { results in
Task {
results.forEach { drawResult in
team.setSeedPosition(inSpot: seedSpaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: false)
DisclosureGroup {
ForEach(availableSeeds) { team in
NavigationLink {
SpinDrawView(drawees: [team], segments: seedSpaceLeft) { results in
Task {
results.forEach { drawResult in
team.setSeedPosition(inSpot: seedSpaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: false)
}
_save()
if availableSeeds.isEmpty && tournament.availableQualifiedTeams().isEmpty {
self.isEditingTournamentSeed.wrappedValue = false
}
}
_save()
if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty {
self.isEditingTournamentSeed.wrappedValue = false
}
} label: {
TeamRowView(team: team, displayCallDate: false)
}
}
} label: {
Text("Tête\(availableSeeds.count.pluralSuffix) de série à placer").badge(availableSeeds.count)
}
} header: {
Text("Tirage au sort visuel d'une tête de série").font(.subheadline)
}
} else if availableSeeds.isEmpty == false && spaceLeft.isEmpty == false {
Section {
DisclosureGroup {
ForEach(availableSeeds) { team in
NavigationLink {
SpinDrawView(drawees: [team], segments: spaceLeft) { results in
Task {
results.forEach { drawResult in
team.setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: false)
}
_save()
if availableSeeds.isEmpty && tournament.availableQualifiedTeams().isEmpty {
self.isEditingTournamentSeed.wrappedValue = false
}
}
}
} label: {
TeamRowView(team: team, displayCallDate: false)
}
} label: {
TeamRowView(team: team, displayCallDate: false)
}
} label: {
Text("Tête\(availableSeeds.count.pluralSuffix) de série à placer").badge(availableSeeds.count)
}
} header: {
Text("Tirage au sort visuel d'une tête de série").font(.subheadline)

@ -147,7 +147,16 @@ struct InscriptionManagerView: View {
if self.tournament.shouldVerifyBracket == false || self.tournament.shouldVerifyGroupStage == false {
self.tournament.shouldVerifyBracket = true
self.tournament.shouldVerifyGroupStage = true
let waitingList = self.tournament.waitingListTeams(in: self.tournament.selectedSortedTeams())
waitingList.forEach { team in
if team.bracketPosition != nil || team.groupStagePosition != nil {
team.resetPositions()
}
}
do {
try dataStore.teamRegistrations.addOrUpdate(contentOfs: waitingList)
try dataStore.tournaments.addOrUpdate(instance: tournament)
} catch {
Logger.error(error)

@ -27,6 +27,16 @@ struct TournamentCellView: View {
}
}
var teamCount: Int? {
if let tournament = tournament as? Tournament {
let hasStarted = tournament.inscriptionClosed() || tournament.hasStarted()
let count = hasStarted ? tournament.selectedSortedTeams().count : tournament.unsortedTeamsWithoutWO().count
return count
} else {
return nil
}
}
fileprivate func _spacing() -> CGFloat {
self.displayStyle == .short ? 8.0 : 16.0
}
@ -78,10 +88,8 @@ struct TournamentCellView: View {
if let tournament = tournament as? Tournament, displayStyle == .wide {
if tournament.isCanceled {
Text("Annulé").foregroundStyle(.logoRed)
} else {
let hasStarted = tournament.inscriptionClosed() || tournament.hasStarted()
let count = hasStarted ? tournament.selectedSortedTeams().count : tournament.unsortedTeamsWithoutWO().count
Text(count.formatted())
} else if let teamCount {
Text(teamCount.formatted())
}
} else if let federalTournament = tournament as? FederalTournament {
Button {
@ -101,10 +109,10 @@ struct TournamentCellView: View {
HStack {
Text(tournament.durationLabel())
Spacer()
if let tournament = tournament as? Tournament, tournament.isCanceled == false {
if let tournament = tournament as? Tournament, tournament.isCanceled == false, let teamCount {
let hasStarted = tournament.inscriptionClosed() || tournament.hasStarted()
let word = hasStarted ? "équipes" : "inscriptions"
Text(word)
let word = hasStarted ? "équipe" : "inscription"
Text(word + teamCount.pluralSuffix)
}
}
Text(tournament.subtitleLabel())

Loading…
Cancel
Save