Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions SportApp/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,22 @@ struct HomeView: View {
.navigationDestination(for: Tournir.self) { detail in
TournirsDetail()
.environmentObject(coordinator)
.environmentObject(viewModelOfTournirs)
}
}
.tabItem {
Label("Главная", systemImage: "house.fill")
}
.tag(0) // исправить потом

NavigationStack() {
EmptyView()
NavigationStack(path: $coordinator.statListPath) {
StatisticsView(viewModelOfStatistic: StatisticViewModel(tournirsVM: viewModelOfTournirs, coordinator: coordinator))
.environmentObject(coordinator)
.navigationDestination(for: Tournir.self) { detail in
TournirsDetail()
.environmentObject(coordinator)
.environmentObject(viewModelOfTournirs)
}
}
.tabItem {
Label("Мои матчи", systemImage: "pawprint.circle.fill")
Expand Down
1 change: 1 addition & 0 deletions SportApp/Navigation/Coordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Combine

class Coordinator: ObservableObject {
@Published var tournirListPath = NavigationPath()
@Published var statListPath = NavigationPath()
@Published var presentedSheet: ModalSheet?
@Published var user: User = User(id: UUID(), phio: "", password: "", email: "", isAdmin: false)
@Published var currentTournir: Tournir?
Expand Down
7 changes: 7 additions & 0 deletions SportApp/Registration/Model/User.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,10 @@ enum UserCodingKeys: String {
case mmr
case bio
}

struct PairAxoroms: Identifiable, Hashable, Codable {
var id = UUID()
var first: User
var second: User
var isFirstWinner: Bool?
}
39 changes: 35 additions & 4 deletions SportApp/Statistics/View/StatisticsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,44 @@ import SwiftUI

struct StatisticsView: View {
@EnvironmentObject var coordinator: Coordinator
@StateObject var viewModelOfStatistic: StatisticViewModel
@State var tournirs: [Tournir] = []

init(viewModelOfStatistic: StatisticViewModel) {
_viewModelOfStatistic = StateObject(wrappedValue: viewModelOfStatistic)
}

var body: some View {
if coordinator.user.isAdmin == true {

VStack {
ScrollView {
ForEach(TournirInstaseState.list, id: \.id) { state in
VStack {
Text(state.rawValue)

ForEach(tournirs, id: \.id) { tournir in
if tournir.tournirInstanteState == state {
TournirCell(tournir: tournir)
.padding(.horizontal, 16)
.padding(.vertical, 3)
.onTapGesture {
coordinator.tournirListPath = NavigationPath()
coordinator.currentTournir = tournir
coordinator.statListPath.append(tournir)
}
}
}
}
}
}
}
ScrollView{

.onAppear {
if coordinator.user.isAdmin == true {
tournirs = viewModelOfStatistic.tournirs4Admin()
} else {
tournirs = viewModelOfStatistic.tournirs4User()
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(red: 248/255, green: 247/255, blue: 255/255))
}
}
115 changes: 115 additions & 0 deletions SportApp/Statistics/ViewModel/StatisticViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//
// StatisticViewModel.swift
// SportApp
//
// Created by Zaitsev Vladislav on 11.07.2025.
//

import Foundation
import Combine

class StatisticViewModel: ObservableObject {
@Published var allTournirs: [Tournir] = []
@Published var user: User = User(id: UUID(), phio: "", password: "", email: "", isAdmin: false)

private var cancellables = Set<AnyCancellable>()

init(tournirsVM: TournirsViewModel, coordinator: Coordinator) {
coordinator.$user
.assign(to: \.user, on: self)
.store(in: &cancellables)

tournirsVM.$tournirs
.assign(to: \.allTournirs, on: self)
.store(in: &cancellables)
}

func tournirs4User() -> [Tournir] {
let mockTournirs: [Tournir] = [
// 1. Прошедший турнир
Tournir(
id: UUID(),
title: "Cупер кубок 2023",
description: "Главный футбольный турнир года, прошедший в Москве.",
sport: "Футбол",
type_group: .olympic,
type_tournir: .team,
start_time: Calendar.current.date(byAdding: .day, value: -10, to: Date())!,
created_at: Calendar.current.date(byAdding: .month, value: -6, to: Date())!,
entry_cost: 0.0,
is_team_based: true,
place: "Стадион 'Динамо', Москва",
max_participants: 32,
organizer_id: UUID(),
users: [user],
requirements: Requirements(),
tournirInstaseState: .endedTournaments
),

// 2. Турнир идёт
Tournir(
id: UUID(),
title: "Чемпионат города",
description: "Ежегодный баскетбольный чемпионат среди любительских команд.",
sport: "Баскетбол",
type_group: .olympic,
type_tournir: .team,
start_time: Calendar.current.date(byAdding: .hour, value: -2, to: Date())!,
created_at: Calendar.current.date(byAdding: .month, value: -3, to: Date())!,
entry_cost: 500.0,
is_team_based: true,
place: "Спортивный зал 'Арена'",
max_participants: 16,
organizer_id: UUID(),
users: [user],
requirements: Requirements(),
tournirInstaseState: .ongoingTournaments
),

// 3. Регистрация закрыта
Tournir(
id: UUID(),
title: "Турнир чемпионов",
description: "Волейбольный турнир для профессиональных клубов.",
sport: "Волейбол",
type_group: .olympic,
type_tournir: .team,
start_time: Calendar.current.date(byAdding: .day, value: 3, to: Date())!,
created_at: Calendar.current.date(byAdding: .month, value: -4, to: Date())!,
entry_cost: 1000.0,
is_team_based: true,
place: "Крытый спортивный комплекс",
max_participants: 8,
organizer_id: UUID(),
users: [user],
requirements: Requirements(),
tournirInstaseState: .closedRegistrationTournaments
),

// 4. Регистрация открыта
Tournir(
id: UUID(),
title: "Молодёжный кубок",
description: "Хоккейный турнир для молодых игроков до 21 года.",
sport: "Хоккей",
type_group: .olympic,
type_tournir: .team,
start_time: Calendar.current.date(byAdding: .weekOfYear, value: 2, to: Date())!,
created_at: Calendar.current.date(byAdding: .month, value: -1, to: Date())!,
entry_cost: 200.0,
is_team_based: true,
place: "Ледовая арена 'Звезда'",
max_participants: 12,
organizer_id: UUID(),
users: [user],
requirements: Requirements(),
tournirInstaseState: .openedRegistrationTournaments
)
]
return mockTournirs
}

func tournirs4Admin() -> [Tournir] {
allTournirs.filter { $0.organizer_id == user.id }
}
}
16 changes: 0 additions & 16 deletions SportApp/Statistics/ViewModel/StatisticsViewModel.swift

This file was deleted.

70 changes: 66 additions & 4 deletions SportApp/Tournirs/Model/Tournir.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,65 @@ struct Tournir: Codable, Identifiable, Hashable {
var organizer_id: UUID
var users: [User] = []
var requirements: Requirements
var tournirInstaseState: TournirInstaseState = .openedRegistrationTournaments
var tournirInstanteState: TournirInstaseState
var currentMatch: Int = 0
let matchs: Int

init(
id: UUID = UUID(),
title: String,
description: String,
sport: String,
type_group: TypeTournir,
type_tournir: TypeIsTeam,
start_time: Date,
created_at: Date,
entry_cost: Double,
is_team_based: Bool,
place: String,
max_participants: Int,
organizer_id: UUID,
users: [User] = [],
requirements: Requirements,
tournirInstaseState: TournirInstaseState = .openedRegistrationTournaments
) {
self.id = id
self.title = title
self.description = description
self.sport = sport
self.type_group = type_group
self.type_tournir = type_tournir
self.start_time = start_time
self.created_at = created_at
self.entry_cost = entry_cost
self.is_team_based = is_team_based
self.place = place
self.max_participants = max_participants
self.organizer_id = organizer_id
self.users = users
self.requirements = requirements
self.matchs = Int(ceil(log2(Double(max_participants))))
self.tournirInstanteState = tournirInstaseState

self.max_participants = nextPowerOfTwo(max_participants)
}

func nextPowerOfTwo(_ number: Int) -> Int {
guard number > 0 else { return 1 }
let exponent = log2(Double(number - 1)).rounded(.up)
return Int(pow(2.0, exponent))
}
}

enum TournirInstaseState: Codable, Identifiable, Hashable {
case pastTournament
enum TournirInstaseState: String, Codable, Identifiable, Hashable {
case endedTournaments
case ongoingTournaments
case closedRegistrationTournaments
case openedRegistrationTournaments

var id: Int {
switch self {
case .pastTournament:
case .endedTournaments:
return 1
case .ongoingTournaments:
return 2
Expand All @@ -44,6 +91,21 @@ enum TournirInstaseState: Codable, Identifiable, Hashable {
return 4
}
}

static func nextState(_ state: TournirInstaseState) -> TournirInstaseState {
switch state {
case .openedRegistrationTournaments:
return .closedRegistrationTournaments
case .closedRegistrationTournaments:
return .ongoingTournaments
case .ongoingTournaments:
return .endedTournaments
case .endedTournaments:
return .endedTournaments
}
}

static let list: [TournirInstaseState] = [.openedRegistrationTournaments, .closedRegistrationTournaments, .ongoingTournaments, .endedTournaments]
}

struct Requirements: Codable, Hashable {
Expand Down
2 changes: 1 addition & 1 deletion SportApp/Tournirs/View/TournirMaker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ struct TournirMaker: View {
Spacer()

Button(action: {
let tourinr: Tournir = Tournir(id: UUID(), title: name, description: description, sport: Sport.toStringEng(Sport.allSports[selectedSport]), type_group: .olympic, type_tournir: .solo, start_time: combinedDateTime, created_at: Date(), entry_cost: Double(cost) ?? 0, is_team_based: true, place: "", max_participants: 10, organizer_id: UUID(), requirements: Requirements())
let tourinr: Tournir = Tournir(id: UUID(), title: name, description: description, sport: Sport.toStringEng(Sport.allSports[selectedSport]), type_group: .olympic, type_tournir: .solo, start_time: combinedDateTime, created_at: Date(), entry_cost: Double(cost) ?? 0, is_team_based: true, place: "", max_participants: 16, organizer_id: coordinator.user.id, requirements: Requirements())
viewModel.tournirs.append(tourinr)
viewModel.giveTournir(tournir: tourinr)
coordinator.dismissSheet()
Expand Down
Loading
Loading