You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
PadelClub/PadelClub/Utils/SwiftParser.swift

160 lines
4.0 KiB

//
// SwiftParser.swift
// Padel Tournament
//
// Created by Razmig Sarkissian on 01/09/2023.
//
import Foundation
typealias LineIterator = AsyncLineSequence<URL.AsyncBytes>.AsyncIterator
struct Line: Identifiable {
let id: UUID = UUID()
let date: Date
let source: URL
let lineNumber: Int
let rawValue: String
let data: [String?]
// func updatePlayer(player: Player) {
// player.clubName = data[11]
// player.ligue = data[9]
// player.country = data[4]
// player.license = data[5]
// player.inscriptionRank = rank
// player.currentRank = rank
// player.tournamentCount = Int16(tournamentCount)
// player.points = points ?? 0
// player.codeClub = data[10]
// player.assimilation = assimilation
// }
var points: Double? {
if let pointsValue {
return Double(pointsValue.replacingOccurrences(of: ",", with: "."))
}
return nil
}
var pointsValue: String? {
data[6] ?? nil
}
var tournamentCountValue: String? {
data[8] ?? nil
}
var tournamentCount: Int64 {
if let tournamentCountValue {
return Int64(tournamentCountValue) ?? 0
}
return 0
}
var rankValue: String? {
data[1] ?? nil
}
var rank: Int {
if let rankValue {
return Int(rankValue) ?? 0
}
return 0
}
var assimilation: String? {
data[7]
}
}
struct CSVParser: AsyncSequence, AsyncIteratorProtocol {
typealias Element = Line
private let url: URL
private var lineIterator: LineIterator
private let seperator: Character
private let quoteCharacter: Character = "\""
private var lineNumber = 0
private let date: Date
let maleData: Bool
init(url: URL, seperator: Character = ";") {
self.date = url.dateFromPath
self.url = url
self.seperator = seperator
self.lineIterator = url.lines.makeAsyncIterator()
self.maleData = url.path().contains(SourceFile.messieurs.rawValue)
}
mutating func last() async throws -> Line? {
var lastString: String?
var currentString: String?
var isOver: Bool = false
while isOver == false {
lastString = currentString
currentString = try await lineIterator.next()
if currentString == nil {
isOver = true
}
}
if let lastString {
return Line(
date: date,
source: url,
lineNumber: lineNumber,
rawValue: lastString,
data: split(line: lastString))
}
return nil
}
mutating func next() async throws -> Line? {
if let string = try await lineIterator.next() {
defer { lineNumber += 1 }
return Line(
date: date,
source: url,
lineNumber: lineNumber,
rawValue: string,
data: split(line: string)
)
}
return nil
}
func makeAsyncIterator() -> CSVParser {
return self
}
private func split(line: String) -> [String?] {
var data = [String?]()
var inQuote = false
var currentString = ""
for character in line {
switch character {
case quoteCharacter:
inQuote = !inQuote
continue
case seperator:
if !inQuote {
data.append(currentString.isEmpty ? nil : currentString)
currentString = ""
continue
}
default:
break
}
currentString.append(character)
}
data.append(currentString.isEmpty ? nil : currentString)
return data
}
}