fix bugs with smart planning

fix bug with planning view by court
fix bug with seed deletion
paca_championship
Raz 1 year ago
parent 31f093e60e
commit 835bf8fd3f
  1. 8
      PadelClub.xcodeproj/project.pbxproj
  2. 2
      PadelClub/Data/Match.swift
  3. 4
      PadelClub/Data/MatchScheduler.swift
  4. 20
      PadelClub/Views/Match/MatchDetailView.swift
  5. 2
      PadelClub/Views/Match/MatchSetupView.swift
  6. 13
      PadelClub/Views/Planning/PlanningByCourtView.swift
  7. 222
      PadelClub/Views/Planning/PlanningSettingsView.swift
  8. 6
      PadelClub/Views/Round/RoundView.swift

@ -3222,7 +3222,7 @@
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
@ -3246,7 +3246,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.25;
MARKETING_VERSION = 1.0.26;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -3267,7 +3267,7 @@
CODE_SIGN_ENTITLEMENTS = PadelClub/PadelClub.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_ASSET_PATHS = "\"PadelClub/Preview Content\"";
DEVELOPMENT_TEAM = BQ3Y44M3Q6;
@ -3290,7 +3290,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.25;
MARKETING_VERSION = 1.0.26;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

@ -551,6 +551,8 @@ defer {
}
if startDate == nil {
startDate = endDate?.addingTimeInterval(Double(-getDuration()*60))
} else if let startDate, let endDate, startDate >= endDate {
self.startDate = endDate.addingTimeInterval(Double(-getDuration()*60))
}
let teamOne = team(matchDescriptor.winner)

@ -673,7 +673,7 @@ final class MatchScheduler : ModelObject, Storable {
@discardableResult func updateBracketSchedule(tournament: Tournament, fromRoundId roundId: String?, fromMatchId matchId: String?, startDate: Date) -> Bool {
let upperRounds: [Round] = tournament.rounds()
let allMatches: [Match] = tournament.allMatches().filter({ $0.hasEnded() == false })
let allMatches: [Match] = tournament.allMatches().filter({ $0.hasEnded() == false && $0.hasStarted() == false })
var rounds = [Round]()
@ -694,7 +694,7 @@ final class MatchScheduler : ModelObject, Storable {
}
let flattenedMatches = rounds.flatMap { round in
round._matches().filter({ $0.disabled == false && $0.hasEnded() == false }).sorted(by: \.index)
round._matches().filter({ $0.disabled == false && $0.hasEnded() == false && $0.hasStarted() == false }).sorted(by: \.index)
}
flattenedMatches.forEach({

@ -354,6 +354,26 @@ struct MatchDetailView: View {
Text("Remise-à-zéro")
}
if match.teamScores.isEmpty == false {
Divider()
Menu {
ForEach(match.teamScores) { teamScore in
Button(role: .destructive) {
do {
try tournamentStore.teamScores.delete(instance: teamScore)
} catch {
Logger.error(error)
}
match.confirmed = false
_saveMatch()
} label: {
Text(teamScore.team?.teamLabel() ?? "Aucun nom")
}
}
} label: {
Text("Supprimer une équipe")
}
}
} label: {
LabelOptions()
}

@ -205,7 +205,7 @@ struct MatchSetupView: View {
} catch {
Logger.error(error)
}
match.previousMatches().forEach { previousMatch in
if let previousMatch = match.previousMatch(teamPosition) {
if previousMatch.disabled {
previousMatch.enableMatch()
do {

@ -16,6 +16,7 @@ struct PlanningByCourtView: View {
@State private var viewByCourt: Bool = false
@State private var selectedDay: Date
@State private var selectedCourt: Int = 0
@State private var uuid: UUID = UUID()
var timeSlots: [Date:[Match]] {
Dictionary(grouping: matches) { $0.startDate ?? .distantFuture }
@ -48,8 +49,14 @@ struct PlanningByCourtView: View {
let noStartDate = matches.allSatisfy({ $0.startDate == nil })
List {
_byCourtView(noStartDate: noStartDate)
.id(selectedCourt)
_byCourtView(selectedCourt: selectedCourt, selectedDay: selectedDay, noStartDate: noStartDate)
.id(uuid)
}
.onChange(of: selectedCourt) {
uuid = UUID()
}
.onChange(of: selectedDay) {
uuid = UUID()
}
.overlay {
if noStartDate {
@ -98,7 +105,7 @@ struct PlanningByCourtView: View {
}
@ViewBuilder
func _byCourtView(noStartDate: Bool) -> some View {
func _byCourtView(selectedCourt: Int, selectedDay: Date, noStartDate: Bool) -> some View {
if let _matches = courtSlots[selectedCourt]?.filter({ $0.startDate?.dayInt == selectedDay.dayInt }) {
let _sortedMatches = _matches.sorted(by: \.computedStartDateForSorting)
if _sortedMatches.isEmpty == false {

@ -143,82 +143,7 @@ struct PlanningSettingsView: View {
}
}
let allMatches = tournament.allMatches()
let allGroupStages = tournament.allGroupStages()
let allRounds = tournament.allRounds()
let matchesWithDate = allMatches.filter({ $0.startDate != nil })
let groupMatchesByDay = _groupMatchesByDay(matches: matchesWithDate)
let countedSet = _matchCountPerDay(matchesByDay: groupMatchesByDay, tournament: tournament)
_formatPerDayView(matchCountPerDay: countedSet)
let groupStagesWithDate = allGroupStages.filter({ $0.startDate != nil })
let roundsWithDate = allRounds.filter({ $0.startDate != nil })
if matchesWithDate.isEmpty == false || groupStagesWithDate.isEmpty == false || roundsWithDate.isEmpty == false {
Section {
RowButtonView("Supprimer les horaires des matches", role: .destructive) {
do {
deletingDateMatchesDone = false
allMatches.forEach({
$0.startDate = nil
$0.confirmed = false
})
try self.tournamentStore.matches.addOrUpdate(contentOfs: allMatches)
deletingDateMatchesDone = true
} catch {
Logger.error(error)
}
}
} footer: {
Text("Garde les horaires définis pour les poules et les manches.")
}
Section {
RowButtonView("Supprimer tous les horaires", role: .destructive) {
do {
deletingDone = false
allMatches.forEach({
$0.startDate = nil
$0.confirmed = false
})
try self.tournamentStore.matches.addOrUpdate(contentOfs: allMatches)
allGroupStages.forEach({ $0.startDate = nil })
try self.tournamentStore.groupStages.addOrUpdate(contentOfs: allGroupStages)
allRounds.forEach({ $0.startDate = nil })
try self.tournamentStore.rounds.addOrUpdate(contentOfs: allRounds)
deletingDone = true
} catch {
Logger.error(error)
}
}
}
}
Section {
if groupStagesWithDate.isEmpty == false {
Text("Des dates de démarrages ont été indiqué pour les poules et seront prises en compte.")
}
if roundsWithDate.isEmpty == false {
Text("Des dates de démarrages ont été indiqué pour les manches et seront prises en compte.")
}
RowButtonView("Horaire intelligent", role: .destructive) {
await MainActor.run {
issueFound = false
schedulingDone = false
}
self.issueFound = await _setupSchedule()
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()
}
_smartView()
}
.headerProminence(.increased)
.onAppear {
@ -265,6 +190,151 @@ struct PlanningSettingsView: View {
}
}
@ViewBuilder
private func _smartView() -> some View {
let allMatches = tournament.allMatches().filter({ $0.hasEnded() == false && $0.hasStarted() == false })
let allGroupStages = tournament.allGroupStages()
let allRounds = tournament.allRounds()
let matchesWithDate = allMatches.filter({ $0.startDate != nil })
let groupMatchesByDay = _groupMatchesByDay(matches: matchesWithDate)
let countedSet = _matchCountPerDay(matchesByDay: groupMatchesByDay, tournament: tournament)
_formatPerDayView(matchCountPerDay: countedSet)
let groupStagesWithDate = allGroupStages.filter({ $0.startDate != nil })
let roundsWithDate = allRounds.filter({ $0.startDate != nil })
if matchesWithDate.isEmpty == false {
Section {
RowButtonView("Supprimer les horaires des matches", role: .destructive) {
do {
deletingDateMatchesDone = false
allMatches.forEach({
$0.startDate = nil
$0.confirmed = false
})
try self.tournamentStore.matches.addOrUpdate(contentOfs: allMatches)
deletingDateMatchesDone = true
} catch {
Logger.error(error)
}
}
} footer: {
Text("Supprime les horaires des matchs restants non démarrés. Garde les horaires définis pour les poules et les manches du tableau.")
}
}
if groupStagesWithDate.isEmpty == false {
Section {
RowButtonView("Supprimer les horaires des poules", role: .destructive) {
do {
deletingDone = false
allGroupStages.forEach({ $0.startDate = nil })
try self.tournamentStore.groupStages.addOrUpdate(contentOfs: allGroupStages)
deletingDone = true
} catch {
Logger.error(error)
}
}
}
}
if roundsWithDate.isEmpty == false {
Section {
RowButtonView("Supprimer les horaires du tableau", role: .destructive) {
do {
deletingDone = false
allRounds.forEach({ $0.startDate = nil })
try self.tournamentStore.rounds.addOrUpdate(contentOfs: allRounds)
deletingDone = true
} catch {
Logger.error(error)
}
}
} footer: {
Text("Supprime les horaires définis pour les manches du tableau.")
}
}
if matchesWithDate.isEmpty == false && groupStagesWithDate.isEmpty == false && roundsWithDate.isEmpty == false {
Section {
RowButtonView("Supprimer tous les horaires", role: .destructive) {
do {
deletingDone = false
allMatches.forEach({
$0.startDate = nil
$0.confirmed = false
})
try self.tournamentStore.matches.addOrUpdate(contentOfs: allMatches)
allGroupStages.forEach({ $0.startDate = nil })
try self.tournamentStore.groupStages.addOrUpdate(contentOfs: allGroupStages)
allRounds.forEach({ $0.startDate = nil })
try self.tournamentStore.rounds.addOrUpdate(contentOfs: allRounds)
deletingDone = true
} catch {
Logger.error(error)
}
}
} footer: {
Text("Supprime les horaires des matchs restants non démarrés, les horaires définis pour les poules et les manches du tableau.")
}
}
#if DEBUG
Section {
RowButtonView("Supprimer tous les horaires", role: .destructive) {
do {
deletingDone = false
tournament.allMatches().forEach({
$0.startDate = nil
$0.endDate = nil
$0.confirmed = false
})
try self.tournamentStore.matches.addOrUpdate(contentOfs: tournament.allMatches())
allGroupStages.forEach({ $0.startDate = nil })
try self.tournamentStore.groupStages.addOrUpdate(contentOfs: allGroupStages)
allRounds.forEach({ $0.startDate = nil })
try self.tournamentStore.rounds.addOrUpdate(contentOfs: allRounds)
deletingDone = true
} catch {
Logger.error(error)
}
}
} footer: {
Text("Supprime les horaires des matchs, les horaires définis pour les poules et les manches du tableau.")
}
#endif
Section {
if groupStagesWithDate.isEmpty == false {
Text("Des dates de démarrages ont été indiqué pour les poules et seront prises en compte.")
}
if roundsWithDate.isEmpty == false {
Text("Des dates de démarrages ont été indiqué pour les manches et seront prises en compte.")
}
RowButtonView("Horaire intelligent", role: .destructive) {
await MainActor.run {
issueFound = false
schedulingDone = false
}
self.issueFound = await _setupSchedule()
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()
}
}
@ViewBuilder
private func _optionsView() -> some View {
List {

@ -109,7 +109,11 @@ struct RoundView: View {
LabeledContent {
let status = upperRound.status()
if status.0 == status.1 {
Image(systemName: "checkmark").foregroundStyle(.green)
if status.0 == 0 {
Text("aucun match")
} else {
Image(systemName: "checkmark").foregroundStyle(.green)
}
} else {
Text("\(status.0) terminé\(status.0.pluralSuffix) sur \(status.1)")
}

Loading…
Cancel
Save