Added codeable protocol to classes to deserialize API json objects 🔨

pull/23/head
Emre KARTAL 1 year ago
parent de12721408
commit 18a01ab349

@ -19,7 +19,7 @@ struct BetCard: View {
VStack(alignment: .leading,spacing: 2){
HStack{
Spacer()
Text("proposé par " + bet.author.username.capitalized)
Text("proposé par " + bet.author.capitalized)
.font(.system(size: 10))
.foregroundColor(AllInColors.grey800Color)
@ -82,7 +82,7 @@ struct BetCard_Previews: PreviewProvider {
isPublic: true,
status: .inProgress,
invited: [],
author: User(username: "Imri", email: "emre.kartal@etu.uca.fr", nbCoins: 75, friends: []),
author: "Imri",
registered: []))
.preferredColorScheme(.dark)
}

@ -15,8 +15,8 @@ struct BetLineLoading: View {
var value: CGFloat {
let totalParticipations = participations.count
let numberOfYes = participations.filter { $0.response.uppercased() == "YES" }.count
let numberOfNo = participations.filter { $0.response.uppercased() == "NO" }.count
let numberOfYes = participations.filter { $0.answer.uppercased() == "YES" }.count
let numberOfNo = participations.filter { $0.answer.uppercased() == "NO" }.count
if(numberOfNo == 0 && numberOfYes == 0){
return 0.5
}
@ -25,11 +25,11 @@ struct BetLineLoading: View {
}
var yesParticipations: [Participation] {
participations.filter { $0.response.uppercased() == "YES" }
participations.filter { $0.answer.uppercased() == "YES" }
}
var noParticipations: [Participation] {
participations.filter { $0.response.uppercased() == "NO" }
participations.filter { $0.answer.uppercased() == "NO" }
}
var body: some View {

@ -1,5 +1,5 @@
//
// ParticiationCell.swift
// ParticipationCell.swift
// AllIn
//
// Created by Lucas Delanier on 21/01/2024.
@ -8,20 +8,20 @@
import SwiftUI
import Model
struct ParticiationCell: View {
@State var participation: Participation?
struct ParticipationCell: View {
@State var participation: Participation
var body: some View {
HStack(alignment: .center, spacing: 0){
Circle()
.frame(width: 30, height: 30)
.foregroundColor(AllInColors.grey700Color)
.padding(.trailing, 7)
Text(participation?.user.username ?? "Unknown")
Text(participation.username)
.font(.system(size: 15))
.foregroundStyle(AllInColors.primaryTextColor)
.fontWeight(.semibold)
Spacer()
Text(participation?.stake.description ?? "NaN")
Text(participation.stake.description)
.font(.system(size: 18))
.foregroundStyle(AllInColors.lightPurpleColor)
.fontWeight(.bold)

@ -22,7 +22,7 @@ struct ReviewCard: View {
VStack(alignment: .leading,spacing: 2){
HStack{
Spacer()
Text("proposé par \(betDetail.bet.author.username)")
Text("proposé par \(betDetail.bet.author)")
.font(.system(size: 10))
.foregroundColor(AllInColors.grey800Color)
@ -44,7 +44,7 @@ struct ReviewCard: View {
VStack(alignment: .center,spacing:0){
HStack(){
Spacer()
if(betDetail.bet.isFinish()){
if(betDetail.bet.endBetDate < Date()){
Text("Terminé")
.foregroundColor(.white)
.font(.system(size: 25))
@ -72,7 +72,7 @@ struct ReviewCard: View {
.frame(width: .infinity)
.padding(.all,2)
.background(
isAWin || betDetail.bet.isFinish() ?
isAWin || betDetail.bet.endBetDate < Date() ?
AnyView(AllInColors.primaryGradient) :
AnyView(Color.black)
) .cornerRadius(20, corners: [.bottomLeft,.bottomRight])

@ -110,14 +110,11 @@ class AuthService: IAuthService {
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data,
let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode == 200 {
if let userJson = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
let user = User.mapUser(from: userJson) {
AppStateContainer.shared.user = user
AppStateContainer.shared.loggedState.connectedUser = true
WidgetCenter.shared.reloadAllTimelines()
self.initManagerVM(token: token)
}
if httpResponse.statusCode == 200, let user = try? JSONDecoder().decode(User.self, from: data) {
AppStateContainer.shared.user = user
AppStateContainer.shared.loggedState.connectedUser = true
WidgetCenter.shared.reloadAllTimelines()
self.initManagerVM(token: token)
} else {
AppStateContainer.shared.authenticationRefresh = nil
}
@ -137,13 +134,10 @@ class AuthService: IAuthService {
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data,
let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode == 200 {
if let userJson = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
let user = User.mapUser(from: userJson) {
completion(httpResponse.statusCode)
AppStateContainer.shared.user = user
WidgetCenter.shared.reloadAllTimelines()
}
if httpResponse.statusCode == 200, let user = try? JSONDecoder().decode(User.self, from: data) {
AppStateContainer.shared.user = user
WidgetCenter.shared.reloadAllTimelines()
completion(httpResponse.statusCode)
} else {
completion(httpResponse.statusCode)
}

@ -38,7 +38,7 @@ class CreationBetViewModel: ObservableObject {
resetAllFieldErrors()
if let user = AppStateContainer.shared.user {
manager.addBet(bet: toBet(theme: theme, description: description, endRegister: endRegisterDate, endBet: endBetDate, isPublic: isPublic, status: .inProgress, creator: user, type: selectedOption)) { statusCode in
manager.addBet(bet: toBet(theme: theme, description: description, endRegister: endRegisterDate, endBet: endBetDate, isPublic: isPublic, status: .inProgress, creator: user.username, type: selectedOption)) { statusCode in
switch statusCode {
case 201:
self.betAdded = true
@ -113,7 +113,7 @@ class CreationBetViewModel: ObservableObject {
self.errorMessage = errorMessage
}
func toBet(theme: String, description: String, endRegister: Date, endBet: Date, isPublic: Bool, status: BetStatus, creator: User, type: Int) -> Bet {
func toBet(theme: String, description: String, endRegister: Date, endBet: Date, isPublic: Bool, status: BetStatus, creator: String, type: Int) -> Bet {
switch type {
case 0:
return BinaryBet(theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPublic: isPublic, status: status, invited: [], author: creator, registered: [])

@ -54,6 +54,7 @@ struct BetEndingValidationView: View {
Text("Ce bet est arrivé à la date de fin. Vous devez à présent distribuer les gains en validant le pari gagnant.")
.textStyle(weight: .regular, color: AllInColors.grey800Color, size: 13)
.multilineTextAlignment(.center)
Text("Veuillez choisir la réponse finale:")
.font(.system(size: 17))
.foregroundStyle(.white)
@ -61,8 +62,9 @@ struct BetEndingValidationView: View {
.padding(.top, 30)
.padding(.bottom, 10)
.frame(maxWidth: .infinity, alignment: .leading)
VStack(spacing: 14){
ForEach(bet.answers, id: \.self) { answer in
ForEach(bet.answers) { answer in
ChoiceFinalAnswerCell(selected : answer.response == viewModel.selectedAnswer, answer: answer).onTapGesture {
if(viewModel.selectedAnswer == answer.response){
viewModel.selectedAnswer = nil

@ -66,7 +66,7 @@ struct DetailsView: View {
Text("proposé par")
.font(.system(size: 10))
.foregroundColor(AllInColors.grey800Color)
Text((viewModel.betDetail?.bet.author.username ?? "Unknown").capitalized)
Text((viewModel.betDetail?.bet.author ?? "Unknown").capitalized)
.font(.system(size: 10))
.fontWeight(.semibold)
.foregroundColor(AllInColors.primaryTextColor)
@ -122,8 +122,8 @@ struct DetailsView: View {
.fontWeight(.bold)
.padding(.bottom, 10)
ScrollView(showsIndicators: false) {
ForEach(viewModel.betDetail?.participations ?? []) { (participation: Participation) in
ParticiationCell(participation: participation).padding(.horizontal, 10)
ForEach(viewModel.betDetail?.participations ?? []) { participation in
ParticipationCell(participation: participation).padding(.horizontal, 10)
}
}
.padding(.bottom, geometry.safeAreaInsets.bottom + 28)

@ -18,7 +18,7 @@
1244EF622B4EC67000374ABF /* ReviewCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1244EF612B4EC67000374ABF /* ReviewCard.swift */; };
129D051D2B6E7FF0003D3E08 /* OddCapsule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 129D051C2B6E7FF0003D3E08 /* OddCapsule.swift */; };
12C370482B5A5EE500CD9F0F /* BetLineLoading.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C370472B5A5EE500CD9F0F /* BetLineLoading.swift */; };
12C3704A2B5D5BD000CD9F0F /* ParticiationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C370492B5D5BD000CD9F0F /* ParticiationCell.swift */; };
12C3704A2B5D5BD000CD9F0F /* ParticipationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12C370492B5D5BD000CD9F0F /* ParticipationCell.swift */; };
EC0193782B25BF16005D81E6 /* AllcoinsCapsule.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0193772B25BF16005D81E6 /* AllcoinsCapsule.swift */; };
EC01937A2B25C12B005D81E6 /* BetCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0193792B25C12B005D81E6 /* BetCard.swift */; };
EC01937C2B25C2A8005D81E6 /* AllcoinsCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC01937B2B25C2A8005D81E6 /* AllcoinsCounter.swift */; };
@ -154,7 +154,7 @@
1244EF612B4EC67000374ABF /* ReviewCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewCard.swift; sourceTree = "<group>"; };
129D051C2B6E7FF0003D3E08 /* OddCapsule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OddCapsule.swift; sourceTree = "<group>"; };
12C370472B5A5EE500CD9F0F /* BetLineLoading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BetLineLoading.swift; sourceTree = "<group>"; };
12C370492B5D5BD000CD9F0F /* ParticiationCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParticiationCell.swift; sourceTree = "<group>"; };
12C370492B5D5BD000CD9F0F /* ParticipationCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParticipationCell.swift; sourceTree = "<group>"; };
EC0193772B25BF16005D81E6 /* AllcoinsCapsule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllcoinsCapsule.swift; sourceTree = "<group>"; };
EC0193792B25C12B005D81E6 /* BetCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BetCard.swift; sourceTree = "<group>"; };
EC01937B2B25C2A8005D81E6 /* AllcoinsCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllcoinsCounter.swift; sourceTree = "<group>"; };
@ -420,7 +420,7 @@
120919172B56D0AE00D0FA29 /* ParticipationModal.swift */,
120919192B56DC6C00D0FA29 /* DropDownAnswerMenu.swift */,
12C370472B5A5EE500CD9F0F /* BetLineLoading.swift */,
12C370492B5D5BD000CD9F0F /* ParticiationCell.swift */,
12C370492B5D5BD000CD9F0F /* ParticipationCell.swift */,
123225DA2B67E41400D30BB3 /* ChoiceFinalAnswerCell.swift */,
129D051C2B6E7FF0003D3E08 /* OddCapsule.swift */,
);
@ -693,7 +693,7 @@
EC3077072B24CB840060E34D /* SplashView.swift in Sources */,
EC01937E2B25C52E005D81E6 /* TopBar.swift in Sources */,
ECA9D1CB2B2DA2320076E0EC /* DropDownFriends.swift in Sources */,
12C3704A2B5D5BD000CD9F0F /* ParticiationCell.swift in Sources */,
12C3704A2B5D5BD000CD9F0F /* ParticipationCell.swift in Sources */,
123590B82B5541BA00F7AEBD /* ParticipateButton.swift in Sources */,
EC01FCC32B56650400BB2390 /* DetailsViewModel.swift in Sources */,
ECB26A1B2B40746C00FE06B3 /* FriendsViewModel.swift in Sources */,

@ -31,63 +31,26 @@ public class FactoryApiBet: FactoryBet {
return json
}
public func fromJsonDateString(_ dateString: String) -> Date? {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
let date = formatter.date(from: dateString)
return date
}
public func toBet(from json: [String: Any]) -> Bet? {
guard let id = json["id"] as? String,
let theme = json["theme"] as? String,
let phrase = json["sentenceBet"] as? String,
let endRegisterDateString = json["endRegistration"] as? String,
let endBetDateString = json["endBet"] as? String,
let isPublic = json["isPrivate"] as? Bool,
let createdBy = json["createdBy"] as? String,
let type = json["type"] as? String,
let status = json["status"] as? String else {
guard let type = json["type"] as? String, let jsonData = try? JSONSerialization.data(withJSONObject: json, options: []) else {
return nil
}
guard let endRegisterDate = fromJsonDateString(endRegisterDateString),
let endBetDate = fromJsonDateString(endBetDateString) else {
let decoder = JSONDecoder()
do {
switch type {
case "BINARY":
return try decoder.decode(BinaryBet.self, from: jsonData)
case "MATCH":
return try decoder.decode(MatchBet.self, from: jsonData)
case "CUSTOM":
return try decoder.decode(CustomBet.self, from: jsonData)
default:
return try decoder.decode(BinaryBet.self, from: jsonData)
}
} catch {
print("Error decoding Bet object: \(error)")
return nil
}
return toBet(id: id, theme: theme, description: phrase, endRegister: endRegisterDate, endBet: endBetDate, isPublic: isPublic, status: toStatus(status: status), creator: User(username: createdBy, email: createdBy, nbCoins: 0, friends: []), type: type)
}
func toStatus(status: String) -> BetStatus {
switch status {
case "IN_PROGRESS":
return .inProgress
case "WAITING":
return .waiting
case "CLOSING":
return .closing
case "FINISHED":
return .finished
case "CANCELLED":
return .cancelled
default:
return .finished
}
}
public func toBet(id: String, theme: String, description: String, endRegister: Date, endBet: Date, isPublic: Bool, status: BetStatus, creator: User, type: String) -> Bet {
switch type {
case "BINARY":
return BinaryBet(id: id, theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPublic: isPublic, status: status, invited: [], author: creator, registered: [])
case "MATCH":
return MatchBet(id: id, theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPublic: isPublic, status: status, invited: [], author: creator, registered: [], nameTeam1: "", nameTeam2: "")
case "CUSTOM":
return CustomBet(id: id, theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPublic: isPublic, status: status, invited: [], author: creator, registered: [])
default:
return BinaryBet(id: id, theme: theme, phrase: description, endRegisterDate: endRegister, endBetDate: endBet, isPublic: isPublic, status: status, invited: [], author: creator, registered: [])
}
}
public func toBetDetail(from json: [String: Any]) -> BetDetail? {
@ -98,51 +61,27 @@ public class FactoryApiBet: FactoryBet {
var participations: [Participation] = []
if let participationsJson = json["participations"] as? [[String: Any]], !participationsJson.isEmpty {
for participationJson in participationsJson {
if let participation = self.toParticipate(from: participationJson) {
participations.append(participation)
}
if let participationsJson = json["participations"] as? [[String: Any]] {
do {
participations = try JSONDecoder().decode([Participation].self, from: JSONSerialization.data(withJSONObject: participationsJson))
} catch {
print("Error decoding participations: \(error)")
}
}
var answers: [AnswerDetail] = []
if let answersJson = json["answers"] as? [[String: Any]], !answersJson.isEmpty {
for answer in answersJson {
if let answer = self.toAnswer(from: answer) {
answers.append(answer)
}
if let answersJson = json["answers"] as? [[String: Any]] {
do {
answers = try JSONDecoder().decode([AnswerDetail].self, from: JSONSerialization.data(withJSONObject: answersJson))
} catch {
print("Error decoding answers: \(error)")
}
}
return BetDetail(bet: bet, answers: answers, participations: participations)
}
public func toParticipate(from json: [String: Any]) -> Participation? {
guard let id = json["id"] as? String,
let betId = json["betId"] as? String,
let username = json["username"] as? String,
let answer = json["answer"] as? String,
let stake = json["stake"] as? Int else {
return nil
}
return Participation(id: id, stake: stake, date: Date(), response: answer, user: User(username: username, email: "Email", nbCoins: 0, friends: []), betId: betId)
}
public func toAnswer(from json: [String: Any]) -> AnswerDetail? {
guard let response = json["response"] as? String,
let totalStakes = json["totalStakes"] as? Int,
let totalParticipants = json["totalParticipants"] as? Int,
let highestStake = json["highestStake"] as? Int,
let odds = json["odds"] as? Float else {
return nil
}
return AnswerDetail(response: response, totalStakes: totalStakes, totalParticipants: totalParticipants, highestStake: highestStake, odds: odds)
}
public func betTypeString(fromType type: String) -> String {
switch type {
case "BinaryBet":

@ -8,7 +8,7 @@
import Foundation
/// A class representing detailed information about a specific answer option for a bet.
public class AnswerDetail: ObservableObject, Hashable {
public class AnswerDetail: ObservableObject, Identifiable, Codable {
/// The response or outcome associated with this answer.
public private(set) var response: String
@ -41,16 +41,4 @@ public class AnswerDetail: ObservableObject, Hashable {
self.odds = odds
}
public func hash(into hasher: inout Hasher) {
// Use properties that define the uniqueness of the instance for hashing
hasher.combine(response)
// ... (combine other properties)
}
public static func == (lhs: AnswerDetail, rhs: AnswerDetail) -> Bool {
// Check equality based on properties
return lhs.response == rhs.response
// ... (check other properties)
}
}

@ -8,7 +8,7 @@
import Foundation
/// A class representing a betting entity, including details about the bet theme, participants, and deadlines.
public class Bet: ObservableObject, Identifiable {
public class Bet: ObservableObject, Identifiable, Codable {
/// The id for the bet.
public private(set) var id: String
@ -32,14 +32,41 @@ public class Bet: ObservableObject, Identifiable {
public private(set) var status: BetStatus
/// List of users who are invited to participate in the bet.
public private(set) var invited: [User]
public private(set) var invited: [User] = []
/// The user who created the bet.
public private(set) var author: User
public private(set) var author: String
/// List of users who have registered for the bet.
public private(set) var registered: [User]
public private(set) var registered: [User] = []
private enum CodingKeys: String, CodingKey {
case id
case theme
case phrase = "sentenceBet"
case endRegisterDate = "endRegistration"
case endBetDate = "endBet"
case isPublic = "isPrivate"
case status
case author = "createdBy"
}
public required init(from decoder: Decoder) throws {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(String.self, forKey: .id)
self.theme = try container.decode(String.self, forKey: .theme)
self.phrase = try container.decode(String.self, forKey: .phrase)
let endRegisterDateString = try container.decode(String.self, forKey: .endRegisterDate)
self.endRegisterDate = formatter.date(from: endRegisterDateString)!
let endBetDateString = try container.decode(String.self, forKey: .endBetDate)
self.endBetDate = formatter.date(from: endBetDateString)!
self.isPublic = try container.decode(Bool.self, forKey: .isPublic)
self.status = try container.decode(BetStatus.self, forKey: .status)
self.author = try container.decode(String.self, forKey: .author)
}
/// Custom Constructor
///
@ -54,7 +81,7 @@ public class Bet: ObservableObject, Identifiable {
/// - invited: List of users who are invited to participate in the bet.
/// - author: The user who created the bet.
/// - registered: List of users who have registered for the bet.
public init(id: String, theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPublic: Bool, status: BetStatus, invited: [User], author: User, registered: [User]) {
public init(id: String, theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPublic: Bool, status: BetStatus, invited: [User], author: String, registered: [User]) {
self.id = id
self.theme = theme
self.phrase = phrase
@ -79,7 +106,7 @@ public class Bet: ObservableObject, Identifiable {
/// - invited: List of users who are invited to participate in the bet.
/// - author: The user who created the bet.
/// - registered: List of users who have registered for the bet.
public init(theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPublic: Bool, status: BetStatus, invited: [User], author: User, registered: [User]) {
public init(theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPublic: Bool, status: BetStatus, invited: [User], author: String, registered: [User]) {
self.id = UUID().uuidString
self.theme = theme
self.phrase = phrase
@ -92,14 +119,4 @@ public class Bet: ObservableObject, Identifiable {
self.registered = registered
}
/// Adds a new user to the list of registered participants for the bet.
///
/// - Parameter newUser: The user to be added to the list of registered participants.
public func addRegistered(newUser: User){
self.registered.append(newUser)
}
public func isFinish() -> Bool{
self.endBetDate < Date()
}
}

@ -46,13 +46,7 @@ public class BetDetail: ObservableObject {
/// Adds a new user participation to the list of participations for the bet.
///
/// - Parameter newParticipation: The new user participation to be added.
public func addParticipation(newParticipation: Participation){
if !self.bet.registered.contains(where: { existingUser in
return existingUser.email == newParticipation.user.email
}) {
self.bet.addRegistered(newUser: newParticipation.user)
}
public func addParticipation(newParticipation: Participation) {
self.participations.append(newParticipation)
}
}

@ -7,6 +7,11 @@
import Foundation
public enum BetStatus {
case inProgress, waiting, closing, finished, cancelled
public enum BetStatus: String, Codable {
case inProgress = "IN_PROGRESS"
case waiting = "WAITING"
case closing = "CLOSING"
case finished = "FINISHED"
case cancelled = "CANCELLED"
}

@ -11,5 +11,4 @@ public protocol FactoryBet {
func toResponse(bet: Bet) -> [String: Any]
func toBet(from json: [String: Any]) -> Bet?
func toBetDetail(from json: [String: Any]) -> BetDetail?
func toBet(id: String, theme: String, description: String, endRegister: Date, endBet: Date, isPublic: Bool, status: BetStatus, creator: User, type: String) -> Bet
}

@ -15,6 +15,11 @@ public class MatchBet: Bet {
/// The name of the second team involved in the match.
public var nameTeam2: String
private enum CodingKeys: String, CodingKey {
case nameTeam1
case nameTeam2
}
/// Custom Constructor
///
/// - Parameters:
@ -30,7 +35,7 @@ public class MatchBet: Bet {
/// - registered: List of users who have registered for the match bet.
/// - nameTeam1: The name of the first team involved in the match.
/// - nameTeam2: The name of the second team involved in the match.
public init(id: String, theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPublic: Bool, status: BetStatus, invited: [User], author: User, registered: [User], nameTeam1: String, nameTeam2: String) {
public init(id: String, theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPublic: Bool, status: BetStatus, invited: [User], author: String, registered: [User], nameTeam1: String, nameTeam2: String) {
self.nameTeam1 = nameTeam1
self.nameTeam2 = nameTeam2
super.init(id: id, theme: theme, phrase: phrase, endRegisterDate: endRegisterDate, endBetDate: endBetDate, isPublic: isPublic, status: status, invited: invited, author: author, registered: registered)
@ -50,9 +55,24 @@ public class MatchBet: Bet {
/// - registered: List of users who have registered for the match bet.
/// - nameTeam1: The name of the first team involved in the match.
/// - nameTeam2: The name of the second team involved in the match.
public init(theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPublic: Bool, status: BetStatus, invited: [User], author: User, registered: [User], nameTeam1: String, nameTeam2: String) {
public init(theme: String, phrase: String, endRegisterDate: Date, endBetDate: Date, isPublic: Bool, status: BetStatus, invited: [User], author: String, registered: [User], nameTeam1: String, nameTeam2: String) {
self.nameTeam1 = nameTeam1
self.nameTeam2 = nameTeam2
super.init(theme: theme, phrase: phrase, endRegisterDate: endRegisterDate, endBetDate: endBetDate, isPublic: isPublic, status: status, invited: invited, author: author, registered: registered)
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.nameTeam1 = try container.decode(String.self, forKey: .nameTeam1)
self.nameTeam2 = try container.decode(String.self, forKey: .nameTeam2)
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(nameTeam1, forKey: .nameTeam1)
try container.encode(nameTeam2, forKey: .nameTeam2)
try super.encode(to: encoder)
}
}

@ -8,20 +8,18 @@
import Foundation
/// A class representing a user's participation in a bet.
public class Participation: ObservableObject, Identifiable {
public class Participation: ObservableObject, Codable, Identifiable {
public let id: String
/// The amount of stake in the bet.
public private(set) var stake: Int
/// The date and time when the participation occurred.
public private(set) var date: Date
/// The response or outcome of the participation.
public private(set) var response: String
public private(set) var answer: String
/// The user who participated in the bet.
public private(set) var user: User
public private(set) var username: String
/// The unique identifier of the bet.
public private(set) var betId: String
@ -34,12 +32,11 @@ public class Participation: ObservableObject, Identifiable {
/// - response: The response or outcome of the participation.
/// - user: The user who participated in the bet.
/// - betId: The unique identifier of the bet.
public init(id: String, stake: Int, date: Date, response: String, user: User, betId: String) {
public init(id: String, stake: Int, answer: String, username: String, betId: String) {
self.id = id
self.stake = stake
self.date = date
self.response = response
self.user = user
self.answer = answer
self.username = username
self.betId = betId
}
}

@ -8,7 +8,7 @@
import Foundation
/// A struct representing a user with details such as username, email, number of coins, and friends.
public struct User {
public struct User: Codable {
/// The username of the user.
public private(set) var username: String
@ -19,41 +19,15 @@ public struct User {
/// The number of coins associated with the user.
public var nbCoins: Int
/// List of friends associated with the user.
public private(set) var friends: [User]
/// Custom constructor to initialize a User instance.
///
/// - Parameters:
/// - username: The username of the user.
/// - email: The email address of the user.
/// - nbCoins: The number of coins associated with the user.
/// - friends: List of friends associated with the user.
public init(username: String, email: String, nbCoins: Int, friends: [User]) {
public init(username: String, email: String, nbCoins: Int) {
self.username = username
self.email = email
self.nbCoins = nbCoins
self.friends = friends
}
/// Adds a new friend to the list of friends for the user.
///
/// - Parameter user: The user to be added as a friend.
public mutating func addFriend(user: User) {
self.friends.append(user)
}
/// Maps user data from a JSON dictionary to create a User instance.
///
/// - Parameter json: The JSON dictionary containing user data.
/// - Returns: An optional User instance if mapping is successful, otherwise nil.
public static func mapUser(from json: [String: Any]) -> User? {
guard let username = json["username"] as? String,
let email = json["email"] as? String,
let nbCoins = json["nbCoins"] as? Int else {
return nil
}
return User(username: username, email: email, nbCoins: nbCoins, friends: [])
}
}

@ -21,16 +21,14 @@ struct Stub {
public mutating func loadBets() {
var user1 = User(username: "Lucas", email: "lucas.delanier@etu.uca.fr", nbCoins: 100, friends: [])
let user1 = User(username: "Lucas", email: "lucas.delanier@etu.uca.fr", nbCoins: 100)
users.append(user1)
var user2 = User(username: "Imri", email: "emre.kartal@etu.uca.fr", nbCoins: 75, friends: [user1])
let user2 = User(username: "Imri", email: "emre.kartal@etu.uca.fr", nbCoins: 75)
users.append(user2)
user1.addFriend(user: user2)
let user3 = User(username: "Arthur", email: "arthur.valin@etu.uca.fr", nbCoins: 30, friends: [user2])
let user3 = User(username: "Arthur", email: "arthur.valin@etu.uca.fr", nbCoins: 30)
users.append(user3)
user2.addFriend(user: user3)
let bet1 = BinaryBet(
theme: "Football - Finale de la Ligue des Champions",
@ -40,7 +38,7 @@ struct Stub {
isPublic: true,
status: .inProgress,
invited: [],
author: user1,
author: "Lucas",
registered: [user2]
)
self.bets.append(bet1)
@ -53,7 +51,7 @@ struct Stub {
isPublic: false,
status: .inProgress,
invited: [user3],
author: user1,
author: "Lucas",
registered: [user2]
)
self.bets.append(bet2)
@ -66,7 +64,7 @@ struct Stub {
isPublic: true,
status: .finished,
invited: [],
author: user1,
author: "Lucas",
registered: [user2, user1, user3]
)
self.bets.append(bet3)
@ -79,7 +77,7 @@ struct Stub {
isPublic: false,
status: .finished,
invited: [user1],
author: user2,
author: "Lucase",
registered: [user3]
)
self.bets.append(bet4)
@ -89,10 +87,10 @@ struct Stub {
self.betsDetail.append(betDetail)
}
self.betsDetail[0].addParticipation(newParticipation: Participation(id: UUID().uuidString, stake: 120, date: Date(), response: "OUI", user: user1, betId: "1"))
self.betsDetail[0].addParticipation(newParticipation: Participation(id: UUID().uuidString, stake: 20, date: Date(), response: "NON", user: user2, betId: "2"))
self.betsDetail[0].addParticipation(newParticipation: Participation(id: UUID().uuidString, stake: 320, date: Date(), response: "OUI", user: user3, betId: "3"))
self.betsDetail[0].addParticipation(newParticipation: Participation(id: UUID().uuidString, stake: 320, date: Date(), response: "OUI", user: user3, betId: "3"))
self.betsDetail[0].addParticipation(newParticipation: Participation(id: UUID().uuidString, stake: 120, answer: "OUI", username: user1.username, betId: "1"))
self.betsDetail[0].addParticipation(newParticipation: Participation(id: UUID().uuidString, stake: 20, answer: "NON", username: user2.username, betId: "2"))
self.betsDetail[0].addParticipation(newParticipation: Participation(id: UUID().uuidString, stake: 320, answer: "OUI", username: user3.username, betId: "3"))
self.betsDetail[0].addParticipation(newParticipation: Participation(id: UUID().uuidString, stake: 320, answer: "OUI", username: user3.username, betId: "3"))
}

Loading…
Cancel
Save