infography update

master
Laurent 6 years ago
parent d43eb40784
commit d2b6f539f1
  1. 24
      TournamentStats.xcodeproj/project.pbxproj
  2. 48
      TournamentStats/AppDelegate.swift
  3. 35
      TournamentStats/Base.lproj/Main.storyboard
  4. 4
      TournamentStats/UI/DataSourceWrapper.swift
  5. 22
      TournamentStats/UI/UIColor+Extensions.swift
  6. 10
      TournamentStats/UI/UIView+Extensions.swift
  7. 36
      TournamentStats/UI/components/PieChart.swift
  8. 34
      TournamentStats/UI/components/TableView.swift
  9. 26
      TournamentStats/UI/components/TitleLabel.swift
  10. 162
      TournamentStats/UI/reports/InfographyView.swift
  11. 5
      TournamentStats/report/structures/TournamentCounter.swift
  12. 67
      TournamentStats/utils/ColumnRepresentable.swift

@ -129,6 +129,10 @@
4DF7614D22A6CC0D004B0EF1 /* NotablePlayers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF7614C22A6CC0D004B0EF1 /* NotablePlayers.swift */; }; 4DF7614D22A6CC0D004B0EF1 /* NotablePlayers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF7614C22A6CC0D004B0EF1 /* NotablePlayers.swift */; };
4DF7614F22A6CF93004B0EF1 /* PlayerResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF7614E22A6CF93004B0EF1 /* PlayerResult.swift */; }; 4DF7614F22A6CF93004B0EF1 /* PlayerResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF7614E22A6CF93004B0EF1 /* PlayerResult.swift */; };
4DF7615122A7AECA004B0EF1 /* TournamentRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF7615022A7AECA004B0EF1 /* TournamentRepresentable.swift */; }; 4DF7615122A7AECA004B0EF1 /* TournamentRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF7615022A7AECA004B0EF1 /* TournamentRepresentable.swift */; };
4DF78DCE22F9AA3F00C02F73 /* PieChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF78DCD22F9AA3F00C02F73 /* PieChart.swift */; };
4DF78DD122F9AADF00C02F73 /* TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF78DD022F9AADF00C02F73 /* TableView.swift */; };
4DF78DD422F9C85C00C02F73 /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF78DD322F9C85C00C02F73 /* UIColor+Extensions.swift */; };
4DF78DD622F9CE7E00C02F73 /* TitleLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF78DD522F9CE7E00C02F73 /* TitleLabel.swift */; };
FFE9052C22BB7313006FEFA4 /* event34 in Resources */ = {isa = PBXBuildFile; fileRef = FFE9052922BB7312006FEFA4 /* event34 */; }; FFE9052C22BB7313006FEFA4 /* event34 in Resources */ = {isa = PBXBuildFile; fileRef = FFE9052922BB7312006FEFA4 /* event34 */; };
FFE9052D22BB7313006FEFA4 /* event41 in Resources */ = {isa = PBXBuildFile; fileRef = FFE9052A22BB7312006FEFA4 /* event41 */; }; FFE9052D22BB7313006FEFA4 /* event41 in Resources */ = {isa = PBXBuildFile; fileRef = FFE9052A22BB7312006FEFA4 /* event41 */; };
FFE9052E22BB7313006FEFA4 /* event40 in Resources */ = {isa = PBXBuildFile; fileRef = FFE9052B22BB7313006FEFA4 /* event40 */; }; FFE9052E22BB7313006FEFA4 /* event40 in Resources */ = {isa = PBXBuildFile; fileRef = FFE9052B22BB7313006FEFA4 /* event40 */; };
@ -271,6 +275,10 @@
4DF7614C22A6CC0D004B0EF1 /* NotablePlayers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotablePlayers.swift; sourceTree = "<group>"; }; 4DF7614C22A6CC0D004B0EF1 /* NotablePlayers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotablePlayers.swift; sourceTree = "<group>"; };
4DF7614E22A6CF93004B0EF1 /* PlayerResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerResult.swift; sourceTree = "<group>"; }; 4DF7614E22A6CF93004B0EF1 /* PlayerResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerResult.swift; sourceTree = "<group>"; };
4DF7615022A7AECA004B0EF1 /* TournamentRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentRepresentable.swift; sourceTree = "<group>"; }; 4DF7615022A7AECA004B0EF1 /* TournamentRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TournamentRepresentable.swift; sourceTree = "<group>"; };
4DF78DCD22F9AA3F00C02F73 /* PieChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PieChart.swift; sourceTree = "<group>"; };
4DF78DD022F9AADF00C02F73 /* TableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableView.swift; sourceTree = "<group>"; };
4DF78DD322F9C85C00C02F73 /* UIColor+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extensions.swift"; sourceTree = "<group>"; };
4DF78DD522F9CE7E00C02F73 /* TitleLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLabel.swift; sourceTree = "<group>"; };
FFE9052922BB7312006FEFA4 /* event34 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = event34; sourceTree = "<group>"; }; FFE9052922BB7312006FEFA4 /* event34 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = event34; sourceTree = "<group>"; };
FFE9052A22BB7312006FEFA4 /* event41 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = event41; sourceTree = "<group>"; }; FFE9052A22BB7312006FEFA4 /* event41 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = event41; sourceTree = "<group>"; };
FFE9052B22BB7313006FEFA4 /* event40 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = event40; sourceTree = "<group>"; }; FFE9052B22BB7313006FEFA4 /* event40 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = event40; sourceTree = "<group>"; };
@ -482,6 +490,7 @@
4DF760C022A561A8004B0EF1 /* UI */ = { 4DF760C022A561A8004B0EF1 /* UI */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
4DF78DCF22F9AA9300C02F73 /* components */,
4D97941222F827A5004A2D7F /* reports */, 4D97941222F827A5004A2D7F /* reports */,
4DF7608722A3FB96004B0EF1 /* DetailViewController.swift */, 4DF7608722A3FB96004B0EF1 /* DetailViewController.swift */,
4DF7608522A3FB96004B0EF1 /* MasterViewController.swift */, 4DF7608522A3FB96004B0EF1 /* MasterViewController.swift */,
@ -489,6 +498,7 @@
4D39B6F422F856EF00625E31 /* StackTableCell.xib */, 4D39B6F422F856EF00625E31 /* StackTableCell.xib */,
4D39B6F622F8573900625E31 /* StackTableCell.swift */, 4D39B6F622F8573900625E31 /* StackTableCell.swift */,
4D39B6F922F85C3400625E31 /* UIView+Extensions.swift */, 4D39B6F922F85C3400625E31 /* UIView+Extensions.swift */,
4DF78DD322F9C85C00C02F73 /* UIColor+Extensions.swift */,
); );
path = UI; path = UI;
sourceTree = "<group>"; sourceTree = "<group>";
@ -528,6 +538,16 @@
path = structures; path = structures;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
4DF78DCF22F9AA9300C02F73 /* components */ = {
isa = PBXGroup;
children = (
4DF78DCD22F9AA3F00C02F73 /* PieChart.swift */,
4DF78DD022F9AADF00C02F73 /* TableView.swift */,
4DF78DD522F9CE7E00C02F73 /* TitleLabel.swift */,
);
path = components;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -745,6 +765,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
4DF7614822A59660004B0EF1 /* ReportGenerator.swift in Sources */, 4DF7614822A59660004B0EF1 /* ReportGenerator.swift in Sources */,
4DF78DD422F9C85C00C02F73 /* UIColor+Extensions.swift in Sources */,
4DF760C222A561FF004B0EF1 /* ColumnRepresentable.swift in Sources */, 4DF760C222A561FF004B0EF1 /* ColumnRepresentable.swift in Sources */,
4DF760B022A47C74004B0EF1 /* RowImporter.swift in Sources */, 4DF760B022A47C74004B0EF1 /* RowImporter.swift in Sources */,
4DF7614A22A66675004B0EF1 /* TournamentWinner.swift in Sources */, 4DF7614A22A66675004B0EF1 /* TournamentWinner.swift in Sources */,
@ -752,6 +773,8 @@
4D39B6F122F829A500625E31 /* InfographyView.swift in Sources */, 4D39B6F122F829A500625E31 /* InfographyView.swift in Sources */,
4DF760B322A47CAE004B0EF1 /* Realm+Extensions.swift in Sources */, 4DF760B322A47CAE004B0EF1 /* Realm+Extensions.swift in Sources */,
4DF7608822A3FB96004B0EF1 /* DetailViewController.swift in Sources */, 4DF7608822A3FB96004B0EF1 /* DetailViewController.swift in Sources */,
4DF78DD122F9AADF00C02F73 /* TableView.swift in Sources */,
4DF78DD622F9CE7E00C02F73 /* TitleLabel.swift in Sources */,
4DF7615122A7AECA004B0EF1 /* TournamentRepresentable.swift in Sources */, 4DF7615122A7AECA004B0EF1 /* TournamentRepresentable.swift in Sources */,
4DF7608622A3FB96004B0EF1 /* MasterViewController.swift in Sources */, 4DF7608622A3FB96004B0EF1 /* MasterViewController.swift in Sources */,
4DF7608422A3FB96004B0EF1 /* AppDelegate.swift in Sources */, 4DF7608422A3FB96004B0EF1 /* AppDelegate.swift in Sources */,
@ -761,6 +784,7 @@
4D39B6FC22F8686300625E31 /* CumulatedWins.swift in Sources */, 4D39B6FC22F8686300625E31 /* CumulatedWins.swift in Sources */,
4DF7614F22A6CF93004B0EF1 /* PlayerResult.swift in Sources */, 4DF7614F22A6CF93004B0EF1 /* PlayerResult.swift in Sources */,
4D39B6F722F8573900625E31 /* StackTableCell.swift in Sources */, 4D39B6F722F8573900625E31 /* StackTableCell.swift in Sources */,
4DF78DCE22F9AA3F00C02F73 /* PieChart.swift in Sources */,
4DF7614622A59407004B0EF1 /* CumulatedResults.swift in Sources */, 4DF7614622A59407004B0EF1 /* CumulatedResults.swift in Sources */,
4D0F103922C4C1C4005F797A /* ChipCountParser.swift in Sources */, 4D0F103922C4C1C4005F797A /* ChipCountParser.swift in Sources */,
4D39B6FA22F85C3400625E31 /* UIView+Extensions.swift in Sources */, 4D39B6FA22F85C3400625E31 /* UIView+Extensions.swift in Sources */,

@ -12,10 +12,10 @@ import Realm
@UIApplicationMain @UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate { class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
var window: UIWindow? var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// UI stuff // UI stuff
@ -40,49 +40,53 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele
let d = Date().timeIntervalSince(s) let d = Date().timeIntervalSince(s)
print("reports created in \(d)s") print("reports created in \(d)s")
let infography = InfographyView(frame: CGRect(x: 0, y: 0, width: 1000, height: 1000), generator: generator) if let ivc = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "container") as? InfographyViewController {
ivc.generator = generator
if let imageData = infography.toImage()?.pngData() { ivc.view.frame = CGRect(x: 0, y: 0, width: 1000, height: 1000)
guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) as NSURL else { if let imageData = ivc.view.toImage()?.pngData() {
return false
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)
}
} }
do {
try imageData.write(to: directory.appendingPathComponent("infography.png")!)
} catch {
print(error.localizedDescription)
}
} }
return true return true
} }
func applicationWillResignActive(_ application: UIApplication) { func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
} }
func applicationDidEnterBackground(_ application: UIApplication) { func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
} }
func applicationWillEnterForeground(_ application: UIApplication) { func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
} }
func applicationDidBecomeActive(_ application: UIApplication) { func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
} }
func applicationWillTerminate(_ application: UIApplication) { func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
} }
// MARK: - Split view // MARK: - Split view
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool { func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {
guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false } guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false }
guard let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController else { return false } guard let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController else { return false }
@ -92,6 +96,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDele
} }
return false return false
} }
} }

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="H1p-Uh-vWS"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="H1p-Uh-vWS">
<device id="ipad9_7" orientation="portrait"> <device id="retina5_9" orientation="portrait">
<adaptation id="fullscreen"/> <adaptation id="fullscreen"/>
</device> </device>
<dependencies> <dependencies>
@ -15,7 +15,7 @@
<objects> <objects>
<navigationController title="Master" id="RMx-3f-FxP" sceneMemberID="viewController"> <navigationController title="Master" id="RMx-3f-FxP" sceneMemberID="viewController">
<navigationBar key="navigationBar" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="Pmd-2v-anx"> <navigationBar key="navigationBar" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="Pmd-2v-anx">
<rect key="frame" x="0.0" y="20" width="320" height="50"/> <rect key="frame" x="0.0" y="44" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
</navigationBar> </navigationBar>
<connections> <connections>
@ -31,11 +31,11 @@
<objects> <objects>
<viewController title="Detail" id="JEX-9P-axG" customClass="DetailViewController" customModule="TournamentStats" customModuleProvider="target" sceneMemberID="viewController"> <viewController title="Detail" id="JEX-9P-axG" customClass="DetailViewController" customModule="TournamentStats" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="svH-Pt-448"> <view key="view" contentMode="scaleToFill" id="svH-Pt-448">
<rect key="frame" x="0.0" y="0.0" width="768" height="1024"/> <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<label clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Detail view content goes here" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="0XM-y9-sOw"> <label clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Detail view content goes here" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="0XM-y9-sOw">
<rect key="frame" x="20" y="502" width="728" height="20.5"/> <rect key="frame" x="20" y="395.66666666666669" width="335" height="20.666666666666686"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/> <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
@ -79,26 +79,26 @@
<objects> <objects>
<tableViewController title="Master" clearsSelectionOnViewWillAppear="NO" id="7bK-jq-Zjz" customClass="MasterViewController" customModule="TournamentStats" customModuleProvider="target" sceneMemberID="viewController"> <tableViewController title="Master" clearsSelectionOnViewWillAppear="NO" id="7bK-jq-Zjz" customClass="MasterViewController" customModule="TournamentStats" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="r7i-6Z-zg0"> <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="r7i-6Z-zg0">
<rect key="frame" x="0.0" y="0.0" width="320" height="1024"/> <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes> <prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="Arm-wq-HPj" detailTextLabel="HdP-BR-LBd" style="IBUITableViewCellStyleValue1" id="WCw-Qf-5nD"> <tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="Arm-wq-HPj" detailTextLabel="HdP-BR-LBd" style="IBUITableViewCellStyleValue1" id="WCw-Qf-5nD">
<rect key="frame" x="0.0" y="28" width="320" height="44"/> <rect key="frame" x="0.0" y="28" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WCw-Qf-5nD" id="37f-cq-3Eg"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WCw-Qf-5nD" id="37f-cq-3Eg">
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/> <rect key="frame" x="0.0" y="0.0" width="375" height="43.666666666666664"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Arm-wq-HPj"> <label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Arm-wq-HPj">
<rect key="frame" x="16" y="12" width="33.5" height="20.5"/> <rect key="frame" x="16.000000000000004" y="11.999999999999998" width="33.333333333333336" height="20.333333333333332"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/> <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</label> </label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="HdP-BR-LBd"> <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="HdP-BR-LBd">
<rect key="frame" x="260" y="12" width="44" height="20.5"/> <rect key="frame" x="315" y="11.999999999999998" width="44" height="20.333333333333332"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/> <nil key="textColor"/>
@ -129,7 +129,7 @@
<objects> <objects>
<navigationController id="vC3-pB-5Vb" sceneMemberID="viewController"> <navigationController id="vC3-pB-5Vb" sceneMemberID="viewController">
<navigationBar key="navigationBar" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="DjV-YW-jjY"> <navigationBar key="navigationBar" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="DjV-YW-jjY">
<rect key="frame" x="0.0" y="20" width="768" height="50"/> <rect key="frame" x="0.0" y="44" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
</navigationBar> </navigationBar>
<connections> <connections>
@ -140,6 +140,21 @@
</objects> </objects>
<point key="canvasLocation" x="-45" y="129"/> <point key="canvasLocation" x="-45" y="129"/>
</scene> </scene>
<!--Infography View Controller-->
<scene sceneID="e9y-X1-vaX">
<objects>
<placeholder placeholderIdentifier="IBFirstResponder" id="yr4-1K-87y" userLabel="First Responder" sceneMemberID="firstResponder"/>
<viewController storyboardIdentifier="container" id="mxo-2c-VBS" customClass="InfographyViewController" customModule="TournamentStats" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Eky-dM-hcs">
<rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<viewLayoutGuide key="safeArea" id="sco-HF-vLG"/>
</view>
</viewController>
</objects>
<point key="canvasLocation" x="-879" y="638"/>
</scene>
</scenes> </scenes>
<inferredMetricsTieBreakers> <inferredMetricsTieBreakers>
<segue reference="6S0-TO-JiA"/> <segue reference="6S0-TO-JiA"/>

@ -42,8 +42,8 @@ class DataSourceWrapper<T : ColumnRepresentable> : NSObject, UITableViewDataSour
columns.forEach { value in columns.forEach { value in
let label: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: 50, height: 30)) let label: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: 50, height: 30))
label.textColor = UIColor.black label.textColor = UIColor.white
label.backgroundColor = UIColor.white label.backgroundColor = UIColor.clear
label.text = value label.text = value
label.font = font label.font = font
cell.stackView.addArrangedSubview(label) cell.stackView.addArrangedSubview(label)

@ -0,0 +1,22 @@
//
// UIColor+Extensions.swift
// TournamentStats
//
// Created by Laurent Morvillier on 06/08/2019.
// Copyright © 2019 Stax River. All rights reserved.
//
import Foundation
import UIKit
extension UIColor {
convenience init(red: CGFloat, green: CGFloat, blue: CGFloat) {
self.init(red: red/255.0, green: green/255.0, blue: blue/255.0, alpha: 1.0)
}
convenience init(r red: CGFloat, g green: CGFloat, b blue: CGFloat, a alpha: CGFloat) {
self.init(red: red/255.0, green: green/255.0, blue: blue/255.0, alpha: alpha)
}
}

@ -26,6 +26,16 @@ extension UIView {
// MARK: - Constraints // MARK: - Constraints
public func defineConstraints(width: CGFloat? = nil, height: CGFloat? = nil) {
self.translatesAutoresizingMaskIntoConstraints = false
if let width = width {
self.widthAnchor.constraint(equalToConstant: width).isActive = true
}
if let height = height {
self.heightAnchor.constraint(equalToConstant: height).isActive = true
}
}
@objc public func addMaxConstraints(view: UIView) { @objc public func addMaxConstraints(view: UIView) {
view.translatesAutoresizingMaskIntoConstraints = false view.translatesAutoresizingMaskIntoConstraints = false

@ -0,0 +1,36 @@
//
// PieChart.swift
// TournamentStats
//
// Created by Laurent Morvillier on 06/08/2019.
// Copyright © 2019 Stax River. All rights reserved.
//
import Foundation
import Charts
class PieChart : PieChartView {
override init(frame: CGRect) {
super.init(frame: frame)
self.holeColor = UIColor.clear
self.usePercentValuesEnabled = true
self.legend.textColor = UIColor.white
self.legend.font = UIFont.systemFont(ofSize: 16.0)
self.legend.orientation = .vertical
// self.legend.form = .square
// self.legend.neededHeight = 320.0
// self.legend.neededWidth = 300.0
self.legend.maxSizePercent = 0.2
self.legend.verticalAlignment = .center
// self.legend.horizontalAlignment = .left
self.holeRadiusPercent = 0.2
self.drawEntryLabelsEnabled = false
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

@ -0,0 +1,34 @@
//
// TableView.swift
// TournamentStats
//
// Created by Laurent Morvillier on 06/08/2019.
// Copyright © 2019 Stax River. All rights reserved.
//
import Foundation
import UIKit
class TableView<T : ColumnRepresentable> : UITableView {
var wrapper: DataSourceWrapper<T>
init(data: [T], frame: CGRect, style: UITableView.Style) {
self.wrapper = DataSourceWrapper(array: data)
super.init(frame: frame, style: style)
self.register(UINib(nibName: "StackTableCell", bundle: Bundle.main), forCellReuseIdentifier: "Cell")
self.backgroundColor = UIColor.clear
self.dataSource = self.wrapper
self.delegate = self.wrapper
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

@ -0,0 +1,26 @@
//
// TitleLabel.swift
// TournamentStats
//
// Created by Laurent Morvillier on 06/08/2019.
// Copyright © 2019 Stax River. All rights reserved.
//
import Foundation
import UIKit
class TitleLabel : UILabel {
init(frame: CGRect, text: String) {
super.init(frame: frame)
self.textColor = UIColor.white
self.text = text
self.textAlignment = .center
self.font = UIFont.boldSystemFont(ofSize: 16.0)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

@ -8,46 +8,144 @@
import Foundation import Foundation
import UIKit import UIKit
import Charts
class InfographyView : UIView { class InfographyViewController : UIViewController {
var references: [UITableViewDataSource] = [] var generator: ReportGenerator?
init(frame: CGRect, generator: ReportGenerator) { override func viewDidLayoutSubviews() {
super.init(frame: frame)
self.backgroundColor = UIColor.white super.viewDidLayoutSubviews()
let table1 = UITableView(frame: CGRect(x: 0, y: 0, width: 500, height: 500), style: .grouped) let gradient: CAGradientLayer = CAGradientLayer()
table1.register(UINib(nibName: "StackTableCell", bundle: Bundle.main), forCellReuseIdentifier: "Cell")
table1.backgroundColor = UIColor.clear let startColor = UIColor(red: 23/255, green: 72/255, blue: 61/255, alpha: 1)
let ds = DataSourceWrapper(array: generator.biggestWinners) let endColor = UIColor(red: 47/255, green: 149/255, blue: 126/255, alpha: 1)
table1.dataSource = ds
table1.delegate = ds gradient.colors = [startColor.cgColor, endColor.cgColor]
self.references.append(ds) gradient.locations = [0.2 , 1.0]
gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
let table2 = UITableView(frame: CGRect(x: 500, y: 0, width: 500, height: 500), style: .grouped) gradient.endPoint = CGPoint(x: 1.0, y: 1.0)
table2.register(UINib(nibName: "StackTableCell", bundle: Bundle.main), forCellReuseIdentifier: "Cell") gradient.frame = self.view.bounds
table2.backgroundColor = UIColor.clear
let ds2 = DataSourceWrapper(array: generator.mostWins) self.view.layer.insertSublayer(gradient, at: 0)
table2.dataSource = ds2
table2.delegate = ds2 }
self.references.append(ds2)
override func viewDidLoad() {
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]) let hstack1: UIStackView = UIStackView(arrangedSubviews: [table1, table2])
hstack1.distribution = .fill hstack1.defineConstraints(width: 1000, height: 300.0)
hstack1.backgroundColor = UIColor.green hstack1.distribution = .equalSpacing
hstack1.spacing = 8.0
hstack1.axis = .horizontal 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 vstack: UIStackView = UIStackView(arrangedSubviews: [hstack1]) let hstack2a: UIStackView = UIStackView(arrangedSubviews: [title1, title2, title3])
hstack1.backgroundColor = UIColor.blue hstack2a.defineConstraints(width: 1000)
vstack.axis = .vertical hstack2a.distribution = .fillEqually
self.addSubview(vstack) hstack2a.axis = .horizontal
self.addMaxConstraints(view: vstack) hstack2a.alignment = .top
} let buyinDistribPie = PieChart(frame: CGRect.zero)
buyinDistribPie.data = generator.tournamentBuyinDistribution.pieChartData
required init?(coder aDecoder: NSCoder) { buyinDistribPie.defineConstraints(height: 300)
fatalError("init(coder:) has not been implemented")
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: 300)
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)
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")
// }
//
//}

@ -7,6 +7,7 @@
// //
import Foundation import Foundation
import Charts
class DistributionCounter : HTMLRepresentable { class DistributionCounter : HTMLRepresentable {
@ -32,6 +33,10 @@ class DistributionCounter : HTMLRepresentable {
return strings return strings
} }
var pieChartDataEntry: PieChartDataEntry {
return PieChartDataEntry(value: Double(self.counter), label: name)
}
// static func htmlHeaders() -> String { // static func htmlHeaders() -> String {
// var strings: [String] = [] // var strings: [String] = []
// strings.append("Tournament") // strings.append("Tournament")

@ -7,10 +7,77 @@
// //
import Foundation import Foundation
import Charts
extension UIColor {
static var paGreen: UIColor {
return UIColor(red: 0/255, green: 255/255, blue: 196/255, alpha: 1)
}
static var paColor1: UIColor {
return UIColor(red: 125/255, green: 155/255, blue: 255/255, alpha: 1)
}
static var paColor2: UIColor {
return UIColor(red: 255/255, green: 125/255, blue: 196/255, alpha: 1)
}
}
public protocol ColumnRepresentable { public protocol ColumnRepresentable {
static func headers() -> [String] static func headers() -> [String]
func colums() -> [String] func colums() -> [String]
var chartDataEntry: ChartDataEntry { get }
var pieChartDataEntry: PieChartDataEntry { get }
}
extension ColumnRepresentable {
var chartDataEntry: ChartDataEntry {
return ChartDataEntry(x: 0, y: 0)
}
var pieChartDataEntry: PieChartDataEntry {
return PieChartDataEntry(value: 0.0)
}
}
class PercentageFormatter : IValueFormatter {
var numberFormatter: NumberFormatter = NumberFormatter()
init() {
self.numberFormatter.maximumFractionDigits = 0
}
func stringForValue(_ value: Double, entry: ChartDataEntry, dataSetIndex: Int, viewPortHandler: ViewPortHandler?) -> String {
return self.numberFormatter.string(from: NSNumber(value: value)) ?? ""
}
}
extension Array where Element : ColumnRepresentable {
var pieChartData: PieChartData {
var dataEntries: [ChartDataEntry] = []
self.forEach { representable in
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.valueFormatter = PercentageFormatter()
return PieChartData(dataSet: dataSet)
}
var chartData: ChartData {
var dataEntries: [ChartDataEntry] = []
self.forEach { representable in
dataEntries.append(representable.chartDataEntry)
}
let dataSet = ChartDataSet(entries: dataEntries)
return ChartData(dataSet: dataSet)
}
} }
public protocol HTMLRepresentable : ColumnRepresentable { public protocol HTMLRepresentable : ColumnRepresentable {

Loading…
Cancel
Save