fix issues with match readiness

add match per day warning data
update the match format picker
paca_championship
Raz 1 year ago
parent ad5b2f06c4
commit 996220fe6f
  1. 2
      PadelClub/Data/Match.swift
  2. 6
      PadelClub/Utils/PadelRule.swift
  3. 136
      PadelClub/Views/Planning/PlanningSettingsView.swift
  4. 8
      PadelClub/Views/Shared/MatchFormatPickerView.swift

@ -700,6 +700,8 @@ defer {
print("teams.count != 2") print("teams.count != 2")
return false return false
} }
guard hasEnded() == false else { return false }
guard hasStarted() == false else { return false }
return teams.compactMap({ $0.team }).allSatisfy({ return teams.compactMap({ $0.team }).allSatisfy({
((checkCanPlay && $0.canPlay()) || checkCanPlay == false) && isTeamPlaying($0, inMatches: matches) == false ((checkCanPlay && $0.canPlay()) || checkCanPlay == false) && isTeamPlaying($0, inMatches: matches) == false
}) })

@ -1262,9 +1262,9 @@ enum MatchFormat: Int, Hashable, Codable, CaseIterable {
case .nineGamesDecisivePoint: case .nineGamesDecisivePoint:
return 40 return 40
case .megaTie: case .megaTie:
return 30 return 20
case .superTie: case .superTie:
return 25 return 15
} }
} }
@ -1349,7 +1349,7 @@ enum MatchFormat: Int, Hashable, Codable, CaseIterable {
case .superTie: case .superTie:
return "E" return "E"
case .megaTie: case .megaTie:
return "F" return "F (non officiel)"
case .twoSetsDecisivePoint: case .twoSetsDecisivePoint:
return "A2" return "A2"
case .twoSetsDecisivePointSuperTie: case .twoSetsDecisivePointSuperTie:

@ -147,6 +147,13 @@ struct PlanningSettingsView: View {
let allGroupStages = tournament.allGroupStages() let allGroupStages = tournament.allGroupStages()
let allRounds = tournament.allRounds() let allRounds = tournament.allRounds()
let matchesWithDate = allMatches.filter({ $0.startDate != nil }) 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 groupStagesWithDate = allGroupStages.filter({ $0.startDate != nil })
let roundsWithDate = allRounds.filter({ $0.startDate != nil }) let roundsWithDate = allRounds.filter({ $0.startDate != nil })
if matchesWithDate.isEmpty == false || groupStagesWithDate.isEmpty == false || roundsWithDate.isEmpty == false { if matchesWithDate.isEmpty == false || groupStagesWithDate.isEmpty == false || roundsWithDate.isEmpty == false {
@ -391,6 +398,135 @@ struct PlanningSettingsView: View {
Logger.error(error) Logger.error(error)
} }
} }
private func _groupMatchesByDay(matches: [Match]) -> [Date: [Match]] {
var matchesByDay = [Date: [Match]]()
let calendar = Calendar.current
for match in matches {
// Extract day/month/year and create a date with only these components
let components = calendar.dateComponents([.year, .month, .day], from: match.computedStartDateForSorting)
let strippedDate = calendar.date(from: components)!
// Group matches by the strippedDate (only day/month/year)
if matchesByDay[strippedDate] == nil {
matchesByDay[strippedDate] = []
}
let shouldIncludeMatch: Bool
switch match.matchType {
case .groupStage:
shouldIncludeMatch = !matchesByDay[strippedDate]!.filter { $0.groupStage != nil }.compactMap { $0.groupStage }.contains(match.groupStage!)
case .bracket:
shouldIncludeMatch = !matchesByDay[strippedDate]!.filter { $0.round != nil }.compactMap { $0.round }.contains(match.round!)
case .loserBracket:
shouldIncludeMatch = true
}
if shouldIncludeMatch {
matchesByDay[strippedDate]!.append(match)
}
}
return matchesByDay
}
private func _matchCountPerDay(matchesByDay: [Date: [Match]], tournament: Tournament) -> [Date: NSCountedSet] {
let days = matchesByDay.keys
var matchCountPerDay = [Date: NSCountedSet]()
for day in days {
if let matches = matchesByDay[day] {
var groupStageCount = 0
let countedSet = NSCountedSet()
for match in matches {
switch match.matchType {
case .groupStage:
if let groupStage = match.groupStageObject {
if groupStageCount < groupStage.size - 1 {
groupStageCount = groupStage.size - 1
}
}
case .bracket:
countedSet.add(match.matchFormat)
case .loserBracket:
break
}
}
if groupStageCount > 0 {
for _ in 0..<groupStageCount {
countedSet.add(tournament.groupStageMatchFormat)
}
}
if let loserRounds = matches.filter({ $0.round != nil }).filter({ $0.roundObject?.parent == nil }).sorted(by: \.computedStartDateForSorting).last?.roundObject?.loserRounds() {
let ids = matches.map { $0.id }
for loserRound in loserRounds {
if let first = loserRound.playedMatches().first {
if ids.contains(first.id) {
countedSet.add(first.matchFormat)
}
}
}
}
matchCountPerDay[day] = countedSet
}
}
return matchCountPerDay
}
private func _formatPerDayView(matchCountPerDay: [Date: NSCountedSet]) -> some View {
ForEach(Array(matchCountPerDay.keys).sorted(), id: \.self) { date in
if let countedSet = matchCountPerDay[date] {
Section {
let totalMatches = countedSet.totalCount()
ForEach(Array(countedSet).compactMap { $0 as? MatchFormat }, id: \.self) { matchFormat in
let count = countedSet.count(for: matchFormat)
let totalForThisFormat = matchFormat.maximumMatchPerDay(for: totalMatches)
let error = count > totalForThisFormat
// Presenting LabeledContent for each match format and its count
LabeledContent {
Image(systemName: error ? "exclamationmark.triangle" : "checkmark")
.font(.title3)
.foregroundStyle(error ? .red : .green)
} label: {
let label = "\(count) match\(count.pluralSuffix) en \(matchFormat.format)"
let subtitle = "pas plus de " + totalForThisFormat.formatted() + " match\(totalForThisFormat.pluralSuffix) pour ce jour"
Text(label)
Text(subtitle)
}
}
} header: {
Text(date.formatted(.dateTime.weekday(.abbreviated).day(.twoDigits).month(.abbreviated)))
}
}
}
}
// Helper function to format date to string (you can customize the format)
private func _formattedDate(_ date: Date) -> String {
let formatter = DateFormatter()
formatter.dateStyle = .medium // Set the date style (e.g., Oct 12, 2024)
return formatter.string(from: date)
}
}
// Extension to compute the total count in an NSCountedSet
extension NSCountedSet {
func totalCount() -> Int {
var total = 0
for element in self {
total += self.count(for: element)
}
return total
}
} }
//#Preview { //#Preview {

@ -17,7 +17,13 @@ struct MatchFormatPickerView: View {
DisclosureGroup(isExpanded: $isExpanded) { DisclosureGroup(isExpanded: $isExpanded) {
Picker(selection: $matchFormat) { Picker(selection: $matchFormat) {
ForEach(MatchFormat.allCases, id: \.rawValue) { format in ForEach(MatchFormat.allCases, id: \.rawValue) { format in
Text(format.computedShortLabel).tag(format) LabeledContent {
Text("~" + format.formattedEstimatedDuration(tournament.additionalEstimationDuration))
} label: {
Text(format.format + " " + format.suffix)
Text(format.longLabel)
}
.tag(format)
} }
} label: { } label: {
} }

Loading…
Cancel
Save