2019-03-15 13:19:19 +01:00
|
|
|
import Foundation
|
|
|
|
|
2020-05-16 11:21:55 +02:00
|
|
|
struct Cap {
|
2022-06-10 21:20:49 +02:00
|
|
|
|
2019-03-15 13:19:19 +01:00
|
|
|
/// The unique number of the cap
|
|
|
|
let id: Int
|
2022-06-10 21:20:49 +02:00
|
|
|
|
2019-03-15 13:19:19 +01:00
|
|
|
/// The name of the cap
|
2022-06-10 21:20:49 +02:00
|
|
|
var name: String
|
|
|
|
|
2020-05-16 11:21:55 +02:00
|
|
|
/// The name of the cap without special characters
|
2022-06-10 21:20:49 +02:00
|
|
|
var cleanName: String
|
|
|
|
|
2019-03-15 13:19:19 +01:00
|
|
|
/// The number of images existing for the cap
|
2022-06-10 21:20:49 +02:00
|
|
|
var imageCount: Int
|
|
|
|
|
|
|
|
/// The index of the main image for the cap
|
|
|
|
var mainImage: Int
|
|
|
|
|
|
|
|
/// The version of the first classifier capable of recognizing the cap
|
|
|
|
var classifierVersion: Int?
|
|
|
|
|
|
|
|
var color: Color?
|
|
|
|
|
|
|
|
/// The subpath to the main image on the server
|
|
|
|
var mainImagePath: String {
|
|
|
|
String(format: "images/%04d/%04d-%02d.jpg", id, id, mainImage)
|
2019-03-15 13:19:19 +01:00
|
|
|
}
|
2022-06-10 21:20:49 +02:00
|
|
|
|
2022-06-21 19:38:51 +02:00
|
|
|
var image: CapImage {
|
|
|
|
.init(cap: id, version: mainImage)
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:20:49 +02:00
|
|
|
/**
|
|
|
|
Create a new cap.
|
|
|
|
- Parameter id: The unique id of the cap
|
|
|
|
- Parameter name: The name associated with the cap
|
|
|
|
*/
|
|
|
|
init(id: Int, name: String, classifier: Int? = nil) {
|
2020-06-18 22:55:51 +02:00
|
|
|
self.id = id
|
|
|
|
self.name = name
|
|
|
|
self.cleanName = name.clean
|
2022-06-10 21:20:49 +02:00
|
|
|
self.imageCount = 1
|
|
|
|
self.mainImage = 0
|
|
|
|
self.classifierVersion = classifier
|
2020-06-18 22:55:51 +02:00
|
|
|
}
|
2022-06-10 21:20:49 +02:00
|
|
|
|
|
|
|
init(data: CapData) {
|
|
|
|
self.id = data.id
|
|
|
|
self.name = data.name
|
|
|
|
self.cleanName = data.name.clean
|
|
|
|
self.imageCount = data.count
|
|
|
|
self.mainImage = data.mainImage
|
|
|
|
self.classifierVersion = data.classifierVersion
|
2020-06-18 22:55:51 +02:00
|
|
|
}
|
2022-06-11 11:27:56 +02:00
|
|
|
|
|
|
|
var data: CapData {
|
|
|
|
.init(id: id,
|
|
|
|
name: name,
|
|
|
|
count: imageCount,
|
|
|
|
mainImage: mainImage,
|
|
|
|
classifierVersion: classifierVersion,
|
|
|
|
color: color)
|
|
|
|
}
|
2020-06-18 22:55:51 +02:00
|
|
|
|
2022-06-10 21:20:49 +02:00
|
|
|
mutating func update(with data: CapData) {
|
|
|
|
self.name = data.name
|
|
|
|
self.cleanName = data.name.clean
|
|
|
|
self.imageCount = data.count
|
|
|
|
self.mainImage = data.mainImage
|
|
|
|
self.classifierVersion = data.classifierVersion
|
2020-06-18 22:55:51 +02:00
|
|
|
}
|
2022-06-10 21:20:49 +02:00
|
|
|
|
|
|
|
static func ==(lhs: Cap, rhs: CapData) -> Bool {
|
|
|
|
lhs.id == rhs.id &&
|
|
|
|
lhs.name == rhs.name &&
|
|
|
|
lhs.imageCount == rhs.count &&
|
|
|
|
lhs.mainImage == rhs.mainImage &&
|
|
|
|
lhs.classifierVersion == rhs.classifierVersion
|
2020-06-18 22:55:51 +02:00
|
|
|
}
|
2022-06-10 21:20:49 +02:00
|
|
|
|
|
|
|
static func !=(lhs: Cap, rhs: CapData) -> Bool {
|
|
|
|
!(lhs == rhs)
|
2019-07-17 11:10:07 +02:00
|
|
|
}
|
2022-06-10 21:20:49 +02:00
|
|
|
|
|
|
|
func classifiable(by classifierVersion: Int?) -> Bool {
|
|
|
|
guard let version = classifierVersion else {
|
|
|
|
return false
|
2020-06-18 22:55:51 +02:00
|
|
|
}
|
2022-06-10 21:20:49 +02:00
|
|
|
guard let own = self.classifierVersion else {
|
|
|
|
return false
|
2019-03-15 13:19:19 +01:00
|
|
|
}
|
2022-06-10 21:20:49 +02:00
|
|
|
return version >= own
|
2019-03-15 13:19:19 +01:00
|
|
|
}
|
2022-06-10 21:20:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
extension Cap {
|
|
|
|
|
|
|
|
struct Color: Codable, Equatable {
|
|
|
|
|
|
|
|
let r: Int
|
|
|
|
|
|
|
|
let g: Int
|
|
|
|
|
|
|
|
let b: Int
|
2019-03-15 13:19:19 +01:00
|
|
|
}
|
2022-06-10 21:20:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Protocol Identifiable
|
2020-05-16 11:21:55 +02:00
|
|
|
|
2022-06-10 21:20:49 +02:00
|
|
|
extension Cap: Identifiable {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Protocol Comparable
|
|
|
|
|
|
|
|
extension Cap: Codable {
|
|
|
|
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
|
|
case id = "u"
|
|
|
|
case name = "n"
|
|
|
|
case cleanName = "c"
|
|
|
|
case imageCount = "i"
|
|
|
|
case mainImage = "m"
|
|
|
|
case classifierVersion = "v"
|
|
|
|
case color = "f"
|
2019-04-12 13:46:18 +02:00
|
|
|
}
|
2022-06-10 21:20:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Protocol Comparable
|
|
|
|
|
|
|
|
extension Cap: Comparable {
|
|
|
|
|
|
|
|
static func < (lhs: Cap, rhs: Cap) -> Bool {
|
|
|
|
lhs.id < rhs.id
|
2019-03-15 13:19:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:20:49 +02:00
|
|
|
// MARK: Protocol Equatable
|
|
|
|
|
|
|
|
extension Cap: Equatable {
|
2019-03-15 13:19:19 +01:00
|
|
|
|
|
|
|
static func == (lhs: Cap, rhs: Cap) -> Bool {
|
|
|
|
return lhs.id == rhs.id
|
|
|
|
}
|
2022-06-10 21:20:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Protocol Hashable
|
|
|
|
|
|
|
|
extension Cap: Hashable {
|
|
|
|
|
2019-03-15 13:19:19 +01:00
|
|
|
func hash(into hasher: inout Hasher) {
|
|
|
|
hasher.combine(id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:20:49 +02:00
|
|
|
// MARK: String extension
|
2019-03-15 13:19:19 +01:00
|
|
|
|
2022-06-10 21:20:49 +02:00
|
|
|
private extension String {
|
2019-03-15 13:19:19 +01:00
|
|
|
|
|
|
|
var clean: String {
|
|
|
|
return lowercased().replacingOccurrences(of: "[^a-z0-9 ]", with: "", options: .regularExpression)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:20:49 +02:00
|
|
|
// MARK: Int extension
|
2019-03-15 13:19:19 +01:00
|
|
|
|
|
|
|
private extension Int {
|
2022-06-10 21:20:49 +02:00
|
|
|
|
2019-03-15 13:19:19 +01:00
|
|
|
var isEven: Bool {
|
|
|
|
return self % 2 == 0
|
|
|
|
}
|
|
|
|
}
|