Created
January 2, 2025 18:30
-
-
Save allfinlir/4034d953c0613803a0c2f04f6c8e8fe8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
struct InsightsView: View { | |
@Environment(\.managedObjectContext) private var viewContext | |
@FetchRequest(entity: AddBetEntity.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \AddBetEntity.dateForBet, ascending: false)], animation: .default) | |
private var bets: FetchedResults<AddBetEntity> | |
var bettingData: [InsightsBettingData] { | |
[ | |
InsightsBettingData(number: totalWinBets(), text: "Wins"), | |
InsightsBettingData(number: totalLoseBets(), text: "Losses"), | |
InsightsBettingData(number: highestWinBet(), text: "Highest Win"), | |
InsightsBettingData(number: biggestLoss(), text: "Worst Loss") | |
] | |
} | |
var averagesData: [InsightsAveragesBetData] { | |
[ | |
InsightsAveragesBetData(number: averageOddsonBets(), text: "Average Odds"), | |
InsightsAveragesBetData(number: averageWageronBets(), text: "Average Wager"), | |
InsightsAveragesBetData(number: averageOddsonWinnings(), text: "Average Odds Winnings"), | |
InsightsAveragesBetData(number: averageWageronWinnings(), text: "Average Wager Winnings"), | |
InsightsAveragesBetData(number: averageOddsonLosses(), text: "Average Odds Losses"), | |
InsightsAveragesBetData(number: averageWageronLosses(), text: "Average Wager Losses") | |
] | |
} | |
var winRateData: [InsightsWinRateBetData] { | |
[ | |
InsightsWinRateBetData(number: winRateLowOdds(), text: "Odds <= 1.60"), | |
InsightsWinRateBetData(number: winRateMediumLowOdds(), text: "Odds 1.61-2.15"), | |
InsightsWinRateBetData(number: winRateMediumHighOdds(), text: "Odds 2.16-2.85"), | |
InsightsWinRateBetData(number: winRateHighOdds(), text: "Odds >= 2.86") | |
] | |
} | |
var streakData: [InsightsStreaksBetData] { | |
[ | |
InsightsStreaksBetData(number: winsInRow(), text: "Wins in a row"), | |
InsightsStreaksBetData(number: lossesInRow(), text: "Losses in a row") | |
] | |
} | |
let bettingColumns = [ GridItem(.flexible()), GridItem(.flexible()) ] | |
var body: some View { | |
ScrollView { | |
VStack(alignment: .leading) { | |
Text("Bets") | |
.bold() | |
.font(.title3) | |
.padding(.top) | |
LazyVGrid(columns: bettingColumns, spacing: 10) { | |
ForEach(bettingData) { betData in | |
HStack { | |
VStack(alignment: .leading) { | |
Text(betData.text) | |
.font(.caption2) | |
Spacer() | |
Text("\(betData.number, specifier: "%.0f")") | |
.font(.title3) | |
.fontWeight(.semibold) | |
} | |
.padding() | |
Spacer() | |
} | |
.frame(height: 85) | |
.frame(maxWidth: .infinity) | |
.background( | |
ZStack { | |
Color.gray | |
.cornerRadius(10) | |
.opacity(0.1) | |
RoundedRectangle(cornerRadius: 10) | |
.stroke(style: StrokeStyle(lineWidth: 1)) | |
} | |
) | |
} | |
} | |
Text("Averages") | |
.bold() | |
.font(.title3) | |
.padding(.top) | |
LazyVGrid(columns: bettingColumns, spacing: 10) { | |
ForEach(averagesData) { data in | |
HStack { | |
VStack(alignment: .leading) { | |
Text(data.text) | |
.font(.caption2) | |
Spacer() | |
Text("\(data.number, specifier: "%.0f")") | |
.font(.title3) | |
.fontWeight(.semibold) | |
} | |
.padding() | |
Spacer() | |
} | |
.frame(height: 85) | |
.frame(maxWidth: .infinity) | |
.background( | |
ZStack { | |
Color.gray | |
.cornerRadius(10) | |
.opacity(0.1) | |
RoundedRectangle(cornerRadius: 10) | |
.stroke(style: StrokeStyle(lineWidth: 1)) | |
} | |
) | |
} | |
} | |
Text("Win Rate") | |
.bold() | |
.font(.title3) | |
.padding(.top) | |
LazyVGrid(columns: bettingColumns, spacing: 10) { | |
ForEach(winRateData) { data in | |
HStack { | |
VStack(alignment: .leading) { | |
Text(data.text) | |
.font(.caption2) | |
Spacer() | |
Text("\(data.number, specifier: "%.0f")%") | |
.font(.title3) | |
.fontWeight(.semibold) | |
} | |
.padding() | |
Spacer() | |
} | |
.frame(height: 85) | |
.frame(maxWidth: .infinity) | |
.background( | |
ZStack { | |
Color.gray | |
.cornerRadius(10) | |
.opacity(0.1) | |
RoundedRectangle(cornerRadius: 10) | |
.stroke(style: StrokeStyle(lineWidth: 1)) | |
} | |
) | |
} | |
} | |
Text("Streaks") | |
.bold() | |
.font(.title3) | |
.padding(.top) | |
LazyVGrid(columns: bettingColumns, spacing: 10) { | |
ForEach(streakData) { data in | |
HStack { | |
VStack(alignment: .leading) { | |
Text(data.text) | |
.font(.caption2) | |
Spacer() | |
Text("\(data.number)%") | |
.font(.title3) | |
.fontWeight(.semibold) | |
} | |
.padding() | |
Spacer() | |
} | |
.frame(height: 85) | |
.frame(maxWidth: .infinity) | |
.background( | |
ZStack { | |
Color.gray | |
.cornerRadius(10) | |
.opacity(0.1) | |
RoundedRectangle(cornerRadius: 10) | |
.stroke(style: StrokeStyle(lineWidth: 1)) | |
} | |
) | |
} | |
} | |
} | |
.padding() | |
} | |
} | |
func totalWinBets() -> Double { | |
let totalWinBets = bets.filter { $0.winBet == true }.count | |
return Double(totalWinBets) | |
} | |
func totalLoseBets() -> Double { | |
let totalLoseBets = bets.filter { $0.looseBet == true }.count | |
return Double(totalLoseBets) | |
} | |
func highestWinBet() -> Double { | |
let highestWin = bets.compactMap { bet in | |
Double(bet.potentialWin) | |
} | |
return highestWin.max() ?? 0.0 | |
} | |
func biggestLoss() -> Double { | |
let biggestLoss = bets.compactMap { bet in | |
Double(bet.potentialWin) | |
} | |
return biggestLoss.min() ?? 0.0 | |
} | |
func averageOddsonBets() -> Double { | |
let totalOdds = bets.reduce(0) { sum, odds in | |
sum + odds.odds | |
} | |
let averageOddsonAllBets = totalOdds / Double(bets.count) | |
return averageOddsonAllBets | |
} | |
func averageOddsonWinnings() -> Double { | |
let winBetsCount = bets.filter { $0.winBet } | |
let totalOdds = winBetsCount.reduce(0) { $0 + $1.odds } | |
return winBetsCount.isEmpty ? 0 : totalOdds / Double(winBetsCount.count) | |
} | |
func averageOddsonLosses() -> Double { | |
let looseBetsCount = bets.filter { $0.looseBet } | |
let totalOdds = looseBetsCount.reduce(0) { $0 + $1.odds } | |
return looseBetsCount.isEmpty ? 0 : totalOdds / Double(looseBetsCount.count) | |
} | |
func averageWageronBets() -> Double { | |
let totalWager = bets.reduce(0) { sum, odds in | |
sum + odds.betAmount | |
} | |
let averageWageronAllBets = totalWager / Double(bets.count) | |
return averageWageronAllBets | |
} | |
func averageWageronWinnings() -> Double { | |
let winBetsCount = bets.filter { $0.winBet } | |
let totalWager = winBetsCount.reduce(0) { $0 + $1.betAmount } | |
return winBetsCount.isEmpty ? 0 : totalWager / Double(winBetsCount.count) | |
} | |
func averageWageronLosses() -> Double { | |
let lossBetsCount = bets.filter { $0.looseBet } | |
let totalWager = lossBetsCount.reduce(0) { $0 + $1.betAmount } | |
return lossBetsCount.isEmpty ? 0 : totalWager / Double(lossBetsCount.count) | |
} | |
func winRateLowOdds() -> Double { | |
let lowOddsBets = bets.filter { $0.odds <= 1.60 }.count | |
let winningLowOddsBet = bets.filter { $0.odds <= 1.75 && $0.winBet == true}.count | |
let winRate = Double(winningLowOddsBet) / Double(lowOddsBets) | |
if winningLowOddsBet == 0 { | |
return 0.0 | |
} else { | |
return winRate * 100.0 | |
} | |
} | |
func winRateMediumLowOdds() -> Double { | |
let mediumOddsBets = bets.filter { $0.odds > 1.60 && $0.odds <= 2.15 }.count | |
let winningMediumOddsBet = bets.filter { $0.odds > 1.60 && $0.odds <= 2.15 && $0.winBet == true}.count | |
let winRate = Double(winningMediumOddsBet) / Double(mediumOddsBets) | |
if winningMediumOddsBet == 0 { | |
return 0.0 | |
} else { | |
return winRate * 100.0 | |
} | |
} | |
func winRateMediumHighOdds() -> Double { | |
let mediumOddsBets = bets.filter { $0.odds > 2.15 && $0.odds <= 2.85 }.count | |
let winningMediumOddsBet = bets.filter { $0.odds > 2.15 && $0.odds <= 2.85 && $0.winBet == true}.count | |
let winRate = Double(winningMediumOddsBet) / Double(mediumOddsBets) | |
if winningMediumOddsBet == 0 { | |
return 0.0 | |
} else { | |
return winRate * 100.0 | |
} | |
} | |
func winRateHighOdds() -> Double { | |
let highOddsBets = bets.filter { $0.odds > 2.85 }.count | |
let winningHighOddsBet = bets.filter { $0.odds > 2.85 && $0.winBet == true}.count | |
let winRate = Double(winningHighOddsBet) / Double(highOddsBets) | |
if winningHighOddsBet == 0 { | |
return 0.0 | |
} else { | |
return winRate * 100.0 | |
} | |
} | |
func winsInRow() -> Int { | |
var winsInRow = 0 | |
var maxWin = 0 | |
for bet in bets { | |
if bet.winBet { | |
winsInRow += 1 | |
maxWin = max(maxWin, winsInRow) | |
} else { | |
winsInRow = 0 | |
} | |
} | |
return maxWin | |
} | |
func lossesInRow() -> Int { | |
var lossesInRow = 0 | |
var maxLoss = 0 | |
for bet in bets { | |
if bet.looseBet { | |
lossesInRow += 1 | |
maxLoss = max(maxLoss, lossesInRow) | |
} else { | |
lossesInRow = 0 | |
} | |
} | |
return maxLoss | |
} | |
} | |
struct InsightsBettingData: Identifiable,Equatable { | |
let id = UUID() | |
let number: Double | |
let text: String | |
} | |
struct InsightsAveragesBetData: Identifiable,Equatable { | |
let id = UUID() | |
let number: Double | |
let text: String | |
} | |
struct InsightsWinRateBetData: Identifiable,Equatable { | |
let id = UUID() | |
let number: Double | |
let text: String | |
} | |
struct InsightsStreaksBetData: Identifiable, Equatable { | |
let id = UUID() | |
let number: Int | |
let text: String | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment