Skip to content

Instantly share code, notes, and snippets.

@allfinlir
Created October 16, 2023 04:41
Show Gist options
  • Save allfinlir/c0aa6b47c63a0a78fec51198091d8785 to your computer and use it in GitHub Desktop.
Save allfinlir/c0aa6b47c63a0a78fec51198091d8785 to your computer and use it in GitHub Desktop.
import Foundation
struct AddBettorDataModel: Identifiable {
var id = UUID()
var newBettor: String
}
import SwiftUI
struct AddBettorView: View {
@EnvironmentObject var betViewModel: BetViewModel
@State var addNewBettor: String
@Binding var presentAddBettorView: Bool
// @Binding var bettorArray: [String]
var body: some View {
VStack {
Text("Add new bettor")
TextField("Name", text: $addNewBettor)
Button(action: {
betViewModel.newBettorAdded(bettor: addNewBettor)
presentAddBettorView = false
}, label: {
Text("Add")
})
}
}
}
import SwiftUI
struct AddBetView: View {
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var betViewModel: BetViewModel
@AppStorage("savehometeam") var homeTeamData: String = "Home Team"
@AppStorage("saveawayteam") var awayTeamData: String = "Away Team"
@AppStorage("Rikard") var startNewBettorArray: String = ""
@State var chooseLeague: Leagues = .chooseleague
@State var homeTeam: String = ""
@State var awayTeam: String = ""
@State var selectDate = Date()
@State var typeOfBetInput: String = ""
@State var oddsOnBet: String = ""
@State var bettedAmount: String = ""
@State var bettorSelected: String = ""
@State var potentialWinnings: String = ""
@State var countBets: Int = 0
@State var descriptionInput: String = ""
@State var addNewBettor: String = ""
@State private var presentAddBettorView: Bool = false
var body: some View {
Form {
Group {
Section(header: Text("New bet")) {
Picker("League", selection: $chooseLeague) {
ForEach(Leagues.allCases, id: \.self) { league in
Text(league.localName)
}
}
Picker("Home team", selection: $homeTeam) {
ForEach(selectLeague(league: chooseLeague), id: \.self) { selectedHomeTeam in
Text(selectedHomeTeam)
}
}
.onChange(of: homeTeam) { _ in
homeTeamData = homeTeam
}
Picker("Away team", selection: $awayTeam) {
ForEach(selectLeague(league: chooseLeague), id: \.self) { selectedAwayTeam in
Text(selectedAwayTeam)
}
}
.onChange(of: awayTeam) { _ in
awayTeamData = awayTeam
}
DatePicker("Game starts", selection: $selectDate, displayedComponents: [.date, .hourAndMinute])
.datePickerStyle(.compact)
TextField("Type of bet: 1X2, O/U, DC, HT/FT....", text: $typeOfBetInput)
// .keyboardType(.decimalPad) // not needed because not only numbers here to be inputed
TextField("Odds?", text: $oddsOnBet)
.keyboardType(.decimalPad)
TextField("Amount/Units on bet..", text: $bettedAmount)
.keyboardType(.decimalPad)
HStack {
Picker("Bettor", selection: $addNewBettor) {
ForEach(betViewModel.newBettors) { bettor in
NewBettorView(bettor: bettor)
}
}
HStack {
Text("")
}
.contentShape(Rectangle())
.padding(.leading, 16)
.overlay {
HStack {
// Spacer()
Button(action: {
presentAddBettorView = true
}, label: {
Image(systemName: "plus.circle")
.foregroundStyle(.blue)
})
.buttonStyle(PlainButtonStyle())
}
}
.layoutPriority(1)
}
}
Section(header: Text("Motivate bet: ")) {
TextEditor(text: $descriptionInput)
.frame(height: 200)
Button(action: {
pressSaveButton()
}, label: {
Text("Save bet")
.foregroundColor(.green)
})
}
}
}
.sheet(isPresented: $presentAddBettorView, content: {
AddBettorView(addNewBettor: addNewBettor, presentAddBettorView: $presentAddBettorView)
})
}
var oddsOnBetReplaceComma: String {
oddsOnBet.replacingOccurrences(of: ",", with: ".")
}
var bettedAmountReplaceComma: String {
bettedAmount.replacingOccurrences(of: ",", with: ".")
}
func pressSaveButton() {
betViewModel.addBet(league: chooseLeague.rawValue, homeTeam: homeTeam, awayTeam: awayTeam, dateForBet: selectDate, typeOfBet: typeOfBetInput, odds: Double(oddsOnBetReplaceComma) ?? 0.0, betAmount: Double(bettedAmountReplaceComma) ?? 0.0, bettor: [addNewBettor], potentialWin: Double(potentialWinnings) ?? 0.0, betCount: countBets, description: descriptionInput)
// betViewModel.newBettorAdded(bettor: addNewBettor)
presentationMode.wrappedValue.dismiss()
}
}
import Foundation
import SwiftUI
struct BetModel: Identifiable, Codable { // Identifiable so we have id on each item and codable so it can handle JSON data
let id: String
var league: String
let homeTeam: String
let awayTeam: String
var dateForBet: Date
let typeOfBet: String
let odds: Double
let betAmount: Double
var bettor: [String]
var potentialWin: Double
var winBet: Bool
var looseBet: Bool
var pushBet: Bool
var betCount: Int
let description: String
init(id: String = UUID().uuidString, league: String, homeTeam: String, awayTeam: String, dateForBEt: Date, typeOfBet: String, odds: Double, betAmount: Double, bettor: [String], potentialWin: Double, winBet: Bool, looseBet: Bool, pushBet: Bool, betCount: Int, description: String) {
self.id = id
self.league = league
self.homeTeam = homeTeam
self.awayTeam = awayTeam
self.dateForBet = dateForBEt
self.typeOfBet = typeOfBet
self.odds = odds
self.betAmount = betAmount
self.bettor = bettor
self.potentialWin = potentialWin
self.winBet = winBet
self.looseBet = looseBet
self.pushBet = pushBet
self.betCount = betCount
self.description = description
}
func updateWinCompletion() -> BetModel {
return BetModel(id: id, league: league, homeTeam: homeTeam, awayTeam: awayTeam, dateForBEt: dateForBet, typeOfBet: typeOfBet, odds: odds, betAmount: betAmount, bettor: bettor, potentialWin: winBet ? 0.0 : (odds * betAmount) - betAmount, winBet: !winBet, looseBet: looseBet, pushBet: pushBet, betCount: betCount, description: description)
}
func updateLostCompletion() -> BetModel {
return BetModel(id: id, league: league, homeTeam: homeTeam, awayTeam: awayTeam, dateForBEt: dateForBet, typeOfBet: typeOfBet, odds: odds, betAmount: betAmount, bettor: bettor, potentialWin: looseBet ? 0.0 : -betAmount, winBet: winBet, looseBet: !looseBet, pushBet: pushBet, betCount: betCount, description: description)
}
func updatePushCompletion() -> BetModel {
return BetModel(id: id, league: league, homeTeam: homeTeam, awayTeam: awayTeam, dateForBEt: dateForBet, typeOfBet: typeOfBet, odds: odds, betAmount: betAmount, bettor: bettor, potentialWin: 0.0, winBet: winBet, looseBet: looseBet, pushBet: !pushBet, betCount: betCount, description: description)
}
}
import Foundation
class BetViewModel: ObservableObject {
@Published var betItems: [BetModel] = []
@Published var newBettors: [AddBettorDataModel] = []
init() {
getBets() // fetches my data from getBets() function
}
public var totalWinningsLosses: Double {
return betItems.reduce(0) { sum, betResults in
sum + betResults.potentialWin
}
}
func newBettorAdded(bettor: String) {
let newBettor = AddBettorDataModel(newBettor: bettor)
newBettors.insert(newBettor, at: 0)
// saveBet()
}
func makeChartData(from bets: [BetModel]) -> [BetDataPoint] {
let sortedBets = betItems.sorted { $0.dateForBet < $1.dateForBet }
var currentTotal = 0.0
let dataPoints = sortedBets.map { bet in
currentTotal += bet.potentialWin
return BetDataPoint(date: bet.dateForBet, total: currentTotal, league: bet.league)
}
return dataPoints
}
func chartDataPerWeek(from bets: [BetModel]) -> [BetDataPointPerWeek] {
let lastWeek = Calendar.current.date(byAdding: .day, value: -7, to: Date()) ?? Date()
let sortedBetsLastWeek = betItems.filter { $0.dateForBet >= lastWeek }.sorted(by: { $0.dateForBet < $1.dateForBet })
// let sortedBetsLastWeek = betItems.sorted { $0.dateForBet < $1.dateForBet }
var currentWeekTotal = 0.0
let weekDataPoints = sortedBetsLastWeek.map { weekBets in
currentWeekTotal += weekBets.potentialWin
return BetDataPointPerWeek(date: weekBets.dateForBet, totalLastWeek: currentWeekTotal)
}
return weekDataPoints
}
let betItemKey: String = "Bets"
func getBets() {
guard let data = UserDefaults.standard.data(forKey: betItemKey),
let savedBetItems = try? JSONDecoder().decode([BetModel].self, from: data)
else { return }
self.betItems = savedBetItems.sorted(by: { $0.dateForBet > $1.dateForBet }) // this will sort all bets in the array by date.
}
// MARK: Sorts all bets by date in the WinChart View
func sortListofBetsByDate() -> [BetModel] {
betItems.sorted(by: { $0.dateForBet > $1.dateForBet })
}
// MARK: sorts the bets to only the latest 7 days bet results
func resultsLastWeek() -> [BetModel] {
let lastWeek = Calendar.current.date(byAdding: .day, value: -7, to: Date()) ?? Date()
return betItems.filter { $0.dateForBet >= lastWeek }.sorted(by: { $0.dateForBet < $1.dateForBet})
}
// MARK: So you can delete bets from the list
func deleteBet(indexSet: IndexSet) {
betItems.remove(atOffsets: indexSet)
saveBet()
}
// MARK: So you can move items in the bet list
func moveBet(from: IndexSet, to: Int) {
betItems.move(fromOffsets: from, toOffset: to)
}
// MARK: Counts all winning bets
func winningBets() -> Int {
betItems.filter { $0.winBet == true }.count
}
// MARK: Counts all loosing bets.
func loosingBets() -> Int {
betItems.filter { $0.looseBet == true }.count
}
// MARK: counts all bet that are push bets
func pushBets() -> Int {
betItems.filter { $0.pushBet == true }.count
}
// MARK: calculates all bets that have not been decided yet, those that are ongoing
func ongoingBets() -> Int {
betItems.filter { $0.winBet == false && $0.looseBet == false && $0.pushBet == false }.count
}
// func addBettor() -> [String] {
//}
// MARK: So you can add a bet in the bet view, save saveBet() is there so the list is saved when app is closed by user.
func addBet(league: String, homeTeam: String, awayTeam: String, dateForBet: Date, typeOfBet: String, odds: Double, betAmount: Double, bettor: [String], potentialWin: Double, betCount: Int, description: String) {
let newBet = BetModel(league: league, homeTeam: homeTeam, awayTeam: awayTeam, dateForBEt: dateForBet, typeOfBet: typeOfBet, odds: odds, betAmount: betAmount, bettor: bettor, potentialWin: potentialWin, winBet: false, looseBet: false, pushBet: false, betCount: betCount, description: description)
// betItems.append(newBet)
betItems.insert(newBet, at: 0) // use this instead if you want your bet to append at the top of your list
saveBet()
}
// MARK: Updates the bet row view and toggles the winbet boolean from false to true.
func updateWinBet(bet: BetModel) {
if let betWinIndex = betItems.firstIndex(where: {$0.id == bet.id }) {
betItems[betWinIndex] = bet.updateWinCompletion() // updateWinCompletion sätter vi ju in vår BetModel
}
}
// MARK: Updates the bet row view and toggles the loosebet boolean from false to true.
func updateLooseBet(bet: BetModel) {
if let betLooseIndex = betItems.firstIndex(where: {$0.id == bet.id }) {
betItems[betLooseIndex] = bet.updateLostCompletion() // updateLostCompletion sätter vi ju in vår BetModel
}
}
// MARK: Updates the bet row view and toggles the pushbet boolean from false to true.
func updatePushBet(bet: BetModel) {
if let betPushIndex = betItems.firstIndex(where: {$0.id == bet.id}) {
betItems[betPushIndex] = bet.updatePushCompletion()
}
}
// MARK: So data get saved once the app is closed by the user,
func saveBet() {
if let encodedBetData = try? JSONEncoder().encode(betItems) {
UserDefaults.standard.set(encodedBetData, forKey: betItemKey)
getBets() // by adding the function here, all new items in the array will be sorted on date as well.
} else {
print("Couldn't save bet")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment