Caps-iOS/CapCollector/Data/TileImage.swift

135 lines
3.6 KiB
Swift
Raw Normal View History

//
// TileImage.swift
// CapCollector
//
// Created by Christoph on 20.05.20.
// Copyright © 2020 CH. All rights reserved.
//
import Foundation
import SQLite
extension Database {
struct TileImage {
let name: String
let width: Int
/// The tiles of each cap, with the index being the tile, and the value being the cap id.
let caps: [Int]
var encodedCaps: Data {
caps.map(UInt16.init).withUnsafeBytes { (p) in
Data(buffer: p.bindMemory(to: UInt8.self))
}
}
init(name: String, width: Int, caps: [Int]) {
self.name = name
self.width = width
self.caps = caps
}
init(row: Row) {
self.name = row[TileImage.columnName]
self.width = row[TileImage.columnWidth]
self.caps = row[TileImage.columnCaps].withUnsafeBytes { p in
p.bindMemory(to: UInt16.self).map(Int.init)
}
}
var insertQuery: Insert {
TileImage.table.insert(
TileImage.columnName <- name,
TileImage.columnWidth <- width,
TileImage.columnCaps <- encodedCaps)
}
var updateQuery: Update {
TileImage.table.update(
TileImage.columnWidth <- width,
TileImage.columnCaps <- encodedCaps)
}
static let columnName = Expression<String>("name")
static let columnWidth = Expression<Int>("width")
static let columnCaps = Expression<Data>("caps")
static let table = Table("images")
static func named(_ name: String) -> Table {
table.filter(columnName == name)
}
static func exists(_ name: String) -> Table {
named(name).select(columnName)
}
static var createQuery: String {
table.create(ifNotExists: true) { t in
t.column(Cap.columnId, primaryKey: true)
t.column(columnName)
t.column(columnWidth)
t.column(columnCaps)
}
}
}
func save(tileImage: TileImage) -> Bool {
guard exists(tileImage.name) else {
return insert(tileImage)
}
return update(tileImage)
}
var tileImages: [TileImage] {
(try? db.prepare(TileImage.table).map(TileImage.init)) ?? []
}
func tileImage(named name: String) -> TileImage? {
do {
guard let row = try db.pluck(TileImage.named(name)) else {
return nil
}
return TileImage(row: row)
} catch {
log("Failed to get tile image \(name): \(error)")
return nil
}
}
private func exists(_ tileImage: String) -> Bool {
do {
return try db.pluck(TileImage.exists(tileImage)) != nil
} catch {
log("Failed to check tile image \(tileImage): \(error)")
return false
}
}
private func insert(_ tileImage: TileImage) -> Bool {
do {
try db.run(tileImage.insertQuery)
return true
} catch {
log("Failed to insert tile image \(tileImage): \(error)")
return false
}
}
private func update(_ tileImage: TileImage) -> Bool {
do {
try db.run(tileImage.updateQuery)
return true
} catch {
log("Failed to update tile image \(tileImage): \(error)")
return false
}
}
}