// // CSVUtils.swift // TournamentStats // // Created by Laurent Morvillier on 03/06/2019. // Copyright © 2019 Stax River. All rights reserved. // 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) } } struct ColumnDescriptor { var header: String var number: Bool = false var widthWeight: CGFloat = 1.0 } protocol ColumnRepresentable { static func columnDescriptors() -> [ColumnDescriptor] func cellValues() -> [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) } } protocol HTMLRepresentable : ColumnRepresentable { static func htmlHeaders() -> String func html() -> String } extension HTMLRepresentable { static func htmlHeaders() -> String { let all = self.columnDescriptors().map { $0.header }.joined(separator: "") return "\(all)" } func html() -> String { let all = self.cellValues().joined(separator: "") return "\(all)" } } extension Array where Element : HTMLRepresentable { func writeHTML(fileName: String, limit: Int? = 10) { var html = "\n" html.append("") html.append(Element.htmlHeaders()) html.append("\n") let max = limit ?? Int.max for (index, rep) in self.enumerated() { html.append("\n") html.append(rep.html()) if index + 1 >= max { break } } html.append("\n
") do { try FileWriter.writeToDocumentDirectory(content: html, fileName: fileName) } catch { print(error) } } } extension Array where Element : CSVRepresentable { func writeCSV(file: String, limit: Int? = 10) { var string = Element.csvHeaders() let max = limit ?? Int.max for (index, rep) in self.enumerated() { string.append("/n") string.append(rep.csv()) if index >= max { break } } do { try FileWriter.writeToDocumentDirectory(content: string, fileName: file) } catch { print(error) } } } public protocol CSVRepresentable { static func csvHeaders() -> String func csv() -> String }