Caps-iOS/CapCollector/Data/Cap.swift
christophhagen 8892d04f62 Lots of updates
- Add unlock
- Update Sorting menu
- Prepare to load multiple tile images
- New logging
- Calculate thumbnails and colors before schowing grid
2020-06-18 22:55:51 +02:00

204 lines
4.7 KiB
Swift

//
// Cap.swift
// CapCollector
//
// Created by Christoph on 19.11.18.
// Copyright © 2018 CH. All rights reserved.
//
import Foundation
import UIKit
import CoreImage
import SQLite
struct Cap {
// MARK: - Static constants
static let sufficientImageCount = 10
static let imageWidth = 299 // New for XCode models, 227/229 for turicreate
static let imageSize = CGSize(width: imageWidth, height: imageWidth)
static let jpgQuality: CGFloat = 0.3
private static let mosaicColumns = 40
static let mosaicCellSize: CGFloat = 60
private static let mosaicRowHeight = mosaicCellSize * 0.866
private static let mosaicMargin = mosaicCellSize - mosaicRowHeight
// MARK: - Variables
/// The unique number of the cap
let id: Int
/// The name of the cap
let name: String
/// The name of the cap without special characters
let cleanName: String
/// The number of images existing for the cap
let count: Int
/// Indicate if the cap can be found by the recognition model
let matched: Bool
/// Indicate if the cap is present on the server
let uploaded: Bool
// MARK: Init
init(name: String, id: Int) {
self.id = id
self.count = 1
self.name = name
self.cleanName = ""
self.matched = false
self.uploaded = false
}
init(id: Int, name: String, count: Int) {
self.id = id
self.name = name
self.count = count
self.cleanName = name.clean
self.matched = false
self.uploaded = true
}
func renamed(to name: String) -> Cap {
Cap(from: self, renamed: name)
}
init(from cap: Cap, renamed newName: String) {
self.id = cap.id
self.count = cap.count
self.name = newName
self.cleanName = newName.clean
self.matched = cap.matched
self.uploaded = cap.uploaded
}
// MARK: SQLite
init(row: Row) {
self.id = row[Cap.columnId]
self.name = row[Cap.columnName]
self.count = row[Cap.columnCount]
self.cleanName = name.clean
self.matched = row[Cap.columnMatched]
self.uploaded = row[Cap.columnUploaded]
}
static let table = Table("data")
static var createQuery: String {
table.create(ifNotExists: true) { t in
t.column(columnId, primaryKey: true)
t.column(columnName)
t.column(columnCount)
t.column(columnMatched)
t.column(columnUploaded)
}
}
static let columnId = Expression<Int>("id")
static let columnName = Expression<String>("name")
static let columnCount = Expression<Int>("count")
static let columnMatched = Expression<Bool>("matched")
static let columnUploaded = Expression<Bool>("uploaded")
var insertQuery: Insert {
return Cap.table.insert(
Cap.columnId <- id,
Cap.columnName <- name,
Cap.columnCount <- count,
Cap.columnMatched <- matched,
Cap.columnUploaded <- uploaded)
}
// MARK: Display
func matchLabelText(match: Float?, appIsUnlocked: Bool) -> String {
if let match = match {
let percent = Int((match * 100).rounded())
return String(format: "%d %%", arguments: [percent])
}
guard matched else {
return "📵"
}
guard appIsUnlocked, !hasSufficientImages else {
return ""
}
return "⚠️"
}
func countLabelText(appIsUnlocked: Bool) -> String {
guard appIsUnlocked else {
return "\(id)"
}
guard count != 1 else {
return "\(id) (1 image)"
}
return "\(id) (\(count) images)"
}
// MARK: Images
var hasSufficientImages: Bool {
count >= Cap.sufficientImageCount
}
static func thumbnail(for image: UIImage) -> UIImage {
let len = GridViewController.len * 2
return image.resize(to: CGSize.init(width: len, height: len))
}
}
// MARK: - Protocol Hashable
extension Cap: Hashable {
static func == (lhs: Cap, rhs: Cap) -> Bool {
return lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
// MARK: - Protocol Logger
extension Cap: Logger { }
// MARK: - String extension
extension String {
var clean: String {
return lowercased().replacingOccurrences(of: "[^a-z0-9 ]", with: "", options: .regularExpression)
}
}
// MARK: - Int extension
private extension Int {
var isEven: Bool {
return self % 2 == 0
}
}