Skip to content

Instantly share code, notes, and snippets.

@allfinlir
Created January 2, 2025 18:30
Show Gist options
  • Save allfinlir/4034d953c0613803a0c2f04f6c8e8fe8 to your computer and use it in GitHub Desktop.
Save allfinlir/4034d953c0613803a0c2f04f6c8e8fe8 to your computer and use it in GitHub Desktop.
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