Skip to content

Instantly share code, notes, and snippets.

@allfinlir
Last active October 10, 2023 21:07
Show Gist options
  • Save allfinlir/525e54599210192c1be571aba3f180aa to your computer and use it in GitHub Desktop.
Save allfinlir/525e54599210192c1be571aba3f180aa to your computer and use it in GitHub Desktop.
import Foundation
struct BetDataPoint: Identifiable {
var id = UUID()
let date: Date
let total: Double
let league: String
}
struct BetDataPointPerWeek: Identifiable {
var id = UUID()
let date: Date
let totalLastWeek: Double
}
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 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, 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.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, 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, 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, potentialWin: 0.0, winBet: winBet, looseBet: looseBet, pushBet: !pushBet, betCount: betCount, description: description)
}
}
import Foundation
class BetViewModel: ObservableObject {
@Published var betItems: [BetModel] = []
init() {
getBets() // fetches my dat from getBets() function
}
public var totalWinningsLosses: Double {
return betItems.reduce(0) { sum, betResults in
sum + betResults.potentialWin
}
}
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
}
// 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
}
// 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, potentialWin: Double, betCount: Int, description: String) {
let newBet = BetModel(league: league, homeTeam: homeTeam, awayTeam: awayTeam, dateForBEt: dateForBet, typeOfBet: typeOfBet, odds: odds, betAmount: betAmount, 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)
} else {
print("Couldn't save bet")
}
}
}
Then presented in a tabview like this.
@EnvironmentObject var betViewModel: BetViewModel
TabView {
WinChart(resultData: betViewModel.sortListofBetsByDate())
WinChartByWeek(resultData: betViewModel.resultsLastWeek())
}
.frame(height: 250)
.tabViewStyle(.page(indexDisplayMode: .never))
import SwiftUI
import Charts
struct WinChart: View {
@EnvironmentObject var betCharts: BetViewModel
let resultData: [BetModel]
var body: some View {
VStack {
GroupBox("3 Month Results") {
Chart(betCharts.makeChartData(from: resultData)) { result in
LineMark(x: .value("Day", result.date), y: .value("Result", result.total))
.interpolationMethod(.catmullRom)
.lineStyle(StrokeStyle(lineWidth: 2, dash: [5, 10]))
// .foregroundStyle(by: .value("League", result.league))
}
}
.groupBoxStyle(YellowGroupBoxStyle())
/* Chart(betCharts.makeChartData(from: resultData)) { result in
LineMark(x: .value("Day", result.date), y: .value("Result", result.total))
.foregroundStyle(by: .value("League", result.league))
}
.chartLegend(position: .leading, alignment: .top, spacing: 10) */
}
}
}
//struct WinChart_Previews: PreviewProvider {
// static var previews: some View {
// WinChart()
// }
//}
struct YellowGroupBoxStyle: GroupBoxStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.content
.padding(.top, 30)
.padding(20)
.background(Color(hue: 0.10, saturation: 0.10, brightness: 0.98))
.cornerRadius(20)
.overlay(
configuration.label.padding(10),
alignment: .topLeading
)
}
}
import SwiftUI
import Charts
struct WinChartByWeek: View {
@EnvironmentObject var betCharts: BetViewModel
let resultData: [BetModel]
var body: some View {
VStack {
Chart(betCharts.chartDataPerWeek(from: resultData)) { result in
LineMark(x: .value("Day", result.date), y: .value("Result", result.totalLastWeek))
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment