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.

238 lines
10 KiB

//
// Downloader.swift
// TournamentStats
//
// Created by Laurent Morvillier on 02/10/2021.
// Copyright © 2021 Stax River. All rights reserved.
//
import Foundation
import RealmSwift
class Downloader {
struct TS {
var id: String
var date: String
}
static func downloadWSOPResults() {
let ids = ["21666", // 1
"21667", // 2
"21670", // 5
"21671", // 6
"21669", // 4
"21672", // 7
"21673", // 8
"21674", // 9
"21668", // 3
"21675", // 10
"21676", // 11
]
for id in ids {
sleep(1)
downloadWSOPResults(id: id)
}
}
fileprivate static func downloadWSOPResults(id: String) {
print("Importing tournament \(id)")
guard let url = URL(string: "https://www.wsop.com/tournaments/results/?aid=2&grid=4943&tid=\(id)&rr=5") else {
return
}
let realm = try! Realm()
do {
try realm.write {
self.downloadWSOPResults(realm: realm, url: url)
}
} catch {
print("error = \(error)")
}
}
fileprivate static func downloadWSOPResults(realm: Realm, url: URL, currentTournament: Tournament? = nil) {
let nf = NumberFormatter()
nf.numberStyle = .decimal
nf.locale = Locale.init(identifier: "en_US")
nf.groupingSeparator = ","
do {
let string = try String(contentsOf: url)
let infos = string.slice(from: "<div id=\"eventinfo\">", to: "<div class='eventinfo-reports'>")
?? string.slice(from: "<div id=\"eventinfo\">", to: "eventinfo-progress")
?? string.slice(from: "<div id=\"eventinfo\">", to: "eventstats")
if let infos = infos {
var tournament: Tournament? = currentTournament
if tournament == nil {
let tour = realm.create(Tournament.self)
tournament = tour
// <p>Sunday, July 17, 2022 to Sunday, July 17, 2022</p>
if let name = infos.slice(from: "<h1>", to: "</h1>") {
tour.name = name
let fullDatesString = infos.slice(from: "<p>", to: "</p>")
let fullDates = fullDatesString?.components(separatedBy: " to ")
if let endString = fullDates?.last, let end = Formatter.longDate.date(from: endString) {
tour.date = end
} else {
print("Using now for date")
tour.date = Date()
}
if let strNumber = name.slice(from: "Event #", to: ":"), let number = nf.number(from: strNumber) {
tour.number = number.intValue
}
print("#\(tour.number) \(name)")
if name.contains("6-Handed") {
tour.tableSize = 6
} else if name.contains("7-Handed") {
tour.tableSize = 7
} else if name.contains("8-Handed") {
tour.tableSize = 8
} else if name.contains("Heads-Up") || name.contains("Heads Up") {
tour.tableSize = 2
}
} else {
print("no name = \(infos)")
}
if let stats = string.slice(from: "<ul id=\"eventstats\">", to: "<div id=\"nav-tabs\">") {
if let strBuyin = stats.slice(from: "Buy-in:</b> &#36;", to: "</li>"), let buyin = nf.number(from: strBuyin) {
tour.buyin = buyin.intValue
} else {
print("no buyin = \(stats)")
}
if let strprizepool = stats.slice(from: "Prizepool:</b> &#36;", to: " </li>"), let pp = nf.number(from: strprizepool) {
tour.prizepool = pp.doubleValue
} else {
print("no prizepool = \(stats)")
}
if let strentries = stats.slice(from: "Entries:</b> ", to: " </li>"), let entries = nf.number(from: strentries) {
tour.entries = entries.intValue
} else {
print("no entries = \(stats)")
}
}
}
if let strresultsblock = string.slice(from: "Country</li>", to: "<div id=\"PagingNav\"") {
let strresults = strresultsblock.components(separatedBy: "<li class='place")
print("Results count = \(strresults.count)")
for strresult in strresults {
let cells = strresult.components(separatedBy: "<li")
if !(cells.count == 6 || cells.count == 7) {
// print("cell count = \(cells.count)")
continue
}
let hasPOY = cells.count == 7
var rank: Int? = nil
var name: String? = nil
var earnings: Double? = nil
var city: String? = nil
var state: String? = nil
var country: String? = nil
var poy: Double? = nil
if let strrank = cells[0].slice(from: ">", to: "<") {
rank = nf.number(from: strrank)?.intValue
}
if let nameraw = cells[1].components(separatedBy: "'>").last {
name = nameraw.replacingOccurrences(of: "</a></li>", with: "")
}
if let earningsraw = cells[2].components(separatedBy: "&#36;").last {
let strearnings = earningsraw.replacingOccurrences(of: "</li>", with: "")
earnings = nf.number(from: strearnings)?.doubleValue
}
if hasPOY, let poyraw = cells[3].components(separatedBy: "\'>").last {
let strpoy = poyraw.replacingOccurrences(of: "</li>", with: "")
poy = nf.number(from: strpoy)?.doubleValue
}
let cityIndex = hasPOY ? 4 : 3
if let cityraw = cells[cityIndex].components(separatedBy: "\'>").last {
city = cityraw.replacingOccurrences(of: "</li>", with: "")
}
let stateIndex = hasPOY ? 5 : 4
if let stateraw
= cells[stateIndex].components(separatedBy: "\'>").last {
state = stateraw.replacingOccurrences(of: "</li>", with: "")
}
let countryIndex = hasPOY ? 6 : 5
if let countryraw
= cells[countryIndex].components(separatedBy: "\'>").last {
country = String(countryraw.prefix(2))
}
guard let rank = rank, let name = name, let earnings = earnings else {
print("Missing data: R: \(String(describing: rank)), N: \(name), E: \(earnings)")
continue
}
let player = realm.getOrCreatePlayer(name: name, city: city ?? "", state: state ?? "", country: country ?? "")
let result = realm.create(Result.self)
result.player = player
result.earnings = earnings
result.rank = rank
tournament?.results.append(result)
}
if currentTournament == nil, let paging = string.slice(from: "<div id=\"PagingNav\"", to: "<div class=\"banner\">") {
let pages = paging.components(separatedBy: "<a href='")
if pages.count > 2 {
for i in 2..<pages.count { // don't do page 1 again
let components = pages[i].components(separatedBy: "'")
if let urlString = components.first,
let url = URL(string: "https://www.wsop.com\(urlString)") {
self.downloadWSOPResults(realm: realm, url: url, currentTournament: tournament)
}
}
}
}
} else {
print("Bad page strresultsblock")
}
} else {
print("Missing name block")
}
} catch {
print("some error = \(error)")
}
}
}