New Baseline -- Added basic Cloudkit support and changed to julian.steffen@me.com Apple Developer Account

This commit is contained in:
2021-05-14 17:42:35 +02:00
parent 6e548640ff
commit bcf3098bfe
63 changed files with 2378 additions and 1086 deletions

View File

@@ -0,0 +1,328 @@
//
// LibraryImport.swift
// Zockerhoehle
//
// Created by Julian-Steffen Müller on 20.11.19.
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
//
import Foundation
import UIKit
import CoreData
// MARK: - Library Import
class LibraryImport {
static func backupName(from filename : String) -> String? {
if filename.hasPrefix("libExp_") && filename.hasSuffix(".json") {
var backupName = filename
backupName.removeFirst("libExp_".count)
backupName.removeLast(".json".count)
return backupName
}else{
return .none
}
}
func backupFiles() -> [String] {
do {
let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
let filesInDocumentsDir = try FileManager.default.contentsOfDirectory(at: documentDirectory, includingPropertiesForKeys: .none, options: [])
let backupFiles = filesInDocumentsDir.filter{
$0.isFileURL
}.map {
$0.lastPathComponent
}.filter {
$0.hasPrefix("libExp_") && $0.hasSuffix(".json")
}.sorted(by: { $0 > $1 })
return backupFiles
}catch let error {
print(error)
print("LibraryImport::backupFiles - Error reading files from Document directory!")
}
return []
}
private func resetDatabase() {
print(GameSeriesStore().gameSeries)
CDManager.shared.viewContext.reset()
CDManager.shared.viewContext.performAndWait {
let deleteRequests =
[NSBatchDeleteRequest(fetchRequest: Game.fetchRequest()),
NSBatchDeleteRequest(fetchRequest: Accessory.fetchRequest()),
NSBatchDeleteRequest(fetchRequest: Console.fetchRequest()),
NSBatchDeleteRequest(fetchRequest: GameSeries.fetchRequest()),
NSBatchDeleteRequest(fetchRequest: Logo.fetchRequest()),
NSBatchDeleteRequest(fetchRequest: Cover.fetchRequest())]
let storeCoordinator = CDManager.shared.persistentContainer.persistentStoreCoordinator
do {
for deleteRequest in deleteRequests {
try storeCoordinator.execute(deleteRequest, with: CDManager.shared.viewContext)
}
}catch let error {
print(error)
print("LibraryImport::resetDatabase - Reset of Database failes!")
}
}
print(GameSeriesStore().gameSeries)
}
private func makeCDGame(from game: BHLGame, _ gameDict: inout [UUID : Game], _ cdConsole: Console) {
let cdGame = Game(context: CDManager.shared.viewContext)
gameDict[game.uuid] = cdGame
cdGame.name = game.name
cdGame.uuid = game.uuid
cdGame.inWishlist = game.inWishlist
cdGame.isFinished = game.isFinished
cdGame.lentTo = game.lentTo
//TODO: cdGame.createdAt = game.createdAt.
let cdCover = Cover(context: CDManager.shared.viewContext)
cdCover.image = game.cover
cdCover.game = cdGame
cdGame.cover = cdCover
cdConsole.addToGames(cdGame)
cdGame.console = cdConsole
print("Imported: \(cdGame.name) for \(cdConsole.name)")
}
private func makeCDAccessory(from accessory: BHLAccessory, _ accessoryDict: inout [UUID : Accessory], _ cdConsole: Console) {
let cdAccessory = Accessory(context: CDManager.shared.viewContext)
accessoryDict[accessory.uuid] = cdAccessory
cdAccessory.name = accessory.name
cdAccessory.uuid = accessory.uuid
cdAccessory.lentTo = accessory.lentTo
cdAccessory.color = accessory.color
cdAccessory.manufacturer = accessory.manufacturer
cdAccessory.inWishlist = accessory.inWishlist
cdConsole.addToAccessories(cdAccessory)
cdAccessory.console = cdConsole
}
private func makeCDConsole(from console : BHLConsole) -> Console {
let cdConsole = Console(context: CDManager.shared.viewContext)
cdConsole.name = console.name
cdConsole.uuid = console.uuid
cdConsole.manufacturer = console.manufacturer
cdConsole.shortName = console.shortName
cdConsole.generation = Int64(console.generation)
let cdLogo = Logo(context: CDManager.shared.viewContext)
cdLogo.image = console.logo
cdLogo.console = cdConsole
cdConsole.logo = cdLogo
return cdConsole
}
private func makeCDGameSeries(from gameSeries: BHLGameSeries, _ gameDict: inout [UUID : Game]) {
let cdGameSeries = GameSeries(context: CDManager.shared.viewContext)
cdGameSeries.name = gameSeries.name
let cdCover = GameSeriesCover(context: CDManager.shared.viewContext)
cdCover.image = gameSeries.cover
cdCover.gameSeries = cdGameSeries
cdGameSeries.cover = cdCover
for uuid in gameSeries.games {
if let game = gameDict[uuid] {
cdGameSeries.addToGames(game)
game.series = cdGameSeries
}
}
}
func importLIB(from filename: String) {
do {
let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
let file = documentDirectory.appendingPathComponent(filename)
if file.isFileURL {
let library = try JSONDecoder().decode(BHLibrary.self, from: Data(contentsOf: file))
resetDatabase()
var gameDict = [UUID:Game]()
var accessoryDict = [UUID:Accessory]()
for console in library.consoles {
let cdConsole = makeCDConsole(from: console)
print("CONSOLE: \(cdConsole.name) with \(console.games.count) games")
for uuid in console.games {
if let game = library.games.first(where: {$0.uuid == uuid}) {
makeCDGame(from: game, &gameDict, cdConsole)
}else{
print("LibraryImport::importLIB - Game with UUID '\(uuid)' not found")
}
}
for uuid in console.accessories {
if let accessory = library.accessories.first(where: {$0.uuid == uuid}) {
makeCDAccessory(from: accessory, &accessoryDict, cdConsole)
}else{
print("LibraryImport::importLIB - Accessory with UUID '\(uuid)' not found")
}
}
}
for gameSeries in library.gameSeries {
makeCDGameSeries(from: gameSeries, &gameDict)
}
}
}catch let error {
print(error)
print("LibraryImport::importLIB - Error while importing!")
}
}
}
// MARK: - BHLLibrary Classes
struct BHLibrary : Decodable {
let games : [BHLGame]
let consoles : [BHLConsole]
let gameSeries : [BHLGameSeries]
let accessories : [BHLAccessory]
}
struct BHLGame : Decodable {
let uuid : UUID
let name : String
let lentTo : String?
let isDigital : Bool
let inWishlist : Bool
let isFinished : Bool
let notes : String?
let createdAt : String?
let publisher : String?
let console : UUID?
let series : UUID?
let cover : UIImage?
enum CodingKeys: String, CodingKey {
case uuid
case name
case lentTo
case isDigital
case inWishlist
case isFinished
case notes
case createdAt
case publisher
case console
case series
case cover
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
uuid = try container.decode(UUID.self, forKey: .uuid)
name = try container.decode(String.self, forKey: .name)
lentTo = try container.decode(String?.self, forKey: .lentTo)
isDigital = try container.decode(Bool.self, forKey: .isDigital)
inWishlist = try container.decode(Bool.self, forKey: .inWishlist)
isFinished = try container.decode(Bool.self, forKey: .isFinished)
notes = try container.decode(String?.self, forKey: .notes)
createdAt = try container.decode(String?.self, forKey: .notes)
publisher = try container.decode(String?.self, forKey: .publisher)
console = try container.decode(UUID?.self, forKey: .console)
series = try container.decode(UUID?.self, forKey: .console)
if let coverBase64 = try container.decode(String?.self, forKey: .cover),
let coverData = Data(base64Encoded: coverBase64) {
cover = UIImage(data: coverData)
}else {
cover = .none
}
}
}
struct BHLAccessory : Decodable {
let uuid : UUID
let name : String
let color : String?
let manufacturer : String?
let inWishlist : Bool
let lentTo : String?
let console : UUID?
}
struct BHLGameSeries : Decodable {
let uuid : UUID
let name : String
let cover : UIImage?
let games : [UUID]
enum CodingKeys: String, CodingKey {
case uuid
case name
case cover
case games
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
uuid = try container.decode(UUID.self, forKey: .uuid)
name = try container.decode(String.self, forKey: .name)
games = try container.decode([UUID].self, forKey: .games)
if let coverBase64 = try container.decode(String?.self, forKey: .cover),
let coverData = Data(base64Encoded: coverBase64) {
cover = UIImage(data: coverData)
}else {
cover = .none
}
}
}
struct BHLConsole : Decodable {
let uuid : UUID
let name : String
let logo : UIImage?
let generation : Int
let manufacturer : String?
let shortName : String?
let accessories : [UUID]
let games : [UUID]
enum CodingKeys: String, CodingKey {
case uuid
case name
case logo
case generation
case manufacturer
case shortName
case accessories
case games
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
uuid = try container.decode(UUID.self, forKey: .uuid)
name = try container.decode(String.self, forKey: .name)
generation = try container.decode(Int.self, forKey: .generation)
manufacturer = try container.decode(String?.self, forKey: .manufacturer)
shortName = try container.decode(String?.self, forKey: .shortName)
accessories = try container.decode([UUID].self, forKey: .accessories)
games = try container.decode([UUID].self, forKey: .games)
if let coverBase64 = try container.decode(String?.self, forKey: .logo),
let coverData = Data(base64Encoded: coverBase64) {
logo = UIImage(data: coverData)
}else {
logo = .none
}
}
}