add loser bracket in pdf

newoffer2025
Raz 6 months ago
parent 2b3f102ac3
commit faaff120d7
  1. 12
      PadelClub.xcodeproj/project.pbxproj
  2. 2
      PadelClub/HTML Templates/bracket-template.html
  3. 13
      PadelClub/HTML Templates/match-template.html
  4. 23
      PadelClub/HTML Templates/tournament-template.html
  5. 2
      PadelClub/Utils/HtmlGenerator.swift
  6. 38
      PadelClub/Utils/HtmlService.swift
  7. 37
      PadelClub/Views/Tournament/Screen/PrintSettingsView.swift

@ -3120,7 +3120,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.2.27; MARKETING_VERSION = 1.2.28;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -3166,7 +3166,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.2.27; MARKETING_VERSION = 1.2.28;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -3285,7 +3285,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.2.27; MARKETING_VERSION = 1.2.28;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -3330,7 +3330,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.2.27; MARKETING_VERSION = 1.2.28;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -3374,7 +3374,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.2.27; MARKETING_VERSION = 1.2.28;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub.beta; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub.beta;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -3416,7 +3416,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.2.27; MARKETING_VERSION = 1.2.28;
PRODUCT_BUNDLE_IDENTIFIER = app.padelclub.beta; PRODUCT_BUNDLE_IDENTIFIER = app.padelclub.beta;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";

@ -1,5 +1,5 @@
<ul class="round"> <ul class="round">
<li class="spacer"> <li class="spacer" style="transform: translateY(-20px);">
&nbsp;{{roundLabel}} &nbsp;{{roundLabel}}
<div>{{formatLabel}}</div> <div>{{formatLabel}}</div>
</li> </li>

@ -1,8 +1,13 @@
<li class="game game-top {{entrantOneWon}}" style="visibility:{{hidden}}"> <li class="game game-top {{entrantOneWon}}" style="visibility:{{hidden}}; position: relative;">
{{entrantOne}} {{entrantOne}}
<div class="match-description-overlay" style="visibility:{{hidden}};">{{matchDescriptionTop}}</div>
</li> </li>
<li class="game game-spacer" style="visibility:{{hidden}}"><div class="multiline">{{matchDescription}}</div></li> <li class="game game-spacer" style="visibility:{{hidden}}">
<li class="game game-bottom {{entrantTwoWon}}" style="visibility:{{hidden}}"> </li>
{{entrantTwo}} <li class="game game-bottom {{entrantTwoWon}}" style="visibility:{{hidden}}; position: relative;">
<div style="transform: translateY(-100%);">
{{entrantTwo}}
</div>
<div class="match-description-overlay" style="visibility:{{hidden}};">{{matchDescriptionBottom}}</div>
</li> </li>
<li class="spacer">&nbsp;</li> <li class="spacer">&nbsp;</li>

@ -92,11 +92,32 @@
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.game {
/* Ensure the game container is a positioning context for the overlay */
position: relative;
/* Add any other existing styles for your game list items */
}
.match-description-overlay {
/* Position the overlay directly on top of the game item */
position: absolute;
top: 0;
left: 0;
transform: translateY(100%);
width: 100%;
height: 100%;
display: flex; /* Enable flexbox for centering */
justify-content: center; /* Center horizontally */
align-items: center; /* Center vertically (if needed) */
font-size: 1em; /* Optional: Adjust font size */
/* Add any other desired styling for the overlay */
}
</style> </style>
</head> </head>
<body> <body>
<h3>{{tournamentTitle}} - {{tournamentStartDate}}</h3> <h3 style="visibility:{{titleHidden}}">{{tournamentTitle}} - {{tournamentStartDate}}</h3>
<main id="tournament"> <main id="tournament">
{{brackets}} {{brackets}}
</main> </main>

@ -176,7 +176,7 @@ class HtmlGenerator: ObservableObject {
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).html(headName: displayHeads, withRank: displayRank, withTeamIndex: displayTeamIndex, withScore: displayScore) HtmlService.loserBracket(upperRound: upperRound, hideTitle: false).html(headName: displayHeads, withRank: displayRank, withTeamIndex: displayTeamIndex, withScore: displayScore)
} }
var pdfURL: URL? { var pdfURL: URL? {

@ -12,7 +12,7 @@ enum HtmlService {
case template(tournament: Tournament) case template(tournament: Tournament)
case bracket(round: Round) case bracket(round: Round)
case loserBracket(upperRound: Round) case loserBracket(upperRound: Round, hideTitle: Bool)
case match(match: Match) case match(match: Match)
case player(entrant: TeamRegistration) case player(entrant: TeamRegistration)
case hiddenPlayer case hiddenPlayer
@ -187,11 +187,17 @@ enum HtmlService {
var template = html var template = html
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(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore))
if withScore, let top = match.topPreviousRoundMatch(), top.hasEnded() {
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(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore))
} }
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(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore))
if withScore, let bottom = match.bottomPreviousRoundMatch(), bottom.hasEnded() {
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(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore))
} }
@ -206,9 +212,10 @@ enum HtmlService {
} else if match.teamWon(atPosition: .two) == true { } else if match.teamWon(atPosition: .two) == true {
template = template.replacingOccurrences(of: "{{entrantTwoWon}}", with: "winner") template = template.replacingOccurrences(of: "{{entrantTwoWon}}", with: "winner")
} }
template = template.replacingOccurrences(of: "{{matchDescription}}", with: [match.localizedStartDate(), match.scoreLabel()].joined(separator: "\n")) // template = template.replacingOccurrences(of: "{{matchDescription}}", with: [match.localizedStartDate(), match.scoreLabel()].joined(separator: "\n"))
} }
template = template.replacingOccurrences(of: "{{matchDescription}}", with: "") template = template.replacingOccurrences(of: "{{matchDescriptionTop}}", with: "")
template = template.replacingOccurrences(of: "{{matchDescriptionBottom}}", with: "")
return template return template
case .bracket(let round): case .bracket(let round):
var template = "" var template = ""
@ -216,16 +223,31 @@ enum HtmlService {
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(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore))
} }
bracket = html.replacingOccurrences(of: "{{match-template}}", with: template) bracket = html.replacingOccurrences(of: "{{match-template}}", with: template)
bracket = bracket.replacingOccurrences(of: "{{roundLabel}}", with: round.roundTitle()) bracket = bracket.replacingOccurrences(of: "{{roundLabel}}", with: round.roundTitle())
bracket = bracket.replacingOccurrences(of: "{{formatLabel}}", with: round.matchFormat.formatTitle()) bracket = bracket.replacingOccurrences(of: "{{formatLabel}}", with: round.matchFormat.formatTitle())
return bracket return bracket
case .loserBracket(let upperRound): 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: "{{tournamentTitle}}", with: upperRound.correspondingLoserRoundTitle()) template = template.replacingOccurrences(of: "{{tournamentTitle}}", with: upperRound.correspondingLoserRoundTitle())
if let tournamentStartDate = upperRound.initialStartDate()?.localizedDate() {
template = template.replacingOccurrences(of: "{{tournamentStartDate}}", with: tournamentStartDate)
} else {
template = template.replacingOccurrences(of: "{{tournamentStartDate}}", with: "")
}
template = template.replacingOccurrences(of: "{{titleHidden}}", with: hideTitle ? "hidden" : "")
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(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore))
if round.index == 1 {
let sub = HtmlService.loserBracket(upperRound: round, hideTitle: true).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)
template = template.appending(sub)
}
} }
let winnerName = "" let winnerName = ""
let winner = """ let winner = """
@ -240,6 +262,14 @@ enum HtmlService {
brackets = brackets.appending(winner) brackets = brackets.appending(winner)
template = template.replacingOccurrences(of: "{{brackets}}", with: brackets) template = template.replacingOccurrences(of: "{{brackets}}", with: brackets)
for round in upperRound.loserRounds() {
if round.index > 1 {
let sub = HtmlService.loserBracket(upperRound: round, hideTitle: true).html(headName: headName, withRank: withRank, withTeamIndex: withTeamIndex, withScore: withScore)
template = template.appending(sub)
}
}
return template return template
case .template(let tournament): case .template(let tournament):
var template = html var template = html

@ -47,9 +47,9 @@ struct PrintSettingsView: View {
Text("Tableau") Text("Tableau")
}) })
// Toggle(isOn: $generator.includeLoserBracket, label: { Toggle(isOn: $generator.includeLoserBracket, label: {
// Text("Tableau des matchs de classements") Text("Tableau des matchs de classements")
// }) })
if tournament.groupStages().isEmpty == false { if tournament.groupStages().isEmpty == false {
Toggle(isOn: $generator.includeGroupStage, label: { Toggle(isOn: $generator.includeGroupStage, label: {
@ -132,18 +132,18 @@ struct PrintSettingsView: View {
} label: { } label: {
Text("Aperçu du tableau") Text("Aperçu du tableau")
} }
//
// ForEach(tournament.rounds()) { round in ForEach(tournament.rounds()) { round in
// if round.index > 0 { if round.index > 0 {
// NavigationLink { NavigationLink {
// WebViewPreview(round: round) WebViewPreview(round: round)
// .environmentObject(generator) .environmentObject(generator)
// } label: { } label: {
// Text("Aperçu \(round.correspondingLoserRoundTitle())") Text("Aperçu \(round.correspondingLoserRoundTitle())")
// } }
// } }
// } }
//
ForEach(tournament.groupStages()) { groupStage in ForEach(tournament.groupStages()) { groupStage in
NavigationLink { NavigationLink {
WebViewPreview(groupStage: groupStage) WebViewPreview(groupStage: groupStage)
@ -182,6 +182,13 @@ struct PrintSettingsView: View {
Text("Poule") Text("Poule")
} }
} }
if let round = tournament.rounds().first {
ShareLink(item: generator.generateLoserBracketHtml(upperRound: round)) {
Text("Classement")
}
}
} header: { } header: {
Text("Partager le code source HTML") Text("Partager le code source HTML")
} }

Loading…
Cancel
Save