From 3bf0aa4eb4c25b47d56467ec37abe2c9149827eb Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 15 Aug 2019 16:48:55 +0200 Subject: [PATCH] More improvements in the infography --- TournamentStats.xcodeproj/project.pbxproj | 24 +- TournamentStats/AppDelegate.swift | 29 +- TournamentStats/Seed.swift | 176 +++++------ TournamentStats/UI/Fonts.swift | 19 ++ .../UI/components/DataSourceWrapper.swift | 53 ++-- TournamentStats/UI/components/Label.swift | 24 ++ TournamentStats/UI/components/PieChart.swift | 3 +- TournamentStats/UI/components/TableView.swift | 34 ++- .../UI/reports/InfographyView.swift | 223 +++++++------- TournamentStats/UI/reports/InfographyView.xib | 280 ++++++++++++++++++ .../UI/reports/InfographyViewController.swift | 192 ++++++++++++ TournamentStats/report/Queries.swift | 11 +- TournamentStats/report/ReportGenerator.swift | 22 +- .../report/structures/CountryCounter.swift | 21 +- .../report/structures/CumulatedResults.swift | 4 +- .../structures/TournamentRepresentable.swift | 8 +- .../report/structures/TournamentStats.swift | 85 +++++- .../utils/ColumnRepresentable.swift | 26 +- 18 files changed, 968 insertions(+), 266 deletions(-) create mode 100644 TournamentStats/UI/Fonts.swift create mode 100644 TournamentStats/UI/components/Label.swift create mode 100644 TournamentStats/UI/reports/InfographyView.xib create mode 100644 TournamentStats/UI/reports/InfographyViewController.swift diff --git a/TournamentStats.xcodeproj/project.pbxproj b/TournamentStats.xcodeproj/project.pbxproj index 7940728..4a18947 100644 --- a/TournamentStats.xcodeproj/project.pbxproj +++ b/TournamentStats.xcodeproj/project.pbxproj @@ -36,7 +36,7 @@ 4D2F1C5B22CC92D1007C639E /* event84 in Resources */ = {isa = PBXBuildFile; fileRef = 4D2F1C4322CC92D1007C639E /* event84 */; }; 4D30463322F4232600DA86C4 /* event57 in Resources */ = {isa = PBXBuildFile; fileRef = 4D30463122F4232600DA86C4 /* event57 */; }; 4D30463422F4232600DA86C4 /* event78 in Resources */ = {isa = PBXBuildFile; fileRef = 4D30463222F4232600DA86C4 /* event78 */; }; - 4D39B6F122F829A500625E31 /* InfographyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D39B6F022F829A500625E31 /* InfographyView.swift */; }; + 4D39B6F122F829A500625E31 /* InfographyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D39B6F022F829A500625E31 /* InfographyViewController.swift */; }; 4D39B6F322F8549100625E31 /* DataSourceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D39B6F222F8549100625E31 /* DataSourceWrapper.swift */; }; 4D39B6F522F856EF00625E31 /* StackTableCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4D39B6F422F856EF00625E31 /* StackTableCell.xib */; }; 4D39B6F722F8573900625E31 /* StackTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D39B6F622F8573900625E31 /* StackTableCell.swift */; }; @@ -44,6 +44,10 @@ 4D39B6FC22F8686300625E31 /* CumulatedWins.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D39B6FB22F8686300625E31 /* CumulatedWins.swift */; }; 4D39B6FE22F87C3700625E31 /* Charts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D39B6FD22F87C3700625E31 /* Charts.framework */; }; 4DA5CA1E22AD078A00AC628E /* CountryCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DA5CA1D22AD078A00AC628E /* CountryCounter.swift */; }; + 4DB113D72305480600D0C671 /* InfographyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4DB113D62305480600D0C671 /* InfographyView.xib */; }; + 4DB113D923054A4100D0C671 /* InfographyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DB113D823054A4100D0C671 /* InfographyView.swift */; }; + 4DB113DB230559F600D0C671 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DB113DA230559F600D0C671 /* Label.swift */; }; + 4DB113DD2305882A00D0C671 /* Fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DB113DC2305882A00D0C671 /* Fonts.swift */; }; 4DDEF11422AE4FB900F4D7C1 /* TournamentStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DDEF11322AE4FB900F4D7C1 /* TournamentStats.swift */; }; 4DF7608422A3FB96004B0EF1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF7608322A3FB96004B0EF1 /* AppDelegate.swift */; }; 4DF7608622A3FB96004B0EF1 /* MasterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF7608522A3FB96004B0EF1 /* MasterViewController.swift */; }; @@ -178,7 +182,7 @@ 4D2F1C4322CC92D1007C639E /* event84 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = event84; sourceTree = ""; }; 4D30463122F4232600DA86C4 /* event57 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = event57; sourceTree = ""; }; 4D30463222F4232600DA86C4 /* event78 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = event78; sourceTree = ""; }; - 4D39B6F022F829A500625E31 /* InfographyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfographyView.swift; sourceTree = ""; }; + 4D39B6F022F829A500625E31 /* InfographyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfographyViewController.swift; sourceTree = ""; }; 4D39B6F222F8549100625E31 /* DataSourceWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataSourceWrapper.swift; sourceTree = ""; }; 4D39B6F422F856EF00625E31 /* StackTableCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StackTableCell.xib; sourceTree = ""; }; 4D39B6F622F8573900625E31 /* StackTableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackTableCell.swift; sourceTree = ""; }; @@ -186,6 +190,10 @@ 4D39B6FB22F8686300625E31 /* CumulatedWins.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CumulatedWins.swift; sourceTree = ""; }; 4D39B6FD22F87C3700625E31 /* Charts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Charts.framework; path = Carthage/Build/iOS/Charts.framework; sourceTree = ""; }; 4DA5CA1D22AD078A00AC628E /* CountryCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountryCounter.swift; sourceTree = ""; }; + 4DB113D62305480600D0C671 /* InfographyView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = InfographyView.xib; sourceTree = ""; }; + 4DB113D823054A4100D0C671 /* InfographyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfographyView.swift; sourceTree = ""; }; + 4DB113DA230559F600D0C671 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; + 4DB113DC2305882A00D0C671 /* Fonts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Fonts.swift; sourceTree = ""; }; 4DDEF11322AE4FB900F4D7C1 /* TournamentStats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentStats.swift; sourceTree = ""; }; 4DF7608022A3FB96004B0EF1 /* TournamentStats.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TournamentStats.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4DF7608322A3FB96004B0EF1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -308,7 +316,9 @@ 4D97941222F827A5004A2D7F /* reports */ = { isa = PBXGroup; children = ( - 4D39B6F022F829A500625E31 /* InfographyView.swift */, + 4D39B6F022F829A500625E31 /* InfographyViewController.swift */, + 4DB113D62305480600D0C671 /* InfographyView.xib */, + 4DB113D823054A4100D0C671 /* InfographyView.swift */, ); path = reports; sourceTree = ""; @@ -498,6 +508,7 @@ 4D39B6F622F8573900625E31 /* StackTableCell.swift */, 4D39B6F922F85C3400625E31 /* UIView+Extensions.swift */, 4DF78DD322F9C85C00C02F73 /* UIColor+Extensions.swift */, + 4DB113DC2305882A00D0C671 /* Fonts.swift */, ); path = UI; sourceTree = ""; @@ -544,6 +555,7 @@ 4DF78DD022F9AADF00C02F73 /* TableView.swift */, 4D39B6F222F8549100625E31 /* DataSourceWrapper.swift */, 4DF78DD522F9CE7E00C02F73 /* TitleLabel.swift */, + 4DB113DA230559F600D0C671 /* Label.swift */, ); path = components; sourceTree = ""; @@ -643,6 +655,7 @@ 4DF7609022A3FB98004B0EF1 /* LaunchScreen.storyboard in Resources */, 4DF7612B22A56797004B0EF1 /* event15 in Resources */, 4DF7608D22A3FB98004B0EF1 /* Assets.xcassets in Resources */, + 4DB113D72305480600D0C671 /* InfographyView.xib in Resources */, 4D2F1C5722CC92D1007C639E /* event72 in Resources */, 4DF7613722A56797004B0EF1 /* event68 in Resources */, 4DF7611922A56797004B0EF1 /* event18 in Resources */, @@ -765,12 +778,13 @@ buildActionMask = 2147483647; files = ( 4DF7614822A59660004B0EF1 /* ReportGenerator.swift in Sources */, + 4DB113D923054A4100D0C671 /* InfographyView.swift in Sources */, 4DF78DD422F9C85C00C02F73 /* UIColor+Extensions.swift in Sources */, 4DF760C222A561FF004B0EF1 /* ColumnRepresentable.swift in Sources */, 4DF760B022A47C74004B0EF1 /* RowImporter.swift in Sources */, 4DF7614A22A66675004B0EF1 /* TournamentWinner.swift in Sources */, 4D0F103722C4C08F005F797A /* ChipCount.swift in Sources */, - 4D39B6F122F829A500625E31 /* InfographyView.swift in Sources */, + 4D39B6F122F829A500625E31 /* InfographyViewController.swift in Sources */, 4DF760B322A47CAE004B0EF1 /* Realm+Extensions.swift in Sources */, 4DF7608822A3FB96004B0EF1 /* DetailViewController.swift in Sources */, 4DF78DD122F9AADF00C02F73 /* TableView.swift in Sources */, @@ -787,6 +801,7 @@ 4DF78DCE22F9AA3F00C02F73 /* PieChart.swift in Sources */, 4DF7614622A59407004B0EF1 /* CumulatedResults.swift in Sources */, 4D0F103922C4C1C4005F797A /* ChipCountParser.swift in Sources */, + 4DB113DD2305882A00D0C671 /* Fonts.swift in Sources */, 4D39B6FA22F85C3400625E31 /* UIView+Extensions.swift in Sources */, 4DF760BF22A560AA004B0EF1 /* FileWriter.swift in Sources */, 4DA5CA1E22AD078A00AC628E /* CountryCounter.swift in Sources */, @@ -794,6 +809,7 @@ 4DF760BC22A5270E004B0EF1 /* Queries.swift in Sources */, 4DF760BA22A524F4004B0EF1 /* Formatters.swift in Sources */, 4DF7614D22A6CC0D004B0EF1 /* NotablePlayers.swift in Sources */, + 4DB113DB230559F600D0C671 /* Label.swift in Sources */, 4DF760C922A56497004B0EF1 /* Seed.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/TournamentStats/AppDelegate.swift b/TournamentStats/AppDelegate.swift index 3e80ac3..9a7dbca 100644 --- a/TournamentStats/AppDelegate.swift +++ b/TournamentStats/AppDelegate.swift @@ -36,15 +36,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele print("start report generation...") let s = Date() let generator = ReportGenerator() - generator.go() + generator.go(importData: false) let d = Date().timeIntervalSince(s) print("reports created in \(d)s") - if let ivc = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "container") as? InfographyViewController { - ivc.generator = generator - ivc.view.frame = CGRect(x: 0, y: 0, width: 1000, height: 1000) + if let infographyView = Bundle.main.loadNibNamed("InfographyView", owner: self, options: nil)?.first as? InfographyView { + infographyView.generator = generator - if let imageData = ivc.view.toImage()?.pngData() { + if let imageData = infographyView.toImage()?.pngData() { guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) as NSURL else { return false @@ -60,6 +59,26 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele } +// if let ivc = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "container") as? InfographyViewController { +// ivc.generator = generator +// ivc.view.frame = CGRect(x: 0, y: 0, width: 1500, height: 1500) +// +// if let imageData = ivc.view.toImage()?.pngData() { +// +// guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) as NSURL else { +// return false +// } +// +// do { +// try imageData.write(to: directory.appendingPathComponent("infography.png")!) +// } catch { +// print(error.localizedDescription) +// } +// +// } +// +// } + return true } diff --git a/TournamentStats/Seed.swift b/TournamentStats/Seed.swift index 478169b..1cbd32a 100644 --- a/TournamentStats/Seed.swift +++ b/TournamentStats/Seed.swift @@ -25,94 +25,94 @@ class Seed { static let tournamentsDescriptions: [TD] = [ TD(date: "31/05/2019", name: "Casino Employees Event", number: 1, buyin: 500, entries: 685, prizePool: 297975), TD(date: "30/05/2019", name: "Super Turbo Bounty", number: 2, buyin: 10000, entries: 204, prizePool: 1917600), -// TD(date: "08/06/2019", name: "BIG 50 No-Limit Hold'em", number: 3, buyin: 500, entries: 28371, prizePool: 13509435), -// TD(date: "02/06/2019", name: "Omaha Hi/Lo 8 or Better", number: 4, buyin: 1500, entries: 853, prizePool: 1151550), -// TD(date: "03/06/2019", name: "High Roller No-Limit Hold'em for the 50th Annual", number: 5, buyin: 50000, entries: 110, prizePool: 5280000), -// TD(date: "03/06/2019", name: "Limit Mixed Triple Draw", number: 6, buyin: 2500, entries: 296, prizePool: 666000), -// TD(date: "03/06/2019", name: "WSOP.com ONLINE No-Limit Hold'em", number: 7, buyin: 400, entries: 2825, prizePool: 1017000), -// TD(date: "05/06/2019", name: "Short Deck No-Limit Hold'em", number: 8, buyin: 10000, entries: 114, prizePool: 1071600), -// TD(date: "06/06/2019", name: "No-Limit Hold'em Deepstack", number: 9, buyin: 600, entries: 6150, prizePool: 3229275), -// TD(date: "06/06/2019", name: "Dealers Choice", number: 10, buyin: 150, entries: 470, prizePool: 634500), -// TD(date: "07/06/2019", name: "No-Limit Hold'em", number: 11, buyin: 5000, entries: 400, prizePool: 1860000), -// TD(date: "06/06/2019", name: "No-Limit Hold'em Super Turbo Bounty", number: 12, buyin: 1000, entries: 2452, prizePool: 1471200), -// TD(date: "07/06/2019", name: "No-Limit 2-7 Lowball Draw", number: 13, buyin: 1500, entries: 296, prizePool: 399600), -// TD(date: "09/06/2019", name: "HORSE", number: 14, buyin: 1500, entries: 751, prizePool: 1013850), -// TD(date: "09/06/2019", name: "Heads-Up No-Limit Hold'em", number: 15, buyin: 10000, entries: 112, prizePool: 1052800), -// TD(date: "09/06/2019", name: "No-Limit Hold'em 6-Handed", number: 16, buyin: 1500, entries: 1832, prizePool: 2473200), -// TD(date: "09/06/2019", name: "No-Limit Hold'em Shootout", number: 17, buyin: 1500, entries: 917, prizePool: 1237950), -// TD(date: "10/06/2019", name: "Omaha Hi-Lo 8 or Better", number: 18, buyin: 10000, entries: 183, prizePool: 1720200), -// TD(date: "13/06/2019", name: "Millionaire Maker - No-Limit Hold'em", number: 19, buyin: 1500, entries: 8809, prizePool: 11892150), -// TD(date: "11/06/2019", name: "Seven-Card Stud", number: 20, buyin: 1500, entries: 285, prizePool: 384750), -// TD(date: "12/06/2019", name: "No-Limit 2-7 Lowball Draw", number: 21, buyin: 10000, entries: 91, prizePool: 855400), -// TD(date: "12/06/2019", name: "Double Stack No-Limit Hold'em", number: 22, buyin: 1000, entries: 3253, prizePool: 2927700), -// TD(date: "13/06/2019", name: "Eight Game Mix", number: 23, buyin: 1500, entries: 612, prizePool: 826200), -// TD(date: "11/06/2019", name: "WSOP.com ONLINE Pot-Limit Omaha 6-Handed", number: 24, buyin: 600, entries: 1216, prizePool: 656640), -// TD(date: "13/06/2019", name: "Pot-Limit Omaha Deepstack", number: 25, buyin: 600, entries: 2577, prizePool: 1352925), -// TD(date: "16/06/2019", name: "No-Limit Hold'em Marathon", number: 26, buyin: 2620, entries: 1083, prizePool: 2553714), -// TD(date: "14/06/2019", name: "Seven-Card Stud Hi/Lo 8 or Better", number: 27, buyin: 1500, entries: 460, prizePool: 621000), -// TD(date: "14/06/2019", name: "No-Limit Hold'em", number: 28, buyin: 1000, entries: 2477, prizePool: 2229300), -// TD(date: "15/06/2019", name: "HORSE", number: 29, buyin: 10000, entries: 172, prizePool: 1616800), -// TD(date: "16/06/2019", name: "Pot-Limit Omaha", number: 30, buyin: 1000, entries: 1526, prizePool: 1374300), -// TD(date: "15/06/2019", name: "No-Limit Hold'em 6-Handed", number: 31, buyin: 3000, entries: 754, prizePool: 2035800), -// TD(date: "17/06/2019", name: "Seniors No-Limit Hold'em", number: 32, buyin: 1000, entries: 5916 , prizePool: 5324400), -// TD(date: "16/06/2019", name: "Limit 2-7 Lowball Triple Draw", number: 33, buyin: 1500, entries: 467, prizePool: 630450), -// TD(date: "17/06/2019", name: "WSOP.com ONLINE No-Limit Hold'em Knockout Bounty", number: 38, buyin: 600, entries: 1224, prizePool: 550800), -// TD(date: "18/06/2019", name: "Dealers Choice 6-Handed", number: 35, buyin: 10000, entries: 122, prizePool: 1146800), -// TD(date: "18/06/2019", name: "No-Limit Hold'em Shootout", number: 36, buyin: 3000, entries: 313, prizePool: 845100), -// TD(date: "19/06/2019", name: "No-Limit Hold'em Deepstack", number: 37, buyin: 800, entries: 2808, prizePool: 1999296), -// TD(date: "20/06/2019", name: "Double Stack No-Limit Hold'em", number: 34, buyin: 1000, entries: 6241, prizePool: 5592600), -// TD(date: "20/06/2019", name: "Pot-Limit Omaha", number: 40, buyin: 1500, entries: 1216, prizePool: 1641600), -// TD(date: "20/06/2019", name: "Seven Card Stud", number: 41, buyin: 10000, entries: 88, prizePool: 827200), -// TD(date: "21/06/2019", name: "Super Seniors No-Limit Hold'em", number: 39, buyin: 1000, entries: 2650, prizePool: 2385000), -// TD(date: "20/06/2019", name: "WSOP.com ONLINE No-Limit Hold'em Turbo Deepstack", number: 46, buyin: 500, entries: 1181, prizePool: 795180), -// TD(date: "21/06/2019", name: "Mixed No-Limit Hold'em / Pot-Limit Omaha Deepstack 8-Handed", number: 42, buyin: 600, entries: 2403, prizePool: 1261575), -// TD(date: "21/06/2019", name: "Mixed Big Bet", number: 43, buyin: 2500, entries: 218, prizePool: 490500), -// TD(date: "22/06/2019", name: "No-Limit Hold'em Bounty", number: 44, buyin: 1500, entries: 1807, prizePool: 2439450), -// TD(date: "23/06/2019", name: "Pot-Limit Omaha High Roller", number: 45, buyin: 25000, entries: 278, prizePool: 6602500), -// TD(date: "23/06/2019", name: "No-Limit Hold'em", number: 48, buyin: 2500, entries: 996, prizePool: 2241000), -// TD(date: "23/06/2019", name: "Limit 2-7 Lowball Triple Draw", number: 49, buyin: 10000, entries: 100, prizePool: 940000), -// TD(date: "24/06/2019", name: "$1,000/$10,000 Ladies No-Limit Hold'em", number: 47, buyin: 10000, entries: 968, prizePool: 871200), -// TD(date: "24/06/2019", name: "Mixed Omaha Hi/Lo 8 or Better, Seven Card Stud Hi/Lo 8 or Better", number: 51, buyin: 2500, entries: 401, prizePool: 902250), -// TD(date: "25/06/2019", name: "WSOP.com ONLINE No-Limit Hold'em Double Stack", number: 55, buyin: 1000, entries: 1333, prizePool: 1266350), -// TD(date: "26/06/2019", name: "Pot-Limit Omaha 8-Handed", number: 52, buyin: 10000, entries: 518, prizePool: 4869200), -// TD(date: "26/06/2019", name: "No-Limit Hold'em Deepstack 8-Handed", number: 53, buyin: 800, entries: 3759, prizePool: 2676408), -// TD(date: "26/06/2019", name: "Razz", number: 54, buyin: 1500, entries: 363, prizePool: 490050), -// TD(date: "26/06/2019", name: "No-Limit Hold'em Super Turbo Bounty", number: 56, buyin: 1500, entries: 1867, prizePool: 2520450), -// TD(date: "27/06/2019", name: "Monster Stack No-Limit Hold'em", number: 50, buyin: 1500, entries: 6035, prizePool: 8147250), -// TD(date: "27/06/2019", name: "Tag Team No-Limit Hold'em", number: 57, buyin: 1000, entries: 976, prizePool: 878400), -// TD(date: "29/06/2019", name: "Poker Players Championship", number: 58, buyin: 50000, entries: 74, prizePool: 3552000), -// TD(date: "29/06/2019", name: "No-Limit Hold'em DEEPSTACK CHAMPIONSHIP", number: 59, buyin: 600, entries: 6140, prizePool: 3223500), -// TD(date: "29/06/2019", name: "Pot-Limit Omaha Hi/Lo 8 or Better", number: 60, buyin: 1500, entries: 1117, prizePool: 1507950), -// TD(date: "30/06/2019", name: "Razz", number: 62, buyin: 10000, entries: 116, prizePool: 1090400), -// TD(date: "01/07/2019", name: "COLOSSUS", number: 61, buyin: 400, entries: 13109, prizePool: 4382515), -// TD(date: "01/07/2019", name: "Omaha Mix", number: 63, buyin: 1500, entries: 717, prizePool: 967950), -// TD(date: "02/07/2019", name: "Pot-Limit Omaha Hi-Lo 8 or Better ", number: 65, buyin: 10000, entries: 193, prizePool: 1814200), -// TD(date: "02/07/2019", name: "WSOP.com ONLINE No-Limit Hold'em Championship", number: 68, buyin: 1000, entries: 1750, prizePool: 1662500), -// TD(date: "03/07/2019", name: "Seven Card Stud Hi-Lo 8 or Better", number: 67, buyin: 10000, entries: 151, prizePool: 1419400), -// TD(date: "04/07/2019", name: "Crazy Eights No-Limit Hold'em", number: 64, buyin: 888, entries: 10185, prizePool: 8139852), -// TD(date: "04/07/2019", name: "Limit Hold'em", number: 66, buyin: 1500, entries: 541, prizePool: 730350), -// TD(date: "04/07/2019", name: "Mini Main Event", number: 69, buyin: 1000, entries: 5521, prizePool: 4968900), -// TD(date: "05/07/2019", name: "No-Limit Hold'em 6-Handed", number: 70, buyin: 5000, entries: 815, prizePool: 3789750), -// TD(date: "05/07/2019", name: "Limit Hold'em Championship", number: 72, buyin: 10000, entries: 118, prizePool: 1109200), -// TD(date: "05/07/2019", name: "WSOP.com ONLINE No-Limit Hold'em High Roller", number: 74, buyin: 3200, entries: 593, prizePool: 1802720), -// TD(date: "06/07/2019", name: "SALUTE TO WARRIORS - $500 No-Limit Hold'em", number: 71, buyin: 500, entries: 1723, prizePool: 723660), -// TD(date: "08/07/2019", name: "WSOP.com ONLINE No-Limit Hold'em 6-Handed", number: 76, buyin: 800, entries: 1560, prizePool: 1170000), -// TD(date: "11/07/2019", name: "Final Fifty No-Limit Hold'em", number: 90, buyin: 50000, entries: 123, prizePool: 5904000), -// TD(date: "12/07/2019", name: "Limit Hold'em 6-Handed", number: 77, buyin: 3000, entries: 193, prizePool: 521100), -// TD(date: "13/07/2019", name: "Pot-Limit Omaha Bounty", number: 78, buyin: 1500, entries: 1130 , prizePool: 1525500), -// TD(date: "13/07/2019", name: "Little One for One Drop", number: 75, buyin: 1111, entries: 6248, prizePool: 5623200), -// TD(date: "13/07/2019", name: "No-Limit Hold'em", number: 79, buyin: 3000, entries: 671, prizePool: 1811700), -// TD(date: "13/07/2019", name: "50th Annual Bracelet Winners Only No-Limit Hold'em", number: 81, buyin: 1500, entries: 185, prizePool: 277500), -// TD(date: "14/07/2019", name: "Mixed No-Limit Hold'em Pot-Limit Omaha", number: 80, buyin: 1500, entries: 1250, prizePool: 1687500), -// TD(date: "14/07/2019", name: "No-Limit Hold'em High Roller", number: 83, buyin: 100000, entries: 88, prizePool: 9603000), -// TD(date: "15/07/2019", name: "No-Limit Hold'em Double Stack", number: 82, buyin: 1500, entries: 2589, prizePool: 3495150), -// TD(date: "15/07/2019", name: "WSOP.com ONLINE No-Limit Hold'em Summer Saver", number: 88, buyin: 500, entries: 1859, prizePool: 836550), -// TD(date: "16/07/2019", name: "The Closer - No-Limit Hold'em", number: 84, buyin: 1500, entries: 2800, prizePool: 3780000), -// TD(date: "16/07/2019", name: "Pot-Limit Omaha 6-Handed", number: 85, buyin: 3000, entries: 835, prizePool: 2254500), -// TD(date: "17/07/2019", name: "No-Limit Hold'em 6-Handed", number: 86, buyin: 10000, entries: 272, prizePool: 2556800), -// TD(date: "17/07/2019", name: "HORSE", number: 87, buyin: 3000, entries: 301, prizePool: 812700), -// TD(date: "17/07/2019", name: "No-Limit Hold'em", number: 89, buyin: 5000, entries: 608, prizePool: 2827200), -// TD(date: "17/07/2019", name: "No-Limit Hold'em MAIN EVENT - World Championship", number: 73, buyin: 10000, entries: 8569, prizePool: 80548600), + TD(date: "08/06/2019", name: "BIG 50 No-Limit Hold'em", number: 3, buyin: 500, entries: 28371, prizePool: 13509435), + TD(date: "02/06/2019", name: "Omaha Hi/Lo 8 or Better", number: 4, buyin: 1500, entries: 853, prizePool: 1151550), + TD(date: "03/06/2019", name: "High Roller No-Limit Hold'em for the 50th Annual", number: 5, buyin: 50000, entries: 110, prizePool: 5280000), + TD(date: "03/06/2019", name: "Limit Mixed Triple Draw", number: 6, buyin: 2500, entries: 296, prizePool: 666000), + TD(date: "03/06/2019", name: "WSOP.com ONLINE No-Limit Hold'em", number: 7, buyin: 400, entries: 2825, prizePool: 1017000), + TD(date: "05/06/2019", name: "Short Deck No-Limit Hold'em", number: 8, buyin: 10000, entries: 114, prizePool: 1071600), + TD(date: "06/06/2019", name: "No-Limit Hold'em Deepstack", number: 9, buyin: 600, entries: 6150, prizePool: 3229275), + TD(date: "06/06/2019", name: "Dealers Choice", number: 10, buyin: 150, entries: 470, prizePool: 634500), + TD(date: "07/06/2019", name: "No-Limit Hold'em", number: 11, buyin: 5000, entries: 400, prizePool: 1860000), + TD(date: "06/06/2019", name: "No-Limit Hold'em Super Turbo Bounty", number: 12, buyin: 1000, entries: 2452, prizePool: 1471200), + TD(date: "07/06/2019", name: "No-Limit 2-7 Lowball Draw", number: 13, buyin: 1500, entries: 296, prizePool: 399600), + TD(date: "09/06/2019", name: "HORSE", number: 14, buyin: 1500, entries: 751, prizePool: 1013850), + TD(date: "09/06/2019", name: "Heads-Up No-Limit Hold'em", number: 15, buyin: 10000, entries: 112, prizePool: 1052800), + TD(date: "09/06/2019", name: "No-Limit Hold'em 6-Handed", number: 16, buyin: 1500, entries: 1832, prizePool: 2473200), + TD(date: "09/06/2019", name: "No-Limit Hold'em Shootout", number: 17, buyin: 1500, entries: 917, prizePool: 1237950), + TD(date: "10/06/2019", name: "Omaha Hi-Lo 8 or Better", number: 18, buyin: 10000, entries: 183, prizePool: 1720200), + TD(date: "13/06/2019", name: "Millionaire Maker - No-Limit Hold'em", number: 19, buyin: 1500, entries: 8809, prizePool: 11892150), + TD(date: "11/06/2019", name: "Seven-Card Stud", number: 20, buyin: 1500, entries: 285, prizePool: 384750), + TD(date: "12/06/2019", name: "No-Limit 2-7 Lowball Draw", number: 21, buyin: 10000, entries: 91, prizePool: 855400), + TD(date: "12/06/2019", name: "Double Stack No-Limit Hold'em", number: 22, buyin: 1000, entries: 3253, prizePool: 2927700), + TD(date: "13/06/2019", name: "Eight Game Mix", number: 23, buyin: 1500, entries: 612, prizePool: 826200), + TD(date: "11/06/2019", name: "WSOP.com ONLINE Pot-Limit Omaha 6-Handed", number: 24, buyin: 600, entries: 1216, prizePool: 656640), + TD(date: "13/06/2019", name: "Pot-Limit Omaha Deepstack", number: 25, buyin: 600, entries: 2577, prizePool: 1352925), + TD(date: "16/06/2019", name: "No-Limit Hold'em Marathon", number: 26, buyin: 2620, entries: 1083, prizePool: 2553714), + TD(date: "14/06/2019", name: "Seven-Card Stud Hi/Lo 8 or Better", number: 27, buyin: 1500, entries: 460, prizePool: 621000), + TD(date: "14/06/2019", name: "No-Limit Hold'em", number: 28, buyin: 1000, entries: 2477, prizePool: 2229300), + TD(date: "15/06/2019", name: "HORSE", number: 29, buyin: 10000, entries: 172, prizePool: 1616800), + TD(date: "16/06/2019", name: "Pot-Limit Omaha", number: 30, buyin: 1000, entries: 1526, prizePool: 1374300), + TD(date: "15/06/2019", name: "No-Limit Hold'em 6-Handed", number: 31, buyin: 3000, entries: 754, prizePool: 2035800), + TD(date: "17/06/2019", name: "Seniors No-Limit Hold'em", number: 32, buyin: 1000, entries: 5916 , prizePool: 5324400), + TD(date: "16/06/2019", name: "Limit 2-7 Lowball Triple Draw", number: 33, buyin: 1500, entries: 467, prizePool: 630450), + TD(date: "17/06/2019", name: "WSOP.com ONLINE No-Limit Hold'em Knockout Bounty", number: 38, buyin: 600, entries: 1224, prizePool: 550800), + TD(date: "18/06/2019", name: "Dealers Choice 6-Handed", number: 35, buyin: 10000, entries: 122, prizePool: 1146800), + TD(date: "18/06/2019", name: "No-Limit Hold'em Shootout", number: 36, buyin: 3000, entries: 313, prizePool: 845100), + TD(date: "19/06/2019", name: "No-Limit Hold'em Deepstack", number: 37, buyin: 800, entries: 2808, prizePool: 1999296), + TD(date: "20/06/2019", name: "Double Stack No-Limit Hold'em", number: 34, buyin: 1000, entries: 6241, prizePool: 5592600), + TD(date: "20/06/2019", name: "Pot-Limit Omaha", number: 40, buyin: 1500, entries: 1216, prizePool: 1641600), + TD(date: "20/06/2019", name: "Seven Card Stud", number: 41, buyin: 10000, entries: 88, prizePool: 827200), + TD(date: "21/06/2019", name: "Super Seniors No-Limit Hold'em", number: 39, buyin: 1000, entries: 2650, prizePool: 2385000), + TD(date: "20/06/2019", name: "WSOP.com ONLINE No-Limit Hold'em Turbo Deepstack", number: 46, buyin: 500, entries: 1181, prizePool: 795180), + TD(date: "21/06/2019", name: "Mixed No-Limit Hold'em / Pot-Limit Omaha Deepstack 8-Handed", number: 42, buyin: 600, entries: 2403, prizePool: 1261575), + TD(date: "21/06/2019", name: "Mixed Big Bet", number: 43, buyin: 2500, entries: 218, prizePool: 490500), + TD(date: "22/06/2019", name: "No-Limit Hold'em Bounty", number: 44, buyin: 1500, entries: 1807, prizePool: 2439450), + TD(date: "23/06/2019", name: "Pot-Limit Omaha High Roller", number: 45, buyin: 25000, entries: 278, prizePool: 6602500), + TD(date: "23/06/2019", name: "No-Limit Hold'em", number: 48, buyin: 2500, entries: 996, prizePool: 2241000), + TD(date: "23/06/2019", name: "Limit 2-7 Lowball Triple Draw", number: 49, buyin: 10000, entries: 100, prizePool: 940000), + TD(date: "24/06/2019", name: "$1,000/$10,000 Ladies No-Limit Hold'em", number: 47, buyin: 10000, entries: 968, prizePool: 871200), + TD(date: "24/06/2019", name: "Mixed Omaha Hi/Lo 8 or Better, Seven Card Stud Hi/Lo 8 or Better", number: 51, buyin: 2500, entries: 401, prizePool: 902250), + TD(date: "25/06/2019", name: "WSOP.com ONLINE No-Limit Hold'em Double Stack", number: 55, buyin: 1000, entries: 1333, prizePool: 1266350), + TD(date: "26/06/2019", name: "Pot-Limit Omaha 8-Handed", number: 52, buyin: 10000, entries: 518, prizePool: 4869200), + TD(date: "26/06/2019", name: "No-Limit Hold'em Deepstack 8-Handed", number: 53, buyin: 800, entries: 3759, prizePool: 2676408), + TD(date: "26/06/2019", name: "Razz", number: 54, buyin: 1500, entries: 363, prizePool: 490050), + TD(date: "26/06/2019", name: "No-Limit Hold'em Super Turbo Bounty", number: 56, buyin: 1500, entries: 1867, prizePool: 2520450), + TD(date: "27/06/2019", name: "Monster Stack No-Limit Hold'em", number: 50, buyin: 1500, entries: 6035, prizePool: 8147250), + TD(date: "27/06/2019", name: "Tag Team No-Limit Hold'em", number: 57, buyin: 1000, entries: 976, prizePool: 878400), + TD(date: "29/06/2019", name: "Poker Players Championship", number: 58, buyin: 50000, entries: 74, prizePool: 3552000), + TD(date: "29/06/2019", name: "No-Limit Hold'em DEEPSTACK CHAMPIONSHIP", number: 59, buyin: 600, entries: 6140, prizePool: 3223500), + TD(date: "29/06/2019", name: "Pot-Limit Omaha Hi/Lo 8 or Better", number: 60, buyin: 1500, entries: 1117, prizePool: 1507950), + TD(date: "30/06/2019", name: "Razz", number: 62, buyin: 10000, entries: 116, prizePool: 1090400), + TD(date: "01/07/2019", name: "COLOSSUS", number: 61, buyin: 400, entries: 13109, prizePool: 4382515), + TD(date: "01/07/2019", name: "Omaha Mix", number: 63, buyin: 1500, entries: 717, prizePool: 967950), + TD(date: "02/07/2019", name: "Pot-Limit Omaha Hi-Lo 8 or Better ", number: 65, buyin: 10000, entries: 193, prizePool: 1814200), + TD(date: "02/07/2019", name: "WSOP.com ONLINE No-Limit Hold'em Championship", number: 68, buyin: 1000, entries: 1750, prizePool: 1662500), + TD(date: "03/07/2019", name: "Seven Card Stud Hi-Lo 8 or Better", number: 67, buyin: 10000, entries: 151, prizePool: 1419400), + TD(date: "04/07/2019", name: "Crazy Eights No-Limit Hold'em", number: 64, buyin: 888, entries: 10185, prizePool: 8139852), + TD(date: "04/07/2019", name: "Limit Hold'em", number: 66, buyin: 1500, entries: 541, prizePool: 730350), + TD(date: "04/07/2019", name: "Mini Main Event", number: 69, buyin: 1000, entries: 5521, prizePool: 4968900), + TD(date: "05/07/2019", name: "No-Limit Hold'em 6-Handed", number: 70, buyin: 5000, entries: 815, prizePool: 3789750), + TD(date: "05/07/2019", name: "Limit Hold'em Championship", number: 72, buyin: 10000, entries: 118, prizePool: 1109200), + TD(date: "05/07/2019", name: "WSOP.com ONLINE No-Limit Hold'em High Roller", number: 74, buyin: 3200, entries: 593, prizePool: 1802720), + TD(date: "06/07/2019", name: "SALUTE TO WARRIORS - $500 No-Limit Hold'em", number: 71, buyin: 500, entries: 1723, prizePool: 723660), + TD(date: "08/07/2019", name: "WSOP.com ONLINE No-Limit Hold'em 6-Handed", number: 76, buyin: 800, entries: 1560, prizePool: 1170000), + TD(date: "11/07/2019", name: "Final Fifty No-Limit Hold'em", number: 90, buyin: 50000, entries: 123, prizePool: 5904000), + TD(date: "12/07/2019", name: "Limit Hold'em 6-Handed", number: 77, buyin: 3000, entries: 193, prizePool: 521100), + TD(date: "13/07/2019", name: "Pot-Limit Omaha Bounty", number: 78, buyin: 1500, entries: 1130 , prizePool: 1525500), + TD(date: "13/07/2019", name: "Little One for One Drop", number: 75, buyin: 1111, entries: 6248, prizePool: 5623200), + TD(date: "13/07/2019", name: "No-Limit Hold'em", number: 79, buyin: 3000, entries: 671, prizePool: 1811700), + TD(date: "13/07/2019", name: "50th Annual Bracelet Winners Only No-Limit Hold'em", number: 81, buyin: 1500, entries: 185, prizePool: 277500), + TD(date: "14/07/2019", name: "Mixed No-Limit Hold'em Pot-Limit Omaha", number: 80, buyin: 1500, entries: 1250, prizePool: 1687500), + TD(date: "14/07/2019", name: "No-Limit Hold'em High Roller", number: 83, buyin: 100000, entries: 88, prizePool: 9603000), + TD(date: "15/07/2019", name: "No-Limit Hold'em Double Stack", number: 82, buyin: 1500, entries: 2589, prizePool: 3495150), + TD(date: "15/07/2019", name: "WSOP.com ONLINE No-Limit Hold'em Summer Saver", number: 88, buyin: 500, entries: 1859, prizePool: 836550), + TD(date: "16/07/2019", name: "The Closer - No-Limit Hold'em", number: 84, buyin: 1500, entries: 2800, prizePool: 3780000), + TD(date: "16/07/2019", name: "Pot-Limit Omaha 6-Handed", number: 85, buyin: 3000, entries: 835, prizePool: 2254500), + TD(date: "17/07/2019", name: "No-Limit Hold'em 6-Handed", number: 86, buyin: 10000, entries: 272, prizePool: 2556800), + TD(date: "17/07/2019", name: "HORSE", number: 87, buyin: 3000, entries: 301, prizePool: 812700), + TD(date: "17/07/2019", name: "No-Limit Hold'em", number: 89, buyin: 5000, entries: 608, prizePool: 2827200), + TD(date: "17/07/2019", name: "No-Limit Hold'em MAIN EVENT - World Championship", number: 73, buyin: 10000, entries: 8569, prizePool: 80548600), ] diff --git a/TournamentStats/UI/Fonts.swift b/TournamentStats/UI/Fonts.swift new file mode 100644 index 0000000..3a05447 --- /dev/null +++ b/TournamentStats/UI/Fonts.swift @@ -0,0 +1,19 @@ +// +// Fonts.swift +// TournamentStats +// +// Created by Laurent Morvillier on 15/08/2019. +// Copyright © 2019 Stax River. All rights reserved. +// + +import Foundation +import UIKit + +class Fonts { + + static let mainTitle: UIFont = UIFont.systemFont(ofSize: 64.0) + static let subTitle: UIFont = UIFont.systemFont(ofSize: 24.0) + static let pieChartEntries: UIFont = UIFont.boldSystemFont(ofSize: 28) + static let chartLegend: UIFont = UIFont.systemFont(ofSize: 18.0) + +} diff --git a/TournamentStats/UI/components/DataSourceWrapper.swift b/TournamentStats/UI/components/DataSourceWrapper.swift index 1c1ca40..60ff446 100644 --- a/TournamentStats/UI/components/DataSourceWrapper.swift +++ b/TournamentStats/UI/components/DataSourceWrapper.swift @@ -9,30 +9,38 @@ import Foundation import UIKit - - - class DataSourceWrapper : NSObject, UITableViewDataSource, UITableViewDelegate { var columnRepresentables: [T] let columnDescriptors = T.columnDescriptors() var totalWidthWeigth: CGFloat = 0.0 + fileprivate var _maxRows: Int? - init(array: [T]) { + init(array: [T], maxRows: Int? = nil) { self.columnRepresentables = array self.totalWidthWeigth = self.columnDescriptors.map { $0.widthWeight }.reduce(0, +) + if let max = maxRows, max > columnRepresentables.count { + self._maxRows = nil + } else { + self._maxRows = maxRows + } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { print("numberOfRowsInSection = \(self.columnRepresentables.count)") - return self.columnRepresentables.count + 1 // + 1 for header + if let max = self._maxRows { + return 1 + max + } else { + return self.columnRepresentables.count + 1 // + 1 for header + } } fileprivate let FONTSIZE: CGFloat = 18.0 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! StackTableCell - let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")! + let cell = UITableViewCell() + cell.backgroundColor = UIColor.clear var cells: [String] switch indexPath.row { @@ -52,24 +60,33 @@ class DataSourceWrapper : NSObject, UITableViewDataSour font = self.columnDescriptors[index].number ? UIFont.monospacedDigitSystemFont(ofSize: FONTSIZE, weight: UIFont.Weight.regular) : UIFont.systemFont(ofSize: FONTSIZE) } - let label: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: 50, height: 30)) + let labelContainer: UIView = UIView() + cell.contentView.addSubview(labelContainer) + labelContainer.translatesAutoresizingMaskIntoConstraints = false + labelContainer.topAnchor.constraint(equalTo: cell.contentView.topAnchor).isActive = true + labelContainer.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor).isActive = true + let leftPadding: CGFloat = (index == 0) ? 0.0 : 0.0 //16.0 + labelContainer.leftAnchor.constraint(equalTo: leftAnchor, constant: leftPadding).isActive = true + leftAnchor = labelContainer.rightAnchor + + labelContainer.backgroundColor = index.isMultiple(of: 2) ? UIColor.clear : UIColor(white: 0.9, alpha: 0.1) + + let multiplier: CGFloat = self.columnDescriptors[index].widthWeight / self.totalWidthWeigth + labelContainer.widthAnchor.constraint(equalTo: cell.contentView.widthAnchor, multiplier: multiplier).isActive = true + + let label: UILabel = UILabel(frame: CGRect.zero) label.textColor = UIColor.white label.backgroundColor = UIColor.clear label.text = value label.font = font label.textAlignment = self.columnDescriptors[index].number ? .right : .left - - cell.contentView.addSubview(label) - label.translatesAutoresizingMaskIntoConstraints = false - label.topAnchor.constraint(equalTo: cell.contentView.topAnchor).isActive = true - label.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor).isActive = true - label.leftAnchor.constraint(equalTo: leftAnchor).isActive = true - leftAnchor = label.rightAnchor + labelContainer.addSubview(label) - label.backgroundColor = index.isMultiple(of: 2) ? UIColor.clear : UIColor(white: 0.9, alpha: 0.1) - - let multiplier: CGFloat = self.columnDescriptors[index].widthWeight / self.totalWidthWeigth - label.widthAnchor.constraint(equalTo: cell.contentView.widthAnchor, multiplier: multiplier).isActive = true + label.translatesAutoresizingMaskIntoConstraints = false + label.topAnchor.constraint(equalTo: labelContainer.topAnchor).isActive = true + label.bottomAnchor.constraint(equalTo: labelContainer.bottomAnchor).isActive = true + label.leftAnchor.constraint(equalTo: labelContainer.leftAnchor, constant: 8.0).isActive = true + label.rightAnchor.constraint(equalTo: labelContainer.rightAnchor, constant: -8.0).isActive = true } return cell diff --git a/TournamentStats/UI/components/Label.swift b/TournamentStats/UI/components/Label.swift new file mode 100644 index 0000000..97dd43f --- /dev/null +++ b/TournamentStats/UI/components/Label.swift @@ -0,0 +1,24 @@ +// +// File.swift +// TournamentStats +// +// Created by Laurent Morvillier on 15/08/2019. +// Copyright © 2019 Stax River. All rights reserved. +// + +import Foundation +import UIKit + +class Label: UILabel { + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + self._initialize() + } + + fileprivate func _initialize() { + self.textColor = UIColor.white + self.font = Fonts.subTitle + } + +} diff --git a/TournamentStats/UI/components/PieChart.swift b/TournamentStats/UI/components/PieChart.swift index 72895e7..bded110 100644 --- a/TournamentStats/UI/components/PieChart.swift +++ b/TournamentStats/UI/components/PieChart.swift @@ -19,10 +19,9 @@ class PieChart : PieChartView { self.minOffset = 16.0 self.holeRadiusPercent = 0 self.drawEntryLabelsEnabled = false -// self. self.legend.textColor = UIColor.white - self.legend.font = UIFont.systemFont(ofSize: 16.0) + self.legend.font = Fonts.chartLegend self.legend.orientation = .vertical self.legend.form = .circle // self.legend.neededHeight = 203.0 diff --git a/TournamentStats/UI/components/TableView.swift b/TournamentStats/UI/components/TableView.swift index 70da512..eaf7ee9 100644 --- a/TournamentStats/UI/components/TableView.swift +++ b/TournamentStats/UI/components/TableView.swift @@ -9,26 +9,34 @@ import Foundation import UIKit -class TableView : UITableView { +class TableView : UITableView { - var wrapper: DataSourceWrapper + fileprivate var reference: AnyObject? - init(data: [T], frame: CGRect, style: UITableView.Style) { - - self.wrapper = DataSourceWrapper(array: data) - - super.init(frame: frame, style: style) + func setData(data: [T], maxRows: Int? = 10) { + let wrapper = DataSourceWrapper(array: data, maxRows: maxRows) - self.register(UINib(nibName: "StackTableCell", bundle: Bundle.main), forCellReuseIdentifier: "Cell") - self.backgroundColor = UIColor.clear + self.dataSource = wrapper + self.delegate = wrapper - self.dataSource = self.wrapper - self.delegate = self.wrapper - + self.reference = wrapper + } + + override init(frame: CGRect, style: UITableView.Style) { + super.init(frame: frame, style: style) + self._initialize() } required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") + super.init(coder: aDecoder) + self._initialize() } + + fileprivate func _initialize() { + + self.register(UINib(nibName: "StackTableCell", bundle: Bundle.main), forCellReuseIdentifier: "Cell") + self.backgroundColor = UIColor.clear + } + } diff --git a/TournamentStats/UI/reports/InfographyView.swift b/TournamentStats/UI/reports/InfographyView.swift index 8c69e45..d5b127b 100644 --- a/TournamentStats/UI/reports/InfographyView.swift +++ b/TournamentStats/UI/reports/InfographyView.swift @@ -2,21 +2,75 @@ // InfographyView.swift // TournamentStats // -// Created by Laurent Morvillier on 05/08/2019. +// Created by Laurent Morvillier on 15/08/2019. // Copyright © 2019 Stax River. All rights reserved. // import Foundation import UIKit -import Charts -class InfographyViewController : UIViewController { +class InfographyView: UIView { - var generator: ReportGenerator? + var generator: ReportGenerator? { + didSet { + self._fillView() + } + } + + @IBOutlet weak var infographyTitle: UILabel! + + @IBOutlet weak var hStack1a: UIStackView! + @IBOutlet weak var label11: UILabel! + @IBOutlet weak var label12: UILabel! + @IBOutlet weak var label13: UILabel! + + @IBOutlet weak var hStack1b: UIStackView! + @IBOutlet weak var tableView11: TableView! + @IBOutlet weak var tableView12: TableView! + @IBOutlet weak var tableView13: TableView! + + @IBOutlet weak var hStack2a: UIStackView! + @IBOutlet weak var label21: UILabel! + @IBOutlet weak var label22: UILabel! + @IBOutlet weak var label23: UILabel! + + @IBOutlet weak var hStack2b: UIStackView! + @IBOutlet weak var container21: UIView! + @IBOutlet weak var container22: UIView! + @IBOutlet weak var container23: UIView! + + @IBOutlet weak var hStack3a: UIStackView! + @IBOutlet weak var label31: UILabel! + @IBOutlet weak var label32: UILabel! + @IBOutlet weak var label33: UILabel! + + @IBOutlet weak var hStack3b: UIStackView! + @IBOutlet weak var tableView31: TableView! + @IBOutlet weak var tableView32: TableView! + @IBOutlet weak var tableView33: TableView! + + @IBOutlet weak var hStack4a: UIStackView! + @IBOutlet weak var label41: UILabel! + @IBOutlet weak var label42: UILabel! + + @IBOutlet weak var hStack4b: UIStackView! + @IBOutlet weak var container41: UIView! + @IBOutlet weak var container42: UIView! + + @IBOutlet weak var hStack5a: UIStackView! + @IBOutlet weak var label51: UILabel! - override func viewDidLayoutSubviews() { + @IBOutlet weak var hStack5b: UIStackView! + @IBOutlet weak var tableView51: TableView! + + + override func awakeFromNib() { + super.awakeFromNib() - super.viewDidLayoutSubviews() + self._createBackground() + } + + fileprivate func _createBackground() { let gradient: CAGradientLayer = CAGradientLayer() @@ -27,126 +81,77 @@ class InfographyViewController : UIViewController { gradient.locations = [0.2 , 1.0] gradient.startPoint = CGPoint(x: 0.0, y: 0.0) gradient.endPoint = CGPoint(x: 1.0, y: 1.0) - gradient.frame = self.view.bounds + gradient.frame = self.bounds - self.view.layer.insertSublayer(gradient, at: 0) + self.layer.insertSublayer(gradient, at: 0) } - override func viewDidLoad() { + fileprivate func _fillView() { guard let generator = self.generator else { return } - let table1 = TableView(data: generator.biggestWinners, frame: CGRect.zero, style: .grouped) - table1.defineConstraints(width: 500, height: 500) - - let table2 = TableView(data: generator.mostWins, frame: CGRect.zero, style: .grouped) - table2.defineConstraints(width: 500, height: 500) - - let hstack1: UIStackView = UIStackView(arrangedSubviews: [table1, table2]) - hstack1.defineConstraints(width: 1000, height: 300.0) - hstack1.distribution = .equalSpacing - hstack1.spacing = 8.0 - hstack1.axis = .horizontal - hstack1.alignment = .top - - let title1 = TitleLabel(frame: CGRect.zero, text: "Buy-in distribution") - let title2 = TitleLabel(frame: CGRect.zero, text: "First prizes distribution") - let title3 = TitleLabel(frame: CGRect.zero, text: "Prizepool distribution") + self.infographyTitle.text = "2019 WSOP" + self.infographyTitle.textColor = UIColor.white + self.infographyTitle.font = Fonts.mainTitle + + ///// + + self.label11.text = "Biggest Winners".uppercased() + self.label12.text = "Most Cashes".uppercased() + self.label13.text = "Best average cash (7+)".uppercased() + + self.tableView11.setData(data: generator.biggestWinners) + self.tableView12.setData(data: generator.mostCashes) + self.tableView13.setData(data: generator.averageCash) + + ///// - let hstack2a: UIStackView = UIStackView(arrangedSubviews: [title1, title2, title3]) - hstack2a.defineConstraints(width: 1000) - hstack2a.distribution = .fillEqually - hstack2a.axis = .horizontal - hstack2a.alignment = .top + self.label21.text = "Buy-in distribution".uppercased() + self.label22.text = "First prizes distribution".uppercased() + self.label23.text = "Prizepool distribution".uppercased() - let buyinDistribPie = PieChart(frame: CGRect.zero) + let pieChartFrame = CGRect(x: 0, y: 0, width: 500, height: 500) + let buyinDistribPie = PieChart(frame: pieChartFrame) buyinDistribPie.data = generator.tournamentBuyinDistribution.pieChartData - buyinDistribPie.defineConstraints(height: 300) - buyinDistribPie.notifyDataSetChanged() - - let firstPrizeDistributionPie = PieChart(frame: CGRect.zero) + self.container21.addSubview(buyinDistribPie) + + let firstPrizeDistributionPie = PieChart(frame: pieChartFrame) firstPrizeDistributionPie.data = generator.firstPrizeDistribution.pieChartData - firstPrizeDistributionPie.defineConstraints(height: 300) + self.container22.addSubview(firstPrizeDistributionPie) - let prizepoolDistribPie = PieChart(frame: CGRect.zero) + let prizepoolDistribPie = PieChart(frame: pieChartFrame) prizepoolDistribPie.data = generator.tournamentPrizepoolDistribution.pieChartData - prizepoolDistribPie.defineConstraints(height: 400) - - let hstack2: UIStackView = UIStackView(arrangedSubviews: [buyinDistribPie, firstPrizeDistributionPie, prizepoolDistribPie]) - hstack2.defineConstraints(width: 1000, height: 350.0) - hstack2.distribution = .fillEqually - hstack2.axis = .horizontal - hstack2.alignment = .top - - let mainTitle = UILabel() - mainTitle.textColor = UIColor.white - mainTitle.font = UIFont.boldSystemFont(ofSize: 64.0) - mainTitle.textAlignment = .center - mainTitle.text = "2019 WSOP" - - let vstack: UIStackView = UIStackView(arrangedSubviews: [mainTitle, hstack1, hstack2a, hstack2]) - vstack.axis = .vertical - vstack.distribution = .equalCentering - vstack.alignment = .center - vstack.spacing = 10.0 - self.view.addSubview(vstack) + self.container23.addSubview(prizepoolDistribPie) + + ///// + + self.label31.text = "Events by prizepool".uppercased() + self.label32.text = "Events by entries".uppercased() + + self.tableView31.setData(data: generator.tourniesByPrizepool) + self.tableView32.setData(data: generator.tourniesByEntries) - vstack.translatesAutoresizingMaskIntoConstraints = false - vstack.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16.0).isActive = true - vstack.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -16.0).isActive = true - vstack.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 16.0).isActive = true + ///// + + self.label41.text = "USA vs World bracelets".uppercased() + self.label42.text = "Holdem vs exotic games".uppercased() + + let USABraceletsDistribPie = PieChart(frame: pieChartFrame) + USABraceletsDistribPie.data = generator.USAvsWorldWins.pieChartData + self.container41.addSubview(USABraceletsDistribPie) + + let holdemDistributionPie = PieChart(frame: pieChartFrame) + holdemDistributionPie.data = generator.holdemTournamentsDistribution.pieChartData + self.container42.addSubview(holdemDistributionPie) + + self.label51.text = "Average Event".uppercased() + let ds = generator.averageEvent.first + self.tableView51.dataSource = ds + self.tableView51.delegate = ds } } - -//class InfographyView : UIView { -// -// var references: [UITableViewDataSource] = [] -// -// init(frame: CGRect, generator: ReportGenerator) { -// super.init(frame: frame) -// self.backgroundColor = UIColor.lightGray -// -// let table1 = TableView(data: generator.biggestWinners, frame: CGRect.zero, style: .grouped) -// table1.defineConstraints(width: 500, height: 500) -// -// let table2 = TableView(data: generator.mostWins, frame: CGRect.zero, style: .grouped) -// table2.defineConstraints(width: 500, height: 500) -// -// let pieChart = PieChartView(frame: CGRect.zero) -// pieChart.data = generator.tournamentBuyinDistribution.pieChartData -// pieChart.defineConstraints(width: 300, height: 300) -// -// let hstack1: UIStackView = UIStackView(arrangedSubviews: [table1, table2]) -// hstack1.defineConstraints(width: 1000, height: 500) -// hstack1.distribution = .fill -// hstack1.axis = .horizontal -// hstack1.alignment = .top -// hstack1.backgroundColor = UIColor.red -// -// let hstack2: UIStackView = UIStackView(arrangedSubviews: [pieChart]) -// hstack2.defineConstraints(width: 1000, height: 300) -// hstack2.distribution = .fill -// hstack2.axis = .horizontal -// hstack2.alignment = .top -// hstack2.backgroundColor = UIColor.green -// -// let vstack: UIStackView = UIStackView(arrangedSubviews: [hstack1, hstack2]) -// vstack.axis = .vertical -// vstack.distribution = .fill -// vstack.alignment = .leading -// vstack.backgroundColor = UIColor.blue -// self.addSubview(vstack) -// self.addMaxConstraints(view: vstack) -// -// } -// -// required init?(coder aDecoder: NSCoder) { -// fatalError("init(coder:) has not been implemented") -// } -// -//} diff --git a/TournamentStats/UI/reports/InfographyView.xib b/TournamentStats/UI/reports/InfographyView.xib new file mode 100644 index 0000000..deb036f --- /dev/null +++ b/TournamentStats/UI/reports/InfographyView.xib @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TournamentStats/UI/reports/InfographyViewController.swift b/TournamentStats/UI/reports/InfographyViewController.swift new file mode 100644 index 0000000..b9d81c5 --- /dev/null +++ b/TournamentStats/UI/reports/InfographyViewController.swift @@ -0,0 +1,192 @@ +// +// InfographyView.swift +// TournamentStats +// +// Created by Laurent Morvillier on 05/08/2019. +// Copyright © 2019 Stax River. All rights reserved. +// + +import Foundation +import UIKit +import Charts + +class InfographyViewController : UIViewController { + + var generator: ReportGenerator? + + override func viewDidLayoutSubviews() { + + super.viewDidLayoutSubviews() + + let gradient: CAGradientLayer = CAGradientLayer() + + let startColor = UIColor(red: 23/255, green: 72/255, blue: 61/255, alpha: 1) + let endColor = UIColor(red: 47/255, green: 149/255, blue: 126/255, alpha: 1) + + gradient.colors = [startColor.cgColor, endColor.cgColor] + gradient.locations = [0.2 , 1.0] + gradient.startPoint = CGPoint(x: 0.0, y: 0.0) + gradient.endPoint = CGPoint(x: 1.0, y: 1.0) + gradient.frame = self.view.bounds + + self.view.layer.insertSublayer(gradient, at: 0) + + } + + override func viewDidLoad() { + + let totalWidth: CGFloat = 1500.0 + let defaultSpacing: CGFloat = 8.0 + + guard let generator = self.generator else { + return + } + + let mainTitle = UILabel() + mainTitle.textColor = UIColor.white + mainTitle.font = UIFont.boldSystemFont(ofSize: 64.0) + mainTitle.textAlignment = .center + mainTitle.text = "2019 WSOP" + +// let table1 = TableView(data: generator.biggestWinners, frame: CGRect.zero, style: .grouped) +// table1.defineConstraints(width: 500 - defaultSpacing / 3, height: 500) +// +// let table2 = TableView(data: generator.mostWins, frame: CGRect.zero, style: .grouped) +// table2.defineConstraints(width: 500 - defaultSpacing / 3, height: 500) +// +// let table3 = TableView(data: generator.averageCash, frame: CGRect.zero, style: .grouped) +// table3.defineConstraints(width: 500 - defaultSpacing / 3, height: 500) +// +// let hstack1: UIStackView = UIStackView(arrangedSubviews: [table1, table2, table3]) +// hstack1.defineConstraints(width: totalWidth, height: 300.0) +// hstack1.distribution = .equalSpacing +// hstack1.spacing = 8.0 +// hstack1.axis = .horizontal +// hstack1.alignment = .top +// +// ///// +// +// let title1 = TitleLabel(frame: CGRect.zero, text: "Buy-in distribution") +// let title2 = TitleLabel(frame: CGRect.zero, text: "First prizes distribution") +// let title3 = TitleLabel(frame: CGRect.zero, text: "Prizepool distribution") +// +// let hstack2a: UIStackView = UIStackView(arrangedSubviews: [title1, title2, title3]) +// hstack2a.defineConstraints(width: totalWidth) +// hstack2a.distribution = .fillEqually +// hstack2a.axis = .horizontal +// hstack2a.alignment = .top +// +// ///// +// +// let buyinDistribPie = PieChart(frame: CGRect.zero) +// buyinDistribPie.data = generator.tournamentBuyinDistribution.pieChartData +// buyinDistribPie.defineConstraints(height: 300) +// buyinDistribPie.notifyDataSetChanged() +// +// let firstPrizeDistributionPie = PieChart(frame: CGRect.zero) +// firstPrizeDistributionPie.data = generator.firstPrizeDistribution.pieChartData +// firstPrizeDistributionPie.defineConstraints(height: 300) +// +// let prizepoolDistribPie = PieChart(frame: CGRect.zero) +// prizepoolDistribPie.data = generator.tournamentPrizepoolDistribution.pieChartData +// prizepoolDistribPie.defineConstraints(height: 400) +// +// let hstack2: UIStackView = UIStackView(arrangedSubviews: [buyinDistribPie, firstPrizeDistributionPie, prizepoolDistribPie]) +// hstack2.defineConstraints(width: totalWidth, height: 350.0) +// hstack2.distribution = .fillEqually +// hstack2.axis = .horizontal +// hstack2.alignment = .top +// +// +// ///// +// +// let title31 = TitleLabel(frame: CGRect.zero, text: "Events by prizepool") +// let title32 = TitleLabel(frame: CGRect.zero, text: "Events by entries") +// +// let hstack3a: UIStackView = UIStackView(arrangedSubviews: [title31, title32]) +// hstack3a.defineConstraints(width: totalWidth) +// hstack3a.distribution = .fillEqually +// hstack3a.axis = .horizontal +// hstack3a.alignment = .top +// +// ///// +// +// let table31 = TableView(data: generator.tourniesByPrizepool, frame: CGRect.zero, style: .grouped) +// table31.defineConstraints(width: 750, height: 500) +// +// let table32 = TableView(data: generator.tourniesByEntries, frame: CGRect.zero, style: .grouped) +// table32.defineConstraints(width: 750, height: 500) +// +// let hstack3: UIStackView = UIStackView(arrangedSubviews: [table31, table32]) +// hstack3.defineConstraints(width: totalWidth, height: 300.0) +// hstack3.distribution = .equalSpacing +// hstack3.spacing = 8.0 +// hstack3.axis = .horizontal +// hstack3.alignment = .top + + ///// + + let vstack: UIStackView = UIStackView(arrangedSubviews: [mainTitle]) +// let vstack: UIStackView = UIStackView(arrangedSubviews: [mainTitle, hstack1, hstack2a, hstack2, hstack3a, hstack3]) + vstack.axis = .vertical + vstack.distribution = .equalCentering + vstack.alignment = .center + vstack.spacing = 10.0 + self.view.addSubview(vstack) + + vstack.translatesAutoresizingMaskIntoConstraints = false + vstack.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16.0).isActive = true + vstack.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -16.0).isActive = true + vstack.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 16.0).isActive = true + + } + +} + +//class InfographyView : UIView { +// +// var references: [UITableViewDataSource] = [] +// +// init(frame: CGRect, generator: ReportGenerator) { +// super.init(frame: frame) +// self.backgroundColor = UIColor.lightGray +// +// let table1 = TableView(data: generator.biggestWinners, frame: CGRect.zero, style: .grouped) +// table1.defineConstraints(width: 500, height: 500) +// +// let table2 = TableView(data: generator.mostWins, frame: CGRect.zero, style: .grouped) +// table2.defineConstraints(width: 500, height: 500) +// +// let pieChart = PieChartView(frame: CGRect.zero) +// pieChart.data = generator.tournamentBuyinDistribution.pieChartData +// pieChart.defineConstraints(width: 300, height: 300) +// +// let hstack1: UIStackView = UIStackView(arrangedSubviews: [table1, table2]) +// hstack1.defineConstraints(width: 1000, height: 500) +// hstack1.distribution = .fill +// hstack1.axis = .horizontal +// hstack1.alignment = .top +// hstack1.backgroundColor = UIColor.red +// +// let hstack2: UIStackView = UIStackView(arrangedSubviews: [pieChart]) +// hstack2.defineConstraints(width: 1000, height: 300) +// hstack2.distribution = .fill +// hstack2.axis = .horizontal +// hstack2.alignment = .top +// hstack2.backgroundColor = UIColor.green +// +// let vstack: UIStackView = UIStackView(arrangedSubviews: [hstack1, hstack2]) +// vstack.axis = .vertical +// vstack.distribution = .fill +// vstack.alignment = .leading +// vstack.backgroundColor = UIColor.blue +// self.addSubview(vstack) +// self.addMaxConstraints(view: vstack) +// +// } +// +// required init?(coder aDecoder: NSCoder) { +// fatalError("init(coder:) has not been implemented") +// } +// +//} diff --git a/TournamentStats/report/Queries.swift b/TournamentStats/report/Queries.swift index 510a5ef..58d039f 100644 --- a/TournamentStats/report/Queries.swift +++ b/TournamentStats/report/Queries.swift @@ -28,7 +28,7 @@ class Queries { static func averageCash(realm: Realm) -> [CumulatedResults] { - let players = realm.objects(Player.self).filter(NSPredicate(format: "results.@count > 4")) + let players = realm.objects(Player.self).filter(NSPredicate(format: "results.@count > 6")) var crArray: [CumulatedResults] = [] for player in players { @@ -196,14 +196,17 @@ class Queries { let tournaments: Results = realm.objects(Tournament.self) - let low = DistributionCounter(name: "Low (<$2,000)") + let verylow = DistributionCounter(name: "Very Low (<$1,000)") + let low = DistributionCounter(name: "Low ($1,000 - $1,999)") let medium = DistributionCounter(name: "Medium ($2,000 - $5,000)") let high = DistributionCounter(name: "High (> $5,000)") - let counters: [DistributionCounter] = [low, medium, high] + let counters: [DistributionCounter] = [verylow, low, medium, high] tournaments.forEach { tournament in switch tournament.buyin { - case 0..<2000: + case 0..<1000: + verylow.increment() + case 1000..<2000: low.increment() case 2000...5000: medium.increment() diff --git a/TournamentStats/report/ReportGenerator.swift b/TournamentStats/report/ReportGenerator.swift index 229a277..0b8f986 100644 --- a/TournamentStats/report/ReportGenerator.swift +++ b/TournamentStats/report/ReportGenerator.swift @@ -14,16 +14,20 @@ class ReportGenerator { static private let winnersDirectoryName: String = "reports/winners" - func go() { + func go(importData: Bool) { - let realm = try! Realm() - try! realm.write { - realm.deleteAll() + if (importData) { + + let realm = try! Realm() + try! realm.write { + realm.deleteAll() + } + + Seed.createTournaments() + RowImporter.start() } - Seed.createTournaments() - RowImporter.start() - self.create() + self.generateReports() self.writeHTML() } @@ -52,6 +56,7 @@ class ReportGenerator { var tourniesByEntries: [TournamentRepresentable] = [] var tourniesByPrizepool: [TournamentRepresentable] = [] var winsByCountry: [CountryCounter] = [] + var USAvsWorldWins: [CountryCounter] = [] var cashesByCountry: [CountryCounter] = [] var averageEvent: [TournamentStats] = [] var notablesMostCashes: [CumulatedResults] = [] @@ -61,7 +66,7 @@ class ReportGenerator { var firstPrizeDistribution: [DistributionCounter] = [] var holdemTournamentsDistribution: [DistributionCounter] = [] - func create() { + func generateReports() { self.createDirectories() @@ -74,6 +79,7 @@ class ReportGenerator { self.tourniesByEntries = Queries.sortedEvents(realm: realm, fieldName: "entries", ascending: false) self.tourniesByPrizepool = Queries.sortedEvents(realm: realm, fieldName: "prizepool", ascending: false) self.winsByCountry = Queries.winsByCountry(realm: realm) + self.USAvsWorldWins = CountryCounter.aggregate(table: self.winsByCountry, param: "United States") self.cashesByCountry = Queries.cashesByCountry(realm: realm) self.averageEvent = Queries.averageEvent(realm: realm) self.notablesMostCashes = Queries.mostCashes(realm: realm, notable: true) diff --git a/TournamentStats/report/structures/CountryCounter.swift b/TournamentStats/report/structures/CountryCounter.swift index a5fa464..1af3820 100644 --- a/TournamentStats/report/structures/CountryCounter.swift +++ b/TournamentStats/report/structures/CountryCounter.swift @@ -7,8 +7,23 @@ // import Foundation +import Charts -class CountryCounter : HTMLRepresentable { +final class CountryCounter : HTMLRepresentable, Aggregeable { + + static func aggregate(table: [CountryCounter], param: String) -> [CountryCounter] { + + if let indexOfParam = table.firstIndex(where: { $0.country == param }) { + let paramCounter = table[indexOfParam] + var copy = table + copy.remove(at: indexOfParam) + let count = copy.reduce(0) { $0 + $1.counter } + return [paramCounter, CountryCounter(country: "Others", counter: count)] + } + + let count = table.reduce(0) { $0 + $1.counter } + return [CountryCounter(country: "All", counter: count)] + } var country: String var counter: Int @@ -41,6 +56,10 @@ class CountryCounter : HTMLRepresentable { return strings } + var pieChartDataEntry: PieChartDataEntry { + return PieChartDataEntry(value: Double(self.counter), label: self.country) + } + // static func htmlHeaders() -> String { // var strings: [String] = [] // strings.append("Country") diff --git a/TournamentStats/report/structures/CumulatedResults.swift b/TournamentStats/report/structures/CumulatedResults.swift index 161b2e0..f4d825d 100644 --- a/TournamentStats/report/structures/CumulatedResults.swift +++ b/TournamentStats/report/structures/CumulatedResults.swift @@ -38,8 +38,8 @@ class CumulatedResults : HTMLRepresentable, ColumnRepresentable { static func columnDescriptors() -> [ColumnDescriptor] { return [ColumnDescriptor(header: "Name", number: false, widthWeight: 2.0), - ColumnDescriptor(header: "Total Earnings", number: true, widthWeight: 1.0), - ColumnDescriptor(header: "Cashes", number: true, widthWeight: 1.0)] + ColumnDescriptor(header: "Total Earnings", number: true, widthWeight: 1.2), + ColumnDescriptor(header: "Cashes", number: true, widthWeight: 0.8)] } func cellValues() -> [String] { diff --git a/TournamentStats/report/structures/TournamentRepresentable.swift b/TournamentStats/report/structures/TournamentRepresentable.swift index 326857d..8b99c3b 100644 --- a/TournamentStats/report/structures/TournamentRepresentable.swift +++ b/TournamentStats/report/structures/TournamentRepresentable.swift @@ -13,11 +13,11 @@ struct TournamentRepresentable : HTMLRepresentable { var tournament: Tournament static func columnDescriptors() -> [ColumnDescriptor] { - return [ColumnDescriptor(header: "#", number: true, widthWeight: 0.2), - ColumnDescriptor(header: "Buy-in", number: true, widthWeight: 1.0), - ColumnDescriptor(header: "Event", number: false, widthWeight: 1.0), + return [ColumnDescriptor(header: "#", number: true, widthWeight: 0.3), + ColumnDescriptor(header: "Buy-in", number: true, widthWeight: 0.7), + ColumnDescriptor(header: "Event", number: false, widthWeight: 2.6), ColumnDescriptor(header: "Prizepool", number: true, widthWeight: 1.0), - ColumnDescriptor(header: "Entries", number: true, widthWeight: 1.0)] + ColumnDescriptor(header: "Entries", number: true, widthWeight: 0.7)] } func cellValues() -> [String] { diff --git a/TournamentStats/report/structures/TournamentStats.swift b/TournamentStats/report/structures/TournamentStats.swift index a8ab6f3..8eec804 100644 --- a/TournamentStats/report/structures/TournamentStats.swift +++ b/TournamentStats/report/structures/TournamentStats.swift @@ -7,31 +7,42 @@ // import Foundation +import UIKit -struct TournamentStats : HTMLRepresentable { +class TournamentStats : NSObject, HTMLRepresentable, UITableViewDelegate, UITableViewDataSource { var entries: Double var buyin: Double var prizepool: Double var itmValue: Double - func cellValues() -> [String] { - return [] + init(entries: Double, buyin: Double, prizepool: Double, itmValue: Double) { + + self.entries = entries + self.buyin = buyin + self.prizepool = prizepool + self.itmValue = itmValue + + super.init() + } static func columnDescriptors() -> [ColumnDescriptor] { return [] } + func cellValues() -> [String] { + return [] + } + static func htmlHeaders() -> String { return "" } func html() -> String { - let formatter = NumberFormatter() var strings: [(String, String)] = [] - strings.append(("Entries", formatter.string(from: NSNumber(value: self.entries))!)) + strings.append(("Entries", NumberFormatter().string(from: NSNumber(value: self.entries))!)) strings.append(("Buy-in", Formatter.currency.string(from: NSNumber(value: self.buyin))!)) strings.append(("Prizepool", Formatter.currency.string(from: NSNumber(value: self.prizepool))!)) strings.append(("Earnings", Formatter.currency.string(from: NSNumber(value: self.itmValue))!)) @@ -47,4 +58,68 @@ struct TournamentStats : HTMLRepresentable { return all } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 4 + } + + fileprivate let FONTSIZE: CGFloat = 18.0 + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = UITableViewCell() + cell.backgroundColor = UIColor.clear + + var cells: (String, String) + switch indexPath.row { + case 0: + cells = ("Entries", NumberFormatter().string(from: NSNumber(value: self.entries))!) + case 1: + cells = ("Buy-in", Formatter.currency.string(from: NSNumber(value: self.buyin))!) + case 2: + cells = ("Prizepool", Formatter.currency.string(from: NSNumber(value: self.prizepool))!) + default: + cells = ("Earnings", Formatter.currency.string(from: NSNumber(value: self.itmValue))!) + } + + var leftAnchor = cell.contentView.leftAnchor + for i in 0..<2 { + + let labelContainer: UIView = UIView() + cell.contentView.addSubview(labelContainer) + labelContainer.translatesAutoresizingMaskIntoConstraints = false + labelContainer.topAnchor.constraint(equalTo: cell.contentView.topAnchor).isActive = true + labelContainer.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor).isActive = true + let leftPadding: CGFloat = (i == 0) ? 0.0 : 0.0 //16.0 + labelContainer.leftAnchor.constraint(equalTo: leftAnchor, constant: leftPadding).isActive = true + leftAnchor = labelContainer.rightAnchor + + labelContainer.widthAnchor.constraint(equalTo: cell.contentView.widthAnchor, multiplier: 0.5).isActive = true + + let label: UILabel = UILabel(frame: CGRect.zero) + label.textColor = UIColor.white + label.backgroundColor = UIColor.clear + label.text = (i == 0) ? cells.0 : cells.1 + label.font = (i == 0) ? UIFont.boldSystemFont(ofSize: FONTSIZE) : UIFont.systemFont(ofSize: FONTSIZE) + label.textAlignment = (i == 1) ? .right : .left + labelContainer.addSubview(label) + + label.translatesAutoresizingMaskIntoConstraints = false + label.topAnchor.constraint(equalTo: labelContainer.topAnchor).isActive = true + label.bottomAnchor.constraint(equalTo: labelContainer.bottomAnchor).isActive = true + label.leftAnchor.constraint(equalTo: labelContainer.leftAnchor, constant: 8.0).isActive = true + label.rightAnchor.constraint(equalTo: labelContainer.rightAnchor, constant: -8.0).isActive = true + + } + return cell + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 36.0 + } + + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + return 0.1 + } + + } diff --git a/TournamentStats/utils/ColumnRepresentable.swift b/TournamentStats/utils/ColumnRepresentable.swift index 0fe82a7..e55dbd6 100644 --- a/TournamentStats/utils/ColumnRepresentable.swift +++ b/TournamentStats/utils/ColumnRepresentable.swift @@ -23,6 +23,8 @@ extension UIColor { return UIColor(red: 255/255, green: 125/255, blue: 196/255, alpha: 1) } + static let paColor3: UIColor = UIColor(red: 255/255, green: 155/255, blue: 50/255, alpha: 1) + } struct ColumnDescriptor { @@ -56,7 +58,12 @@ class PercentageFormatter : IValueFormatter { } func stringForValue(_ value: Double, entry: ChartDataEntry, dataSetIndex: Int, viewPortHandler: ViewPortHandler?) -> String { - return self.numberFormatter.string(from: NSNumber(value: value)) ?? "" + + if let formatted = self.numberFormatter.string(from: NSNumber(value: value)) { + return formatted + "%" + } else { + return "" + } } } @@ -69,8 +76,9 @@ extension Array where Element : ColumnRepresentable { dataEntries.append(representable.pieChartDataEntry) } let dataSet = PieChartDataSet(entries: dataEntries, label: "") - dataSet.entryLabelFont = UIFont.boldSystemFont(ofSize: 18.0) - dataSet.colors = [UIColor.paGreen, UIColor.paColor1, UIColor.paColor2] + dataSet.entryLabelFont = Fonts.pieChartEntries + dataSet.valueFont = Fonts.pieChartEntries + dataSet.colors = [UIColor.paGreen, UIColor.paColor1, UIColor.paColor2, UIColor.paColor3] dataSet.valueFormatter = PercentageFormatter() return PieChartData(dataSet: dataSet) } @@ -86,6 +94,18 @@ extension Array where Element : ColumnRepresentable { } +//extension Array where Element : Aggregeable { +// +// func aggregate(param: String) -> [Element] { +// return [] +// } +// +//} + +protocol Aggregeable { + static func aggregate(table: [Self], param: String) -> [Self] +} + protocol HTMLRepresentable : ColumnRepresentable { static func htmlHeaders() -> String func html() -> String