135 lines
3.6 KiB
Swift
135 lines
3.6 KiB
Swift
|
//
|
||
|
// 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
|
||
|
}
|
||
|
}
|
||
|
}
|