add planned date display in print options

newoffer2025
Razmig Sarkissian 4 months ago
parent 070d221a56
commit 3781aac090
  1. 4
      PadelClub.xcodeproj/project.pbxproj
  2. 1
      PadelClub/HTML Templates/match-template.html
  3. 8
      PadelClub/HTML Templates/tournament-template.html
  4. 9
      PadelClub/Utils/HtmlGenerator.swift
  5. 85
      PadelClub/Utils/HtmlService.swift
  6. 12
      PadelClub/Views/Tournament/Screen/PrintSettingsView.swift

@ -3137,7 +3137,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.2.42; MARKETING_VERSION = 1.2.43;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -3183,7 +3183,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.2.42; MARKETING_VERSION = 1.2.43;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";

@ -3,6 +3,7 @@
<div class="match-description-overlay" style="visibility:{{hidden}};">{{matchDescriptionTop}}</div> <div class="match-description-overlay" style="visibility:{{hidden}};">{{matchDescriptionTop}}</div>
</li> </li>
<li class="game game-spacer" style="visibility:{{hidden}}"> <li class="game game-spacer" style="visibility:{{hidden}}">
<div class="center-match-overlay" style="visibility:{{hidden}};">{{centerMatchText}}</div>
</li> </li>
<li class="game game-bottom {{entrantTwoWon}}" style="visibility:{{hidden}}; position: relative;"> <li class="game game-bottom {{entrantTwoWon}}" style="visibility:{{hidden}}; position: relative;">
<div style="transform: translateY(-100%);"> <div style="transform: translateY(-100%);">

@ -113,6 +113,14 @@
font-size: 1em; /* Optional: Adjust font size */ font-size: 1em; /* Optional: Adjust font size */
/* Add any other desired styling for the overlay */ /* Add any other desired styling for the overlay */
} }
.center-match-overlay {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 0.8em;
white-space: nowrap; /* Prevents text from wrapping */
}
</style> </style>
</head> </head>
<body> <body>

@ -27,6 +27,7 @@ class HtmlGenerator: ObservableObject {
@Published var displayRank: Bool = false @Published var displayRank: Bool = false
@Published var displayTeamIndex: Bool = false @Published var displayTeamIndex: Bool = false
@Published var displayScore: Bool = false @Published var displayScore: Bool = false
@Published var displayPlannedDate: Bool = true
private var pdfDocument: PDFDocument = PDFDocument() private var pdfDocument: PDFDocument = PDFDocument()
private var rects: [CGRect] = [] private var rects: [CGRect] = []
@ -179,12 +180,16 @@ class HtmlGenerator: ObservableObject {
func generateHtml() -> String { func generateHtml() -> String {
//HtmlService.groupstage(bracket: tournament.orderedBrackets.first!).html() //HtmlService.groupstage(bracket: tournament.orderedBrackets.first!).html()
HtmlService.template(tournament: tournament).html(headName: displayHeads, withRank: displayRank, withTeamIndex: displayTeamIndex, withScore: displayScore) HtmlService.template(tournament: tournament).html(options: options)
} }
func generateLoserBracketHtml(upperRound: Round) -> String { func generateLoserBracketHtml(upperRound: Round) -> String {
//HtmlService.groupstage(bracket: tournament.orderedBrackets.first!).html() //HtmlService.groupstage(bracket: tournament.orderedBrackets.first!).html()
HtmlService.loserBracket(upperRound: upperRound, hideTitle: false).html(headName: displayHeads, withRank: displayRank, withTeamIndex: displayTeamIndex, withScore: displayScore) HtmlService.loserBracket(upperRound: upperRound, hideTitle: false).html(options: options)
}
var options: HtmlOptions {
HtmlOptions(headName: displayHeads, withRank: displayRank, withTeamIndex: displayTeamIndex, withScore: displayScore, withPlannedDate: displayPlannedDate)
} }
var pdfURL: URL? { var pdfURL: URL? {

@ -8,6 +8,29 @@
import Foundation import Foundation
import PadelClubData import PadelClubData
struct HtmlOptions {
let headName: Bool
let withRank: Bool
let withTeamIndex: Bool
let withScore: Bool
let withPlannedDate: Bool
// Default initializer with all options defaulting to true
init(
headName: Bool = true,
withRank: Bool = true,
withTeamIndex: Bool = true,
withScore: Bool = true,
withPlannedDate: Bool = true
) {
self.headName = headName
self.withRank = withRank
self.withTeamIndex = withTeamIndex
self.withScore = withScore
self.withPlannedDate = withPlannedDate
}
}
enum HtmlService { enum HtmlService {
case template(tournament: Tournament) case template(tournament: Tournament)
@ -51,7 +74,7 @@ enum HtmlService {
} }
} }
func html(headName: Bool, withRank: Bool, withTeamIndex: Bool, withScore: Bool) -> String { func html(options: HtmlOptions = HtmlOptions()) -> String {
guard let file = Bundle.main.path(forResource: self.fileName, ofType: "html") else { guard let file = Bundle.main.path(forResource: self.fileName, ofType: "html") else {
fatalError() fatalError()
} }
@ -74,8 +97,8 @@ enum HtmlService {
var col = "" var col = ""
var row = "" var row = ""
bracket.teams().forEach { entrant in bracket.teams().forEach { entrant in
col = col.appending(HtmlService.groupstageColumn(entrant: entrant, position: "col").html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)) col = col.appending(HtmlService.groupstageColumn(entrant: entrant, position: "col").html(options: options))
row = row.appending(HtmlService.groupstageRow(entrant: entrant, teamsPerBracket: bracket.size).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)) row = row.appending(HtmlService.groupstageRow(entrant: entrant, teamsPerBracket: bracket.size).html(options: options))
} }
template = template.replacingOccurrences(of: "{{teamsCol}}", with: col) template = template.replacingOccurrences(of: "{{teamsCol}}", with: col)
template = template.replacingOccurrences(of: "{{teamsRow}}", with: row) template = template.replacingOccurrences(of: "{{teamsRow}}", with: row)
@ -83,7 +106,7 @@ enum HtmlService {
return template return template
case .groupstageEntrant(let entrant): case .groupstageEntrant(let entrant):
var template = html var template = html
if withTeamIndex == false { if options.withTeamIndex == false {
template = template.replacingOccurrences(of: #"<div class="player">{{teamIndex}}</div>"#, with: "") template = template.replacingOccurrences(of: #"<div class="player">{{teamIndex}}</div>"#, with: "")
} else { } else {
template = template.replacingOccurrences(of: "{{teamIndex}}", with: entrant.seedIndex() ?? "") template = template.replacingOccurrences(of: "{{teamIndex}}", with: entrant.seedIndex() ?? "")
@ -91,7 +114,7 @@ enum HtmlService {
if let playerOne = entrant.players()[safe: 0] { if let playerOne = entrant.players()[safe: 0] {
template = template.replacingOccurrences(of: "{{playerOne}}", with: playerOne.playerLabel()) template = template.replacingOccurrences(of: "{{playerOne}}", with: playerOne.playerLabel())
if withRank { if options.withRank {
template = template.replacingOccurrences(of: "{{weightOne}}", with: "(\(playerOne.formattedRank()))") template = template.replacingOccurrences(of: "{{weightOne}}", with: "(\(playerOne.formattedRank()))")
} else { } else {
template = template.replacingOccurrences(of: "{{weightOne}}", with: "") template = template.replacingOccurrences(of: "{{weightOne}}", with: "")
@ -103,7 +126,7 @@ enum HtmlService {
if let playerTwo = entrant.players()[safe: 1] { if let playerTwo = entrant.players()[safe: 1] {
template = template.replacingOccurrences(of: "{{playerTwo}}", with: playerTwo.playerLabel()) template = template.replacingOccurrences(of: "{{playerTwo}}", with: playerTwo.playerLabel())
if withRank { if options.withRank {
template = template.replacingOccurrences(of: "{{weightTwo}}", with: "(\(playerTwo.formattedRank()))") template = template.replacingOccurrences(of: "{{weightTwo}}", with: "(\(playerTwo.formattedRank()))")
} else { } else {
template = template.replacingOccurrences(of: "{{weightTwo}}", with: "") template = template.replacingOccurrences(of: "{{weightTwo}}", with: "")
@ -115,7 +138,7 @@ enum HtmlService {
return template return template
case .groupstageRow(let entrant, let teamsPerBracket): case .groupstageRow(let entrant, let teamsPerBracket):
var template = html var template = html
template = template.replacingOccurrences(of: "{{team}}", with: HtmlService.groupstageColumn(entrant: entrant, position: "row").html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)) template = template.replacingOccurrences(of: "{{team}}", with: HtmlService.groupstageColumn(entrant: entrant, position: "row").html(options: options))
var scores = "" var scores = ""
(0..<teamsPerBracket).forEach { index in (0..<teamsPerBracket).forEach { index in
@ -124,18 +147,18 @@ enum HtmlService {
if shouldHide == false { if shouldHide == false {
match = entrant.groupStageObject()?.matchPlayed(by: entrant.groupStagePosition!, againstPosition: index) match = entrant.groupStageObject()?.matchPlayed(by: entrant.groupStagePosition!, againstPosition: index)
} }
scores.append(HtmlService.groupstageScore(score: match, shouldHide: shouldHide).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)) scores.append(HtmlService.groupstageScore(score: match, shouldHide: shouldHide).html(options: options))
} }
template = template.replacingOccurrences(of: "{{scores}}", with: scores) template = template.replacingOccurrences(of: "{{scores}}", with: scores)
return template return template
case .groupstageColumn(let entrant, let position): case .groupstageColumn(let entrant, let position):
var template = html var template = html
template = template.replacingOccurrences(of: "{{tablePosition}}", with: position) template = template.replacingOccurrences(of: "{{tablePosition}}", with: position)
template = template.replacingOccurrences(of: "{{team}}", with: HtmlService.groupstageEntrant(entrant: entrant).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)) template = template.replacingOccurrences(of: "{{team}}", with: HtmlService.groupstageEntrant(entrant: entrant).html(options: options))
return template return template
case .groupstageScore(let match, let shouldHide): case .groupstageScore(let match, let shouldHide):
var template = html var template = html
if match == nil || withScore == false { if match == nil || options.withScore == false {
template = template.replacingOccurrences(of: "{{winner}}", with: "") template = template.replacingOccurrences(of: "{{winner}}", with: "")
template = template.replacingOccurrences(of: "{{score}}", with: "") template = template.replacingOccurrences(of: "{{score}}", with: "")
} else if let match, let winner = match.winner() { } else if let match, let winner = match.winner() {
@ -146,7 +169,7 @@ enum HtmlService {
return template return template
case .player(let entrant): case .player(let entrant):
var template = html var template = html
if withTeamIndex == false { if options.withTeamIndex == false {
template = template.replacingOccurrences(of: #"<div class="player">{{teamIndex}}</div>"#, with: "") template = template.replacingOccurrences(of: #"<div class="player">{{teamIndex}}</div>"#, with: "")
} else { } else {
template = template.replacingOccurrences(of: "{{teamIndex}}", with: entrant.formattedSeed()) template = template.replacingOccurrences(of: "{{teamIndex}}", with: entrant.formattedSeed())
@ -155,7 +178,7 @@ enum HtmlService {
if let playerOne = entrant.players()[safe: 0] { if let playerOne = entrant.players()[safe: 0] {
template = template.replacingOccurrences(of: "{{playerOne}}", with: playerOne.playerLabel()) template = template.replacingOccurrences(of: "{{playerOne}}", with: playerOne.playerLabel())
if withRank { if options.withRank {
template = template.replacingOccurrences(of: "{{weightOne}}", with: "(\(playerOne.formattedRank()))") template = template.replacingOccurrences(of: "{{weightOne}}", with: "(\(playerOne.formattedRank()))")
} else { } else {
template = template.replacingOccurrences(of: "{{weightOne}}", with: "") template = template.replacingOccurrences(of: "{{weightOne}}", with: "")
@ -167,7 +190,7 @@ enum HtmlService {
if let playerTwo = entrant.players()[safe: 1] { if let playerTwo = entrant.players()[safe: 1] {
template = template.replacingOccurrences(of: "{{playerTwo}}", with: playerTwo.playerLabel()) template = template.replacingOccurrences(of: "{{playerTwo}}", with: playerTwo.playerLabel())
if withRank { if options.withRank {
template = template.replacingOccurrences(of: "{{weightTwo}}", with: "(\(playerTwo.formattedRank()))") template = template.replacingOccurrences(of: "{{weightTwo}}", with: "(\(playerTwo.formattedRank()))")
} else { } else {
template = template.replacingOccurrences(of: "{{weightTwo}}", with: "") template = template.replacingOccurrences(of: "{{weightTwo}}", with: "")
@ -179,27 +202,32 @@ enum HtmlService {
return template return template
case .hiddenPlayer: case .hiddenPlayer:
var template = html + html var template = html + html
if withTeamIndex { if options.withTeamIndex {
template += html template += html
} }
return template return template
case .match(let match): case .match(let match):
var template = html var template = html
if options.withPlannedDate, let plannedStartDate = match.plannedStartDate {
template = template.replacingOccurrences(of: "{{centerMatchText}}", with: plannedStartDate.localizedDate())
} else {
}
if let entrantOne = match.team(.one) { if let entrantOne = match.team(.one) {
template = template.replacingOccurrences(of: "{{entrantOne}}", with: HtmlService.player(entrant: entrantOne).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)) template = template.replacingOccurrences(of: "{{entrantOne}}", with: HtmlService.player(entrant: entrantOne).html(options: options))
if withScore, let top = match.topPreviousRoundMatch(), top.hasEnded() { if options.withScore, let top = match.topPreviousRoundMatch(), top.hasEnded() {
template = template.replacingOccurrences(of: "{{matchDescriptionTop}}", with: [top.scoreLabel(winnerFirst:true)].compactMap({ $0 }).joined(separator: "\n")) template = template.replacingOccurrences(of: "{{matchDescriptionTop}}", with: [top.scoreLabel(winnerFirst:true)].compactMap({ $0 }).joined(separator: "\n"))
} }
} else { } else {
template = template.replacingOccurrences(of: "{{entrantOne}}", with: HtmlService.hiddenPlayer.html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)) template = template.replacingOccurrences(of: "{{entrantOne}}", with: HtmlService.hiddenPlayer.html(options: options))
} }
if let entrantTwo = match.team(.two) { if let entrantTwo = match.team(.two) {
template = template.replacingOccurrences(of: "{{entrantTwo}}", with: HtmlService.player(entrant: entrantTwo).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)) template = template.replacingOccurrences(of: "{{entrantTwo}}", with: HtmlService.player(entrant: entrantTwo).html(options: options))
if withScore, let bottom = match.bottomPreviousRoundMatch(), bottom.hasEnded() { if options.withScore, let bottom = match.bottomPreviousRoundMatch(), bottom.hasEnded() {
template = template.replacingOccurrences(of: "{{matchDescriptionBottom}}", with: [bottom.scoreLabel(winnerFirst:true)].compactMap({ $0 }).joined(separator: "\n")) template = template.replacingOccurrences(of: "{{matchDescriptionBottom}}", with: [bottom.scoreLabel(winnerFirst:true)].compactMap({ $0 }).joined(separator: "\n"))
} }
} else { } else {
template = template.replacingOccurrences(of: "{{entrantTwo}}", with: HtmlService.hiddenPlayer.html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)) template = template.replacingOccurrences(of: "{{entrantTwo}}", with: HtmlService.hiddenPlayer.html(options: options))
} }
if match.disabled { if match.disabled {
template = template.replacingOccurrences(of: "{{hidden}}", with: "hidden") template = template.replacingOccurrences(of: "{{hidden}}", with: "hidden")
@ -216,12 +244,13 @@ enum HtmlService {
} }
template = template.replacingOccurrences(of: "{{matchDescriptionTop}}", with: "") template = template.replacingOccurrences(of: "{{matchDescriptionTop}}", with: "")
template = template.replacingOccurrences(of: "{{matchDescriptionBottom}}", with: "") template = template.replacingOccurrences(of: "{{matchDescriptionBottom}}", with: "")
template = template.replacingOccurrences(of: "{{centerMatchText}}", with: "")
return template return template
case .bracket(let round): case .bracket(let round):
var template = "" var template = ""
var bracket = "" var bracket = ""
for (_, match) in round._matches().enumerated() { for (_, match) in round._matches().enumerated() {
template = template.appending(HtmlService.match(match: match).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)) template = template.appending(HtmlService.match(match: match).html(options: options))
} }
bracket = html.replacingOccurrences(of: "{{match-template}}", with: template) bracket = html.replacingOccurrences(of: "{{match-template}}", with: template)
@ -230,7 +259,7 @@ enum HtmlService {
return bracket return bracket
case .loserBracket(let upperRound, let hideTitle): case .loserBracket(let upperRound, let hideTitle):
var template = html var template = html
template = template.replacingOccurrences(of: "{{minHeight}}", with: withTeamIndex ? "226" : "156") template = template.replacingOccurrences(of: "{{minHeight}}", with: options.withTeamIndex ? "226" : "156")
template = template.replacingOccurrences(of: "{{tournamentTitle}}", with: upperRound.correspondingLoserRoundTitle()) template = template.replacingOccurrences(of: "{{tournamentTitle}}", with: upperRound.correspondingLoserRoundTitle())
if let tournamentStartDate = upperRound.initialStartDate()?.localizedDate() { if let tournamentStartDate = upperRound.initialStartDate()?.localizedDate() {
template = template.replacingOccurrences(of: "{{tournamentStartDate}}", with: tournamentStartDate) template = template.replacingOccurrences(of: "{{tournamentStartDate}}", with: tournamentStartDate)
@ -242,10 +271,10 @@ enum HtmlService {
var brackets = "" var brackets = ""
for round in upperRound.loserRounds() { for round in upperRound.loserRounds() {
brackets = brackets.appending(HtmlService.bracket(round: round).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)) brackets = brackets.appending(HtmlService.bracket(round: round).html(options: options))
if round.index == 1 { if round.index == 1 {
let sub = HtmlService.loserBracket(upperRound: round, hideTitle: true).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore) let sub = HtmlService.loserBracket(upperRound: round, hideTitle: true).html(options: options)
template = template.appending(sub) template = template.appending(sub)
} }
} }
@ -265,7 +294,7 @@ enum HtmlService {
for round in upperRound.loserRounds() { for round in upperRound.loserRounds() {
if round.index > 1 { if round.index > 1 {
let sub = HtmlService.loserBracket(upperRound: round, hideTitle: true).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore) let sub = HtmlService.loserBracket(upperRound: round, hideTitle: true).html(options: options)
template = template.appending(sub) template = template.appending(sub)
} }
} }
@ -273,17 +302,17 @@ enum HtmlService {
return template return template
case .template(let tournament): case .template(let tournament):
var template = html var template = html
template = template.replacingOccurrences(of: "{{minHeight}}", with: withTeamIndex ? "226" : "156") template = template.replacingOccurrences(of: "{{minHeight}}", with: options.withTeamIndex ? "226" : "156")
template = template.replacingOccurrences(of: "{{tournamentTitle}}", with: tournament.tournamentTitle(.title)) template = template.replacingOccurrences(of: "{{tournamentTitle}}", with: tournament.tournamentTitle(.title))
template = template.replacingOccurrences(of: "{{tournamentStartDate}}", with: tournament.formattedDate()) template = template.replacingOccurrences(of: "{{tournamentStartDate}}", with: tournament.formattedDate())
var brackets = "" var brackets = ""
for round in tournament.rounds() { for round in tournament.rounds() {
brackets = brackets.appending(HtmlService.bracket(round: round).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)) brackets = brackets.appending(HtmlService.bracket(round: round).html(options: options))
} }
var winnerName = "" var winnerName = ""
if let tournamentWinner = tournament.tournamentWinner() { if let tournamentWinner = tournament.tournamentWinner() {
winnerName = HtmlService.player(entrant: tournamentWinner).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore) winnerName = HtmlService.player(entrant: tournamentWinner).html(options: options)
} }
let winner = """ let winner = """
<ul class="round" scope="last"> <ul class="round" scope="last">

@ -28,7 +28,11 @@ struct PrintSettingsView: View {
Section { Section {
// Toggle(isOn: $generator.displayHeads, label: { // Toggle(isOn: $generator.displayHeads, label: {
// Text("Afficher les têtes de séries") // Text("Afficher les têtes de séries")
// }) // }
Toggle(isOn: $generator.displayPlannedDate, label: {
Text("Afficher la date plannifiée")
})
Toggle(isOn: $generator.displayTeamIndex, label: { Toggle(isOn: $generator.displayTeamIndex, label: {
Text("Afficher le poids et le rang de l'équipe") Text("Afficher le poids et le rang de l'équipe")
@ -178,7 +182,7 @@ struct PrintSettingsView: View {
} }
if let groupStage = tournament.groupStages().first { if let groupStage = tournament.groupStages().first {
ShareLink(item: HtmlService.groupstage(groupStage: groupStage).html(headName: generator.displayHeads, withRank: generator.displayRank, withTeamIndex: generator.displayTeamIndex, withScore: generator.displayScore)) { ShareLink(item: HtmlService.groupstage(groupStage: groupStage).html(options: generator.options)) {
Text("Poule") Text("Poule")
} }
} }
@ -219,7 +223,7 @@ struct PrintSettingsView: View {
Group { Group {
if prepareGroupStage { if prepareGroupStage {
ForEach(tournament.groupStages()) { groupStage in ForEach(tournament.groupStages()) { groupStage in
WebView(htmlRawData: HtmlService.groupstage(groupStage: groupStage).html(headName: generator.displayHeads, withRank: generator.displayRank, withTeamIndex: generator.displayTeamIndex, withScore: generator.displayScore), loadStatusChanged: { loaded, error, webView in WebView(htmlRawData: HtmlService.groupstage(groupStage: groupStage).html(options: generator.options), loadStatusChanged: { loaded, error, webView in
if let error { if let error {
print("preparePDF", error) print("preparePDF", error)
} else if loaded == false { } else if loaded == false {
@ -321,7 +325,7 @@ struct WebViewPreview: View {
ProgressView() ProgressView()
.onAppear { .onAppear {
if let groupStage { if let groupStage {
html = HtmlService.groupstage(groupStage: groupStage).html(headName: generator.displayHeads, withRank: generator.displayRank, withTeamIndex: generator.displayTeamIndex, withScore: generator.displayScore) html = HtmlService.groupstage(groupStage: groupStage).html(options: generator.options)
} else if let round { } else if let round {
html = generator.generateLoserBracketHtml(upperRound: round) html = generator.generateLoserBracketHtml(upperRound: round)
} else { } else {

Loading…
Cancel
Save