parent
63f4327e8c
commit
a60750ce97
@ -0,0 +1,102 @@ |
|||||||
|
// |
||||||
|
// Model+CSV.swift |
||||||
|
// LeCountdown |
||||||
|
// |
||||||
|
// Created by Laurent Morvillier on 29/11/2023. |
||||||
|
// |
||||||
|
|
||||||
|
import Foundation |
||||||
|
import CoreData |
||||||
|
|
||||||
|
protocol CSVField { |
||||||
|
associatedtype T: CSVRepresentable |
||||||
|
var header: String { get } |
||||||
|
} |
||||||
|
|
||||||
|
protocol CSVRepresentable: NSFetchRequestResult { |
||||||
|
|
||||||
|
associatedtype F: CSVField |
||||||
|
|
||||||
|
func toCSV() -> String |
||||||
|
|
||||||
|
static var fields: [F] { get } |
||||||
|
|
||||||
|
func value(field: F) -> String? |
||||||
|
} |
||||||
|
|
||||||
|
extension CSVRepresentable { |
||||||
|
|
||||||
|
static func toCSV() -> String { |
||||||
|
var csv: String = "" |
||||||
|
|
||||||
|
let context: NSManagedObjectContext = PersistenceController.shared.container.viewContext |
||||||
|
|
||||||
|
let request = NSFetchRequest<Self>(entityName: String(describing: self)) |
||||||
|
|
||||||
|
csv = self.fields.map { "\"\($0.header)\"" }.joined(separator: ",") |
||||||
|
csv.append("\n") |
||||||
|
|
||||||
|
do { |
||||||
|
let entities = try context.fetch(request) |
||||||
|
for entity in entities { |
||||||
|
let entityCSV = entity.toCSV() |
||||||
|
csv.append("\(entityCSV)\n") |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} catch { |
||||||
|
Logger.error(error) |
||||||
|
} |
||||||
|
|
||||||
|
return csv |
||||||
|
} |
||||||
|
|
||||||
|
func toCSV() -> String { |
||||||
|
let values: [String?] = Self.fields.map { field in |
||||||
|
self.value(field: field) |
||||||
|
} |
||||||
|
return values.map { "\"\($0 ?? "")\"" }.joined(separator: ",") |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
extension Record : CSVRepresentable { |
||||||
|
|
||||||
|
static var fields: [RecordCSVField] { |
||||||
|
return RecordCSVField.allCases |
||||||
|
} |
||||||
|
|
||||||
|
func value(field: RecordCSVField) -> String? { |
||||||
|
switch field { |
||||||
|
case .activity: |
||||||
|
return self.activity?.name |
||||||
|
case .start: |
||||||
|
return self.start?.formattedDateTime |
||||||
|
case .end: |
||||||
|
return self.end?.formattedDateTime |
||||||
|
case .cancelled: |
||||||
|
return self.cancelled.description |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
enum RecordCSVField: CSVField, CaseIterable { |
||||||
|
|
||||||
|
typealias T = Record |
||||||
|
|
||||||
|
case activity |
||||||
|
case start |
||||||
|
case end |
||||||
|
case cancelled |
||||||
|
|
||||||
|
var header: String { |
||||||
|
switch self { |
||||||
|
case .activity: return "Activity" |
||||||
|
case .start: return "Start" |
||||||
|
case .end: return "End" |
||||||
|
case .cancelled: return "Cancelled" |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,62 @@ |
|||||||
|
// |
||||||
|
// Patcher.swift |
||||||
|
// LeCountdown |
||||||
|
// |
||||||
|
// Created by Laurent Morvillier on 29/11/2023. |
||||||
|
// |
||||||
|
|
||||||
|
import Foundation |
||||||
|
import CoreData |
||||||
|
|
||||||
|
enum Patch: String, CaseIterable { |
||||||
|
case interval |
||||||
|
|
||||||
|
var key: String { |
||||||
|
return "patch." + self.rawValue |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class Patcher { |
||||||
|
|
||||||
|
static func patch() { |
||||||
|
|
||||||
|
let context = PersistenceController.shared.container.viewContext |
||||||
|
for patch in Patch.allCases { |
||||||
|
|
||||||
|
if true { |
||||||
|
Logger.log("PATCH!!!") |
||||||
|
// if !UserDefaults.standard.bool(forKey: patch.key) { |
||||||
|
|
||||||
|
do { |
||||||
|
switch patch { |
||||||
|
case .interval: |
||||||
|
try self._patchIntervals(context: context) |
||||||
|
} |
||||||
|
|
||||||
|
try context.save() |
||||||
|
UserDefaults.standard.set(true, forKey: patch.key) |
||||||
|
} catch { |
||||||
|
Logger.error(error) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
static fileprivate func _patchIntervals(context: NSManagedObjectContext) throws { |
||||||
|
|
||||||
|
let countdowns: [Countdown] = try context.fetch(Countdown.fetchRequest()) |
||||||
|
for countdown in countdowns { |
||||||
|
if let ranges = countdown.timeRanges, ranges.count == 0 { |
||||||
|
let range = TimeRange(context: context) |
||||||
|
range.duration = countdown.duration |
||||||
|
range.name = countdown.name |
||||||
|
range.order = 0 |
||||||
|
countdown.addToTimeRanges(range) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue