An amazing project that generates micro reports from tournament results
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

357 lines
12 KiB

//
// Queries.swift
// TournamentStats
//
// Created by Laurent Morvillier on 03/06/2019.
// Copyright © 2019 Stax River. All rights reserved.
//
import Foundation
import RealmSwift
import Realm
class Queries {
static func festivalStats(realm: Realm) -> FestivalStats {
let tournaments = realm.objects(Tournament.self)
let stats = FestivalStats()
stats.cumulatedBuyins = tournaments.sum(ofProperty: "buyin")
stats.totalEntries = tournaments.sum(ofProperty: "entries")
stats.totalPrizePool = tournaments.sum(ofProperty: "prizepool")
stats.eventsCount = tournaments.count
return stats
}
static func biggestWinners(realm: Realm) -> [CumulatedResults] {
let players = realm.objects(Player.self)
var crArray: [CumulatedResults] = []
for player in players {
crArray.append(CumulatedResults(player: player))
}
return crArray.sorted(by: { (cr1, cr2) -> Bool in
return cr1.total > cr2.total
})
}
static func averageCash(realm: Realm, minCount: Int) -> [CumulatedResults] {
let players = realm.objects(Player.self).filter(NSPredicate(format: "results.@count >= %i", minCount))
var crArray: [CumulatedResults] = []
for player in players {
crArray.append(CumulatedResults(player: player, options: [.average]))
}
return crArray.sorted(by: { (cr1, cr2) -> Bool in
return cr1.total > cr2.total
})
}
static func mostCashes(realm: Realm, notable: Bool = false) -> [CumulatedResults] {
var players = realm.objects(Player.self)
if (notable) {
players = players.filter("notable = true")
}
var crArray: [CumulatedResults] = []
for player in players {
crArray.append(CumulatedResults(player: player, options: [.countSorted]))
}
return crArray.sorted(by: { (cr1, cr2) -> Bool in
if cr1.numberOfCashes == cr2.numberOfCashes {
return cr1.total > cr2.total
}
return cr1.numberOfCashes > cr2.numberOfCashes
})
}
static func mostWins(realm: Realm) -> [CumulatedWins] {
var crArray: [CumulatedWins] = []
for player in realm.objects(Player.self) {
crArray.append(CumulatedWins(player: player))
}
crArray = crArray.filter { $0.winsCount > 0 }
return crArray.sorted(by: { (cr1, cr2) -> Bool in
if cr1.winsCount == cr2.winsCount {
return cr1.numberOfCashes > cr2.numberOfCashes
}
return cr1.winsCount > cr2.winsCount
})
}
static func allWinnersSortedByEvent(realm: Realm, date: Date? = nil) -> [TournamentWinner] {
let winners: Results<Result>
if let day = date {
winners = realm.objects(Result.self).filter("rank == 1 && ANY tournaments.date IN %@", [day])
} else {
winners = realm.objects(Result.self).filter("rank == 1")
}
var tws: [TournamentWinner] = []
for w in winners {
let tw = TournamentWinner(tournament: w.tournaments.first!, result: w)
tws.append(tw)
}
tws.sort { (tw1, tw2) -> Bool in
tw1.tournament.number < tw2.tournament.number
}
return tws
}
static func notableCashes(realm: Realm, date: Date) -> [PlayerResult] {
let notableCashes: Results<Result> = realm.objects(Result.self).filter("player.notable = true && ANY tournaments.date IN %@", [date])
var prs: [PlayerResult] = []
for nc in notableCashes {
let pr = PlayerResult(tournament: nc.tournaments.first!, result: nc)
prs.append(pr)
}
prs.sort { (pr1, pr2) -> Bool in
if pr1.result.rank == pr2.result.rank {
return pr1.result.earnings > pr2.result.earnings
}
return pr1.result.rank < pr2.result.rank
}
return prs
}
static func sortedEvents(realm: Realm, fieldName: String, ascending: Bool) -> [TournamentRepresentable] {
let tournies = realm.objects(Tournament.self).sorted(byKeyPath: fieldName, ascending: ascending)
var trs: [TournamentRepresentable] = []
for tourny in tournies {
trs.append(TournamentRepresentable(tournament: tourny))
}
return trs
}
static func cashesByCountry(realm: Realm) -> [CountryCounter] {
let playerDistinctCountries = realm.objects(Player.self).distinct(by: ["country"])
var countryCashes: [CountryCounter] = []
for player in playerDistinctCountries {
let country = player.country
let resultsByCountry = realm.objects(Result.self).filter("player.country == %@", country)
let cc = CountryCounter(country: country, counter: resultsByCountry.count)
countryCashes.append(cc)
}
countryCashes.sort { (cc1, cc2) -> Bool in
return cc1.counter > cc2.counter
}
return countryCashes
}
static func winsByCountry(realm: Realm) -> [CountryCounter] {
let winners: Results<Result> = realm.objects(Result.self).filter("rank == 1")
var countryWins: [String : CountryCounter] = [:]
for winner in winners {
if let country = winner.player?.country {
if let cc = countryWins[country] {
cc.increment()
} else {
countryWins[country] = CountryCounter(country: country, counter: 1)
}
}
}
var sortedCountries = countryWins.values.map { $0 }
sortedCountries.sort { (cc1, cc2) -> Bool in
return cc1.counter > cc2.counter
}
return sortedCountries
}
static func averageEvent(realm: Realm) -> [TournamentStats] {
let tournaments: Results<Tournament> = realm.objects(Tournament.self)
let entries: Double? = tournaments.average(ofProperty: "entries")
let buyin: Double? = tournaments.average(ofProperty: "buyin")
let prizepool: Double? = tournaments.average(ofProperty: "prizepool")
let winnerResults = tournaments.compactMap { (tournament) -> Result? in
return tournament.results.first { $0.rank == 1 }
}
let averageFirstPrize = winnerResults.reduce(0.0) { $0 + Double($1.earnings) } / Double(tournaments.count)
if let entries = entries, let buyin = buyin, let prizepool = prizepool {
let ts = TournamentStats(entries: entries, buyin: buyin, prizepool: prizepool, firstPrize: averageFirstPrize)
return [ts]
}
return []
}
static func tournamentBuyinDistribution(realm: Realm) -> [DistributionCounter] {
let tournaments: Results<Tournament> = realm.objects(Tournament.self)
let verylow = DistributionCounter(name: "<$1,000")
let low = DistributionCounter(name: "$1,000 - $1,999")
let medium = DistributionCounter(name: "$2,000 - $5,000")
let high = DistributionCounter(name: ">$5,000")
let counters: [DistributionCounter] = [verylow, low, medium, high]
tournaments.forEach { tournament in
switch tournament.buyin {
case 0..<1000:
verylow.increment()
case 1000..<2000:
low.increment()
case 2000...5000:
medium.increment()
default:
high.increment()
}
}
return counters
}
static func tournamentPrizepoolDistribution(realm: Realm) -> [DistributionCounter] {
let tournaments: Results<Tournament> = realm.objects(Tournament.self)
let low = DistributionCounter(name: "<$1M)")
let medium = DistributionCounter(name: "$1M - $5M")
let high = DistributionCounter(name: ">5M")
let counters: [DistributionCounter] = [low, medium, high]
tournaments.forEach { tournament in
switch tournament.prizepool {
case 0.0..<1000000.0:
low.increment()
case 1000000.0...5000000.0:
medium.increment()
default:
high.increment()
}
}
return counters
}
static func firstPrizeDistribution(realm: Realm) -> [DistributionCounter] {
let winnerResults = realm.objects(Result.self).filter("rank == 1")
let low = DistributionCounter(name: "<$250K")
let medium = DistributionCounter(name: "$250K - $1M")
let high = DistributionCounter(name: ">$1M")
let counters: [DistributionCounter] = [low, medium, high]
winnerResults.forEach { result in
switch result.earnings {
case 0.0..<250000.0:
low.increment()
case 250000.0...1000000.0:
medium.increment()
default:
high.increment()
}
}
return counters
}
static func gamesDistribution(realm: Realm) -> [DistributionCounter] {
let tournaments: Results<Tournament> = realm.objects(Tournament.self)
let noLimitHoldem = DistributionCounter(name: Game.holdem.rawValue)
let potLimitOmaha = DistributionCounter(name: Game.omaha.rawValue)
let not = DistributionCounter(name: "Others")
let games: [DistributionCounter] = [noLimitHoldem, potLimitOmaha, not]
tournaments.forEach { tournament in
if tournament.name.contains(Game.holdem.rawValue) {
noLimitHoldem.increment()
} else if tournament.name.contains(Game.omaha.rawValue) {
potLimitOmaha.increment()
} else {
not.increment()
}
}
return games
}
static func tableSizeDistribution(realm: Realm) -> [DistributionCounter] {
let tournaments: Results<Tournament> = realm.objects(Tournament.self).filter("name CONTAINS %@", "No-Limit Hold'em").distinct(by: ["tableSize"])
var slices: [DistributionCounter] = []
var othersCount: Int = 0
for tournament in tournaments {
let tableSizeCount = realm.objects(Tournament.self).filter("name CONTAINS %@", "No-Limit Hold'em").filter("tableSize == %i", tournament.tableSize).count
if (tableSizeCount < 6) {
othersCount += tableSizeCount
} else {
let counter = DistributionCounter(name: TableSize.format(tableSize: tournament.tableSize), counter: tableSizeCount)
slices.append(counter)
}
}
let others = DistributionCounter(name: "Others", counter: othersCount)
slices.append(others)
slices.sort { (d1, d2) -> Bool in
return d1.counter > d2.counter
}
return slices
}
static func rankingCounts(realm: Realm) -> [PlayerNotableFinishes] {
let players: Results<Player> = realm.objects(Player.self)
var notableFinishes: [PlayerNotableFinishes] = []
players.forEach { player in
var wins: [Result] = []
var runnerUps: [Result] = []
var finalTables: [Result] = []
player.results.forEach { result in
switch result.rank {
case 1:
wins.append(result)
case 2:
runnerUps.append(result)
default:
break
}
let tableSize: Int = result.tournaments.first?.tableSize ?? 9
if result.rank <= tableSize {
finalTables.append(result)
}
}
notableFinishes.append(PlayerNotableFinishes(player: player, wins: wins, runnerUps: runnerUps, finalTables: finalTables))
}
return notableFinishes
}
}