|
|
|
|
@ -8,24 +8,35 @@ |
|
|
|
|
import SwiftUI |
|
|
|
|
|
|
|
|
|
protocol SpinDrawable { |
|
|
|
|
func segmentLabel() -> String |
|
|
|
|
func segmentLabel(_ displayStyle: DisplayStyle) -> [String] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
extension String: SpinDrawable { |
|
|
|
|
func segmentLabel() -> String { |
|
|
|
|
self |
|
|
|
|
func segmentLabel(_ displayStyle: DisplayStyle) -> [String] { |
|
|
|
|
[self] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
extension Match: SpinDrawable { |
|
|
|
|
func segmentLabel() -> String { |
|
|
|
|
self.matchTitle(.wide) |
|
|
|
|
func segmentLabel(_ displayStyle: DisplayStyle) -> [String] { |
|
|
|
|
let teams = teams() |
|
|
|
|
if teams.count == 1 { |
|
|
|
|
return teams.first!.segmentLabel(displayStyle) |
|
|
|
|
} else { |
|
|
|
|
return [roundTitle(), matchTitle(displayStyle)].compactMap { $0 } |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
extension TeamRegistration: SpinDrawable { |
|
|
|
|
func segmentLabel() -> String { |
|
|
|
|
self.teamLabel(.short) |
|
|
|
|
func segmentLabel(_ displayStyle: DisplayStyle) -> [String] { |
|
|
|
|
var strings: [String] = [] |
|
|
|
|
let indexLabel = tournamentObject()?.labelIndexOf(team: self) |
|
|
|
|
if let indexLabel { |
|
|
|
|
strings.append(indexLabel) |
|
|
|
|
} |
|
|
|
|
strings.append(contentsOf: self.players().map { $0.playerLabel(displayStyle) }) |
|
|
|
|
return strings |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -40,15 +51,14 @@ struct DrawOption: Identifiable, SpinDrawable { |
|
|
|
|
let initialIndex: Int |
|
|
|
|
let option: SpinDrawable |
|
|
|
|
|
|
|
|
|
func segmentLabel() -> String { |
|
|
|
|
option.segmentLabel() |
|
|
|
|
func segmentLabel(_ displayStyle: DisplayStyle) -> [String] { |
|
|
|
|
option.segmentLabel(displayStyle) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct SpinDrawView: View { |
|
|
|
|
@Environment(\.dismiss) private var dismiss |
|
|
|
|
|
|
|
|
|
let time: Date = Date() |
|
|
|
|
let drawees: [any SpinDrawable] |
|
|
|
|
@State var segments: [any SpinDrawable] |
|
|
|
|
let completion: ([DrawResult]) -> Void // Completion closure |
|
|
|
|
@ -56,29 +66,20 @@ struct SpinDrawView: View { |
|
|
|
|
@State private var drawCount: Int = 0 |
|
|
|
|
@State private var draws: [DrawResult] = [DrawResult]() |
|
|
|
|
@State private var drawOptions: [DrawOption] = [DrawOption]() |
|
|
|
|
|
|
|
|
|
@State private var selectedIndex: Int? |
|
|
|
|
|
|
|
|
|
var autoMode: Bool { |
|
|
|
|
drawees.count > 1 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func validationLabel(drawee: Int, result: SpinDrawable) -> String { |
|
|
|
|
let draw = drawees[drawee] |
|
|
|
|
return draw.segmentLabel() + " -> " + result.segmentLabel() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@State private var selectedIndex: Int? |
|
|
|
|
var body: some View { |
|
|
|
|
List { |
|
|
|
|
Section { |
|
|
|
|
Text(time.formatted(date: .complete, time: .complete)) |
|
|
|
|
Text(time, style: .timer) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if selectedIndex != nil { |
|
|
|
|
Section { |
|
|
|
|
Text(validationLabel(drawee: drawCount, result: segments[draws.last!.drawIndex])) |
|
|
|
|
_validationLabelView(drawee: drawCount, result: segments[draws.last!.drawIndex]) |
|
|
|
|
if autoMode == false || drawCount == drawees.count { |
|
|
|
|
RowButtonView("ok") { |
|
|
|
|
RowButtonView("Valider le tirage") { |
|
|
|
|
completion(draws) |
|
|
|
|
dismiss() |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
@ -87,15 +88,15 @@ struct SpinDrawView: View { |
|
|
|
|
} |
|
|
|
|
} else if drawCount < drawees.count { |
|
|
|
|
Section { |
|
|
|
|
Text(drawees[drawCount].segmentLabel()) |
|
|
|
|
_segmentLabelView(segment: drawees[drawCount].segmentLabel(.wide), horizontalAlignment: .center) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Section { |
|
|
|
|
FortuneWheelTestView(segments: drawOptions, autoMode: autoMode) { index in |
|
|
|
|
FortuneWheelContainerView(segments: drawOptions, autoMode: autoMode) { index in |
|
|
|
|
self.selectedIndex = index |
|
|
|
|
self.draws.append(DrawResult(drawee: drawCount, drawIndex: drawOptions[index].initialIndex)) |
|
|
|
|
self.drawOptions.remove(at: index) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if autoMode && drawCount < drawees.count { |
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { |
|
|
|
|
self.drawCount += 1 |
|
|
|
|
@ -117,7 +118,7 @@ struct SpinDrawView: View { |
|
|
|
|
Section { |
|
|
|
|
Text("Tous les tirages sont terminés") |
|
|
|
|
ForEach(draws) { drawResult in |
|
|
|
|
Text(validationLabel(drawee: drawResult.drawee, result: segments[drawResult.drawIndex])) |
|
|
|
|
_validationLabelView(drawee: drawResult.drawee, result: segments[drawResult.drawIndex]) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -135,6 +136,18 @@ struct SpinDrawView: View { |
|
|
|
|
Text("Comité du tournoi") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
.toolbar { |
|
|
|
|
ToolbarItem(placement: .cancellationAction) { |
|
|
|
|
Button("Annuler", role: .cancel) { |
|
|
|
|
dismiss() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
.navigationBarBackButtonHidden() |
|
|
|
|
.navigationTitle("Tirage au sort") |
|
|
|
|
.navigationBarTitleDisplayMode(.inline) |
|
|
|
|
.toolbarBackground(.visible, for: .navigationBar) |
|
|
|
|
.toolbar(.hidden, for: .tabBar) |
|
|
|
|
.listStyle(.insetGrouped) |
|
|
|
|
.scrollDisabled(true) |
|
|
|
|
.onAppear { |
|
|
|
|
@ -143,9 +156,29 @@ struct SpinDrawView: View { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private func _segmentLabelView(segment: [String], horizontalAlignment: HorizontalAlignment = .leading) -> some View { |
|
|
|
|
VStack(alignment: horizontalAlignment, spacing: 0.0) { |
|
|
|
|
ForEach(segment, id: \.self) { string in |
|
|
|
|
Text(string) |
|
|
|
|
.frame(maxWidth: .infinity) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ViewBuilder |
|
|
|
|
private func _validationLabelView(drawee: Int, result: SpinDrawable) -> some View { |
|
|
|
|
HStack(spacing: 0.0) { |
|
|
|
|
let draw = drawees[drawee] |
|
|
|
|
_segmentLabelView(segment: draw.segmentLabel(.wide), horizontalAlignment: .leading) |
|
|
|
|
Image(systemName: "arrowshape.forward.fill") |
|
|
|
|
_segmentLabelView(segment: result.segmentLabel(.wide), horizontalAlignment: .trailing) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct FortuneWheelTestView: View { |
|
|
|
|
struct FortuneWheelContainerView: View { |
|
|
|
|
@State private var rotation: Double = 0 |
|
|
|
|
let segments: [any SpinDrawable] |
|
|
|
|
let autoMode: Bool |
|
|
|
|
@ -162,7 +195,6 @@ struct FortuneWheelTestView: View { |
|
|
|
|
.stroke(Color.black, lineWidth: 2) |
|
|
|
|
.frame(width: 20, height: 20) |
|
|
|
|
.rotationEffect(.degrees(180)) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
.onAppear { |
|
|
|
|
if autoMode { |
|
|
|
|
@ -186,7 +218,6 @@ struct FortuneWheelTestView: View { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func rollWheel() { |
|
|
|
|
|
|
|
|
|
rotation = 0 |
|
|
|
|
|
|
|
|
|
// Generate a random angle for the wheel to rotate |
|
|
|
|
@ -249,10 +280,16 @@ struct FortuneWheelView: View { |
|
|
|
|
} |
|
|
|
|
.fill(getColor(forIndex:index)) |
|
|
|
|
|
|
|
|
|
Text(segments[index].segmentLabel()).multilineTextAlignment(.trailing) |
|
|
|
|
.rotationEffect(.degrees(Double(index) * (360 / Double(segments.count)) + (360 / Double(segments.count) / 2))) |
|
|
|
|
.foregroundColor(.white) |
|
|
|
|
.position(arcPosition(index: index, radius: radius)) |
|
|
|
|
VStack(alignment: .trailing, spacing: 0.0) { |
|
|
|
|
let strings = segments[index].segmentLabel(.short) |
|
|
|
|
ForEach(strings, id: \.self) { string in |
|
|
|
|
Text(string).bold() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
.padding(.trailing, 30) |
|
|
|
|
.rotationEffect(.degrees(Double(index) * (360 / Double(segments.count)) + (360 / Double(segments.count) / 2))) |
|
|
|
|
.foregroundColor(.white) |
|
|
|
|
.position(arcPosition(index: index, radius: radius)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|