You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
8.1 KiB
226 lines
8.1 KiB
//
|
|
// Event_v2.swift
|
|
// Padel Tournament
|
|
//
|
|
// Created by razmig on 10/03/2024.
|
|
//
|
|
|
|
import Foundation
|
|
import LeStorage
|
|
import SwiftUI
|
|
|
|
@Observable
|
|
final public class Event: BaseEvent {
|
|
|
|
public init(creator: String? = nil, club: String? = nil, name: String? = nil, tenupId: String? = nil) {
|
|
super.init(creator: creator, club: club, name: name, tenupId: tenupId)
|
|
self.relatedUser = creator
|
|
}
|
|
|
|
required init(from decoder: Decoder) throws {
|
|
try super.init(from: decoder)
|
|
}
|
|
|
|
required public init() {
|
|
super.init()
|
|
}
|
|
|
|
public override func deleteUnusedSharedDependencies(store: Store) {
|
|
store.deleteUnusedSharedDependencies(type: Tournament.self) { $0.event == self.id && $0.isDeleted == false }
|
|
store.deleteUnusedSharedDependencies(type: DateInterval.self) { $0.event == self.id }
|
|
}
|
|
|
|
public override func deleteDependencies(store: Store, actionOption: ActionOption) {
|
|
|
|
store.deleteDependencies(type: Tournament.self, actionOption: actionOption) { $0.event == self.id && $0.isDeleted == false }
|
|
store.deleteDependencies(type: DateInterval.self, actionOption: actionOption) { $0.event == self.id }
|
|
|
|
}
|
|
|
|
// MARK: - Computed dependencies
|
|
|
|
public var tournaments: [Tournament] {
|
|
DataStore.shared.tournaments.filter { $0.event == self.id && $0.isDeleted == false }.sorted(by: \.startDate)
|
|
}
|
|
|
|
public func clubObject() -> Club? {
|
|
guard let club else { return nil }
|
|
return Store.main.findById(club)
|
|
}
|
|
|
|
public var courtsUnavailability: [DateInterval] {
|
|
DataStore.shared.dateIntervals.filter({ $0.event == id })
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
public func eventCourtCount() -> Int {
|
|
tournaments.map { $0.courtCount }.max() ?? 2
|
|
}
|
|
|
|
public func eventStartDate() -> Date {
|
|
tournaments.map { $0.startDate }.min() ?? Date()
|
|
}
|
|
|
|
public func eventDayDuration() -> Int {
|
|
tournaments.map { $0.dayDuration }.max() ?? 1
|
|
}
|
|
|
|
public func eventTitle() -> String {
|
|
if let name, name.isEmpty == false {
|
|
return name
|
|
} else {
|
|
return "Événement"
|
|
}
|
|
}
|
|
|
|
public func existingBuild(_ build: any TournamentBuildHolder) -> Tournament? {
|
|
tournaments.first(where: { $0.isSameBuild(build) })
|
|
}
|
|
|
|
public func tournamentsCourtsUsed(exluding tournamentId: String) -> [DateInterval] {
|
|
tournaments.filter { $0.id != tournamentId }.flatMap({ tournament in
|
|
tournament.getPlayedMatchDateIntervals(in: self)
|
|
})
|
|
}
|
|
|
|
public func federalTournaments() -> [Tournament] {
|
|
tournaments.filter({ $0.isAnimation() == false && $0.isCanceled == false && $0.isDeleted == false })
|
|
}
|
|
|
|
public func paidTournaments() -> [Tournament] {
|
|
tournaments.filter({ $0.isFree() == false && $0.isCanceled == false && $0.isDeleted == false })
|
|
}
|
|
|
|
public func confirmedTournaments() -> [Tournament] {
|
|
tournaments.filter({ $0.isCanceled == false && $0.isDeleted == false })
|
|
}
|
|
|
|
public func shareURL() -> URL? {
|
|
return URL(string: URLs.main.url.appending(path: "event/\(id)").absoluteString.removingPercentEncoding!)
|
|
}
|
|
|
|
public func formattedDateInterval() -> String {
|
|
let tournaments = self.tournaments
|
|
guard !tournaments.isEmpty else {
|
|
return "" // Handle empty tournament list
|
|
}
|
|
|
|
let firstTournament = tournaments.first!
|
|
let lastTournament = tournaments.last!
|
|
|
|
// Helper to check if two dates are on the same day
|
|
func isSameDay(date1: Date, date2: Date) -> Bool {
|
|
return Calendar.current.isDate(date1, inSameDayAs: date2)
|
|
}
|
|
|
|
// Scenario 1: Only one tournament
|
|
if tournaments.count == 1 {
|
|
return firstTournament.startDate.formattedAsDate()
|
|
}
|
|
|
|
// Scenario 2: Multiple tournaments, but all start and end on the same day (single-day event overall)
|
|
let overallEventIsSingleDay = isSameDay(date1: firstTournament.startDate, date2: lastTournament.startDate)
|
|
|
|
if overallEventIsSingleDay {
|
|
return firstTournament.startDate.formattedAsDate()
|
|
}
|
|
|
|
// Scenario 3: Multiple tournaments, spanning multiple days (requires "Du ... au ...")
|
|
let startDay = firstTournament.startDate.localizedDay()
|
|
let endDay = lastTournament.startDate.localizedDay()
|
|
|
|
let startMonthYear = firstTournament.startDate.monthYearFormatted
|
|
let endMonthYear = lastTournament.startDate.monthYearFormatted
|
|
|
|
let calendar = Calendar.current
|
|
let firstStartComponents = calendar.dateComponents([.year, .month], from: firstTournament.startDate)
|
|
let lastEndComponents = calendar.dateComponents([.year, .month], from: lastTournament.startDate)
|
|
|
|
if firstStartComponents.year == lastEndComponents.year && firstStartComponents.month == lastEndComponents.month {
|
|
// Same month and year: "Du 13 au 15 Juin 2025"
|
|
return "Du \(startDay) au \(endDay) \(startMonthYear)"
|
|
} else if firstStartComponents.year == lastEndComponents.year {
|
|
// Different months, same year: "Du 13 Juin au 15 Juillet 2025"
|
|
return "Du \(startDay) \(startMonthYear) au \(endDay) \(endMonthYear)"
|
|
} else {
|
|
// Different years: "Du 13 Juin 2025 au 15 Juin 2026"
|
|
return "Du \(startDay) \(startMonthYear) au \(endDay) \(endMonthYear)"
|
|
}
|
|
}
|
|
|
|
public func tournamentInformation() -> String? {
|
|
confirmedTournaments().first?.information
|
|
}
|
|
|
|
public func eventLinksPasteData() -> String {
|
|
let tournaments = self.confirmedTournaments()
|
|
var link = [String?]()
|
|
link.append(eventTitle())
|
|
|
|
link.append(tournamentInformation())
|
|
|
|
if let url = shareURL() {
|
|
var tournamentLink = [String]()
|
|
tournamentLink.append("Lien de l'événement")
|
|
tournamentLink.append(url.absoluteString)
|
|
let eventLink = tournamentLink.joined(separator: "\n")
|
|
link.append(eventLink)
|
|
}
|
|
|
|
link.append("Retrouvez toutes les infos en suivant le\(tournaments.count.pluralSuffix) lien\(tournaments.count.pluralSuffix) ci-dessous :")
|
|
|
|
link.append(tournaments.compactMap({ tournament in
|
|
if let url = tournament.shareURL(.info) {
|
|
var tournamentLink = [String]()
|
|
tournamentLink.append(tournament.tournamentTitle(.title))
|
|
tournamentLink.append(url.absoluteString)
|
|
return tournamentLink.joined(separator: "\n")
|
|
} else {
|
|
return nil
|
|
}
|
|
}).joined(separator: "\n\n"))
|
|
|
|
return link.compactMap({ $0 }).joined(separator: "\n\n")
|
|
}
|
|
|
|
public func selectedTeams() -> [TeamRegistration] {
|
|
confirmedTournaments().flatMap({ $0.selectedSortedTeams() })
|
|
}
|
|
|
|
public func umpireMail() -> [String]? {
|
|
confirmedTournaments().first?.umpireMail()
|
|
}
|
|
|
|
public func mailSubject() -> String {
|
|
let tournaments = confirmedTournaments()
|
|
|
|
guard !tournaments.isEmpty else {
|
|
return eventTitle()
|
|
}
|
|
|
|
// Get the date range from all confirmed tournaments
|
|
let dates = tournaments.compactMap { $0.startDate }
|
|
guard let firstDate = dates.min(), let lastDate = dates.max() else {
|
|
return eventTitle()
|
|
}
|
|
|
|
let dateRange = firstDate == lastDate
|
|
? firstDate.formattedDate(.short)
|
|
: "\(firstDate.formattedDate(.short)) - \(lastDate.formattedDate(.short))"
|
|
|
|
let subject = [eventTitle(), dateRange, clubObject()?.name].compactMap({ $0 }).joined(separator: " | ")
|
|
return subject
|
|
}
|
|
|
|
func insertOnServer() throws {
|
|
DataStore.shared.events.writeChangeAndInsertOnServer(instance: self)
|
|
for tournament in self.tournaments {
|
|
try tournament.insertOnServer()
|
|
}
|
|
for dataInterval in self.courtsUnavailability {
|
|
try dataInterval.insertOnServer()
|
|
}
|
|
}
|
|
|
|
}
|
|
|