fix pdf rules

add descritpion sharing system
fix slots setup
sync^2
Raz 8 months ago
parent 377f1eced4
commit 6ff21edba8
  1. 49
      PadelClub/Data/Tournament.swift
  2. 7
      PadelClub/Utils/URLs.swift
  3. 27
      PadelClub/Views/Match/MatchSetupView.swift
  4. 77
      PadelClub/Views/Navigation/Agenda/EventListView.swift
  5. 7
      PadelClub/Views/Navigation/Toolbox/ToolboxView.swift
  6. 21
      PadelClub/Views/Round/RoundView.swift

@ -702,16 +702,31 @@ defer {
return getRound(atRoundIndex: roundIndex)?.playedMatches().filter { $0.hasSpaceLeft() } ?? []
}
func availableSeedGroups() -> [SeedInterval] {
func availableSeedGroups(includeAll: Bool = false) -> [SeedInterval] {
let seeds = seeds()
var availableSeedGroup = Set<SeedInterval>()
for (index, seed) in seeds.enumerated() {
if seed.isSeedable(), let seedGroup = seedGroup(for: index) {
availableSeedGroup.insert(seedGroup)
if includeAll {
if let chunks = seedGroup.chunks() {
chunksBy(in: chunks, availableSeedGroup: &availableSeedGroup)
}
} else {
availableSeedGroup.insert(seedGroup)
}
}
}
return availableSeedGroup.sorted(by: <)
}
func chunksBy(in chunks: [SeedInterval], availableSeedGroup: inout Set<SeedInterval>) {
chunks.forEach { chunk in
availableSeedGroup.insert(chunk)
if let moreChunk = chunk.chunks() {
self.chunksBy(in: moreChunk, availableSeedGroup: &availableSeedGroup)
}
}
}
func seedGroup(for alreadySetupSeeds: Int) -> SeedInterval? {
switch alreadySetupSeeds {
@ -771,20 +786,24 @@ defer {
let maxSpots = max(availableSeedSpot.count, availableSeedOpponentSpot.count)
if availableSeedGroup == SeedInterval(first: 3, last: 4), availableSeedSpot.count == 6 {
return availableSeedGroup
} else if availableSeedGroup == SeedInterval(first: 5, last: 8), maxSpots == 6, availableSeeds.count == 2 {
return SeedInterval(first: 7, last: 12)
}
if availableSeeds.count == availableSeedSpot.count && availableSeedGroup.count == availableSeeds.count {
return availableSeedGroup
} else if availableSeeds.count == availableSeedOpponentSpot.count && availableSeedGroup.count == availableSeedOpponentSpot.count {
return availableSeedGroup
} else if let chunks = availableSeedGroup.chunks() {
let seededTeamsCount = self.seededTeams().count
if let chunk = chunks.first(where: { seedInterval in
seedInterval.first >= self.seededTeams().count
return seedInterval.first == seededTeamsCount
}) {
return seedGroupAvailable(atRoundIndex: roundIndex, availableSeedGroup: chunk)
return seedGroupAvailable(atRoundIndex: roundIndex + 1, availableSeedGroup: chunk)
} else {
let seeds = seeds()
if let firstIndex = seeds.firstIndex(where: { $0.isSeedable() }) {
return SeedInterval(first: firstIndex + 1, last: firstIndex + maxSpots)
}
}
} else if fullLeftSeeds.count % maxSpots == 0 {
} else if fullLeftSeeds.count % maxSpots == 0 || fullLeftSeeds.count >= maxSpots {
let seeds = seeds()
if let firstIndex = seeds.firstIndex(where: { $0.isSeedable() }) {
return SeedInterval(first: firstIndex + 1, last: firstIndex + maxSpots)
@ -820,14 +839,14 @@ defer {
for (index, seed) in availableSeeds.enumerated() {
seed.setSeedPosition(inSpot: spots[index], slot: nil, opposingSeeding: false)
}
} else if seedGroup == SeedInterval(first: 5, last: 6), availableSeedSpot.count == 4 {
var spots = [Match]()
spots.append(availableSeedSpot[1])
spots.append(availableSeedSpot[2])
spots = spots.shuffled()
for (index, seed) in availableSeeds.enumerated() {
seed.setSeedPosition(inSpot: spots[index], slot: nil, opposingSeeding: false)
}
// } else if seedGroup == SeedInterval(first: 5, last: 6), availableSeedSpot.count == 4 {
// var spots = [Match]()
// spots.append(availableSeedSpot[1])
// spots.append(availableSeedSpot[2])
// spots = spots.shuffled()
// for (index, seed) in availableSeeds.enumerated() {
// seed.setSeedPosition(inSpot: spots[index], slot: nil, opposingSeeding: false)
// }
} else {
if availableSeeds.count <= availableSeedSpot.count {
let spots = availableSeedSpot.shuffled()

@ -31,9 +31,10 @@ enum URLs: String, Identifiable {
case beachPadel = "https://beach-padel.app.fft.fr/beachja/index/"
//case padelClub = "https://padelclub.app"
case tenup = "https://tenup.fft.fr"
case padelCompetitionGeneralGuide = "https://fft-site.cdn.prismic.io/fft-site/Z2mH0ZbqstJ98yso_CHAPITREIRèglesgénérales.pdf"
case padelCompetitionSpecificGuide = "https://fft-site.cdn.prismic.io/fft-site/Z2mHz5bqstJ98ysm_CHAPITREIIICahierdeschargesdestournois.pdf"
case padelRules = "https://xlr.alwaysdata.net/static/rules/padel-rules-2024.pdf"
case padelCompetitionGeneralGuide = "https://padelclub.app/static/rules/padel-guide-general.pdf"
case padelCompetitionSpecificGuide = "https://padelclub.app/static/rules/padel-guide-cdc.pdf"
case padelCompetitionRankingGuide = "https://padelclub.app/static/rules/padel-guide-rankings.pdf"
case padelRules = "https://padelclub.app/static/rules/padel-rules.pdf"
case restingDischarge = "https://club.fft.fr/tennisfirmidecazeville/60120370_d/data_1/pdf/fo/formlairededechargederesponsabilitetournoidepadel.pdf"
case appReview = "https://apps.apple.com/app/padel-club/id6484163558?mt=8&action=write-review"
case appDescription = "https://padelclub.app/download/"

@ -146,6 +146,33 @@ struct MatchSetupView: View {
Label(seedGroup.localizedInterval(), systemImage: "dice")
}
}
Divider()
Menu {
ForEach(tournament.availableSeedGroups(includeAll: true), id: \.self) { seedGroup in
ConfirmButtonView(shouldConfirm: shouldConfirm, message: MatchSetupView.confirmationMessage) {
if let randomTeam = tournament.randomSeed(fromSeedGroup: seedGroup) {
randomTeam.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
do {
try tournamentStore.matches.addOrUpdate(instance: match)
} catch {
Logger.error(error)
}
do {
try tournamentStore.teamRegistrations.addOrUpdate(instance: randomTeam)
} catch {
Logger.error(error)
}
}
} label: {
Label(seedGroup.localizedInterval(), systemImage: "dice")
}
}
} label: {
Text("plus d'options")
}
} label: {
Text("Tirer au sort").tag(nil as SeedInterval?)
.underline()

@ -107,7 +107,7 @@ struct EventListView: View {
@ViewBuilder
private func _options(_ pcTournaments: [Tournament]) -> some View {
if let lastDataSource, pcTournaments.anySatisfy({ $0.rankSourceShouldBeRefreshed() != nil && $0.hasEnded() == false }) {
Section {
Menu {
Button {
Task {
do {
@ -134,14 +134,14 @@ struct EventListView: View {
}
}
} label: {
Text("Rafraîchir les classements")
Text("M-à-j des classements")
}
} header: {
Text("Source disponible : \(lastDataSource.monthYearFormatted)")
} label: {
Text("Classement \(lastDataSource.monthYearFormatted)")
}
Divider()
}
Section {
Menu {
if pcTournaments.anySatisfy({ $0.isPrivate == true }) {
Button {
pcTournaments.forEach { tournament in
@ -153,7 +153,7 @@ struct EventListView: View {
Logger.error(error)
}
} label: {
Text("Afficher ce\(pcTournaments.count.pluralSuffix) tournoi\(pcTournaments.count.pluralSuffix) sur Padel Club")
Text("Afficher sur Padel Club")
}
}
@ -168,15 +168,15 @@ struct EventListView: View {
Logger.error(error)
}
} label: {
Text("Masquer ce\(pcTournaments.count.pluralSuffix) tournoi\(pcTournaments.count.pluralSuffix) sur Padel Club")
Text("Masquer sur Padel Club")
}
}
} header: {
} label: {
Text("Visibilité sur Padel Club")
}
Divider()
if pcTournaments.anySatisfy({ $0.hasEnded() == false && $0.enableOnlineRegistration == false && $0.onlineRegistrationCanBeEnabled() }) || pcTournaments.anySatisfy({ $0.enableOnlineRegistration == true && $0.hasEnded() == false }) {
Section {
Menu {
if pcTournaments.anySatisfy({ $0.hasEnded() == false && $0.enableOnlineRegistration == false && $0.onlineRegistrationCanBeEnabled() }) {
Button {
pcTournaments.forEach { tournament in
@ -188,7 +188,7 @@ struct EventListView: View {
Logger.error(error)
}
} label: {
Text("Activer l'inscription en ligne")
Text("Activer")
}
}
@ -201,7 +201,7 @@ struct EventListView: View {
}
}
} label: {
Text("Rafraîchir la liste des équipes inscrites en ligne")
Text("M-à-j des inscriptions")
}
@ -215,13 +215,64 @@ struct EventListView: View {
Logger.error(error)
}
} label: {
Text("Désactiver l'inscription en ligne")
Text("Désactiver")
}
}
} header: {
} label: {
Text("Inscription en ligne")
}
}
Divider()
Menu {
Button {
pcTournaments.forEach { tournament in
tournament.information = nil
}
do {
try dataStore.tournaments.addOrUpdate(contentOfs: pcTournaments)
} catch {
Logger.error(error)
}
} label: {
Text("Effacer les descriptions")
}
let info = Set(pcTournaments.compactMap { tournament in
tournament.information?.trimmedMultiline
}).joined(separator: "\n")
if info.isEmpty == false {
Button {
pcTournaments.forEach { tournament in
tournament.information = info
}
do {
try dataStore.tournaments.addOrUpdate(contentOfs: pcTournaments)
} catch {
Logger.error(error)
}
} label: {
Text("Mettre '\(info.trunc(length: 12))'")
}
}
PasteButton(payloadType: String.self) { strings in
if let pasteboard = strings.first {
pcTournaments.forEach { tournament in
tournament.information = pasteboard
}
do {
try dataStore.tournaments.addOrUpdate(contentOfs: pcTournaments)
} catch {
Logger.error(error)
}
}
}
} label: {
Text("Description des tournois")
}
}
private func _nextMonths() -> [Date] {

@ -170,9 +170,10 @@ struct ToolboxView: View {
}
Section {
Link("Accéder au guide de la compétition", destination: URLs.padelCompetitionGeneralGuide.url)
Link("Accéder aux CDC des tournois", destination: URLs.padelCompetitionSpecificGuide.url)
Link("Accéder aux règles du jeu", destination: URLs.padelRules.url)
Link("Guide de la compétition", destination: URLs.padelCompetitionGeneralGuide.url)
Link("CDC des tournois", destination: URLs.padelCompetitionSpecificGuide.url)
Link("Barèmes et assimilations", destination: URLs.padelCompetitionRankingGuide.url)
Link("Règles du jeu", destination: URLs.padelRules.url)
Link("Décharge des temps de repos", destination: URLs.restingDischarge.url)
} header: {
Text("Documents fédéraux")

@ -132,9 +132,6 @@ struct RoundView: View {
if availableSeeds.isEmpty == false, let availableSeedGroup {
_seedGroupSection(availableSeeds: availableSeeds, availableSeedGroup: availableSeedGroup)
if upperRound.round.index == 3, availableSeedGroup.first == 5, availableSeedGroup.last == 8, availableSeeds.count > 4, let half = availableSeedGroup.chunks()?.first {
_seedGroupSection(availableSeeds: Array(availableSeeds.prefix(2)), availableSeedGroup: half)
}
}
if availableQualifiedTeams.isEmpty == false {
@ -295,11 +292,6 @@ struct RoundView: View {
array.append(spots[1])
array.append(spots[4])
return array
} else if availableSeedGroup == SeedInterval(first: 5, last: 6), spots.count == 4 {
var array = [Match]()
array.append(spots[1])
array.append(spots[2])
return array
} else {
return spots
}
@ -394,6 +386,14 @@ struct RoundView: View {
_save(seeds: availableSeeds)
}
}
// if upperRound.round.index == 3, availableSeedGroup.first == 5, availableSeedGroup.last == 8, availableSeeds.count > 1, let half = availableSeedGroup.chunks()?.first {
// FooterButtonView("ou placer \(half.localizedInterval())" + ((half.isFixed() == false) ? " au hasard" : "")) {
// Task {
// tournament.setSeeds(inRoundIndex: upperRound.round.index, inSeedGroup: half)
// _save(seeds: availableSeeds)
// }
// }
// }
} footer: {
if availableSeedGroup.isFixed() == false {
Text("Le tirage au sort ne sera pas visuel. Toutes les équipes de ce chapeau seront tirées.")
@ -411,6 +411,11 @@ struct RoundView: View {
RowButtonView("Tirage au sort \(availableSeedGroup.localizedInterval()) visuel") {
self.selectedSeedGroup = availableSeedGroup
}
// if upperRound.round.index == 3, availableSeedGroup.first == 5, availableSeedGroup.last == 8, availableSeeds.count > 1, let half = availableSeedGroup.chunks()?.first {
// FooterButtonView("ou tirage au sort \(half.localizedInterval()) visuel") {
// self.selectedSeedGroup = half
// }
// }
} footer: {
Text("Le tirage au sort sera visuel et automatique, n'hésitez pas à enregistrer une vidéo de votre écran. Toutes les équipes de ce chapeau seront tirées les unes après les autres.")
}

Loading…
Cancel
Save