Allow adding of thumbnails, update grid
This commit is contained in:
parent
b91d196a37
commit
ba40cb0a17
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,6 +9,7 @@
|
|||||||
Package.resolved
|
Package.resolved
|
||||||
.swiftpm/
|
.swiftpm/
|
||||||
Public/images/
|
Public/images/
|
||||||
|
Public/thumbnails/
|
||||||
Public/classifier.version
|
Public/classifier.version
|
||||||
Public/classifier.mlmodel
|
Public/classifier.mlmodel
|
||||||
Public/caps.json
|
Public/caps.json
|
||||||
|
@ -8,6 +8,11 @@ final class CapServer: ServerOwner {
|
|||||||
|
|
||||||
private let imageFolder: URL
|
private let imageFolder: URL
|
||||||
|
|
||||||
|
private let thumbnailFolder: URL
|
||||||
|
|
||||||
|
/// The file where the cap count is stored for the grid webpage
|
||||||
|
private let gridCountFile: URL
|
||||||
|
|
||||||
/// The file where the database of caps is stored
|
/// The file where the database of caps is stored
|
||||||
private let dbFile: URL
|
private let dbFile: URL
|
||||||
|
|
||||||
@ -73,6 +78,8 @@ final class CapServer: ServerOwner {
|
|||||||
|
|
||||||
init(in folder: URL, writers: [String]) {
|
init(in folder: URL, writers: [String]) {
|
||||||
self.imageFolder = folder.appendingPathComponent("images")
|
self.imageFolder = folder.appendingPathComponent("images")
|
||||||
|
self.thumbnailFolder = folder.appendingPathComponent("thumbnails")
|
||||||
|
self.gridCountFile = folder.appendingPathComponent("count.js")
|
||||||
self.dbFile = folder.appendingPathComponent("caps.json")
|
self.dbFile = folder.appendingPathComponent("caps.json")
|
||||||
self.htmlFile = folder.appendingPathComponent("count.html")
|
self.htmlFile = folder.appendingPathComponent("count.html")
|
||||||
self.classifierVersionFile = folder.appendingPathComponent("classifier.version")
|
self.classifierVersionFile = folder.appendingPathComponent("classifier.version")
|
||||||
@ -217,6 +224,10 @@ final class CapServer: ServerOwner {
|
|||||||
func folder(of cap: Int) -> URL {
|
func folder(of cap: Int) -> URL {
|
||||||
imageFolder.appendingPathComponent(String(format: "%04d", cap))
|
imageFolder.appendingPathComponent(String(format: "%04d", cap))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func thumbnail(of cap: Int) -> URL {
|
||||||
|
thumbnailFolder.appendingPathComponent(String(format: "%04d.jpg", cap))
|
||||||
|
}
|
||||||
|
|
||||||
func file(of cap: Int, version: Int) -> URL {
|
func file(of cap: Int, version: Int) -> URL {
|
||||||
folder(of: cap).appendingPathComponent(String(format: "%04d-%02d.jpg", cap, version))
|
folder(of: cap).appendingPathComponent(String(format: "%04d-%02d.jpg", cap, version))
|
||||||
@ -384,6 +395,7 @@ final class CapServer: ServerOwner {
|
|||||||
cap.classifierVersion = nextClassifierVersion
|
cap.classifierVersion = nextClassifierVersion
|
||||||
caps[cap.id] = cap
|
caps[cap.id] = cap
|
||||||
saveCapCountHTML()
|
saveCapCountHTML()
|
||||||
|
updateGridCapCount()
|
||||||
log("Added cap \(cap.id) '\(cap.name)'")
|
log("Added cap \(cap.id) '\(cap.name)'")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,6 +438,29 @@ final class CapServer: ServerOwner {
|
|||||||
classifierVersion = version
|
classifierVersion = version
|
||||||
log("Updated classifier to version \(version)")
|
log("Updated classifier to version \(version)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getListOfMissingThumbnails() -> [Int] {
|
||||||
|
caps.keys.filter { !fm.fileExists(atPath: thumbnail(of: $0).path) }
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveThumbnail(_ data: Data, for cap: Int) {
|
||||||
|
let url = thumbnail(of: cap)
|
||||||
|
do {
|
||||||
|
try data.write(to: url)
|
||||||
|
} catch {
|
||||||
|
log("Failed to save thumbnail \(cap): \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateGridCapCount() {
|
||||||
|
do {
|
||||||
|
try "const numberOfCaps = \(capCount);"
|
||||||
|
.data(using: .utf8)!
|
||||||
|
.write(to: gridCountFile)
|
||||||
|
} catch {
|
||||||
|
log("Failed to save grid cap count: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: ServerOwner
|
// MARK: ServerOwner
|
||||||
|
|
||||||
|
@ -29,11 +29,8 @@ func routes(_ app: Application) {
|
|||||||
// Add or change a cap
|
// Add or change a cap
|
||||||
app.postCatching("cap") { request in
|
app.postCatching("cap") { request in
|
||||||
try authorize(request)
|
try authorize(request)
|
||||||
guard let buffer = request.body.data else {
|
let data = try request.getBodyData()
|
||||||
log("Invalid body data")
|
let cap = try decoder.decode(Cap.self, from: data)
|
||||||
throw CapError.invalidBody
|
|
||||||
}
|
|
||||||
let cap = try decoder.decode(Cap.self, from: buffer)
|
|
||||||
try server.addOrUpdate(cap)
|
try server.addOrUpdate(cap)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,11 +41,7 @@ func routes(_ app: Application) {
|
|||||||
log("Invalid parameter for cap")
|
log("Invalid parameter for cap")
|
||||||
throw Abort(.badRequest)
|
throw Abort(.badRequest)
|
||||||
}
|
}
|
||||||
guard let buffer = request.body.data else {
|
let data = try request.getBodyData()
|
||||||
log("Missing body data: \(request.body.description)")
|
|
||||||
throw CapError.invalidBody
|
|
||||||
}
|
|
||||||
let data = Data(buffer: buffer)
|
|
||||||
try server.save(image: data, for: cap)
|
try server.save(image: data, for: cap)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,11 +55,7 @@ func routes(_ app: Application) {
|
|||||||
guard version > server.classifierVersion else {
|
guard version > server.classifierVersion else {
|
||||||
throw Abort(.alreadyReported) // 208
|
throw Abort(.alreadyReported) // 208
|
||||||
}
|
}
|
||||||
guard let buffer = request.body.data else {
|
let data = try request.getBodyData()
|
||||||
log("Missing body data: \(request.body.description)")
|
|
||||||
throw CapError.invalidBody
|
|
||||||
}
|
|
||||||
let data = Data(buffer: buffer)
|
|
||||||
try server.save(classifier: data, version: version)
|
try server.save(classifier: data, version: version)
|
||||||
return .ok
|
return .ok
|
||||||
}
|
}
|
||||||
@ -83,16 +72,44 @@ func routes(_ app: Application) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try authorize(request)
|
try authorize(request)
|
||||||
guard let buffer = request.body.data else {
|
let body = try request.getStringBody()
|
||||||
log("Missing body data: \(request.body.description)")
|
|
||||||
throw CapError.invalidBody
|
server.updateTrainedClasses(content: body)
|
||||||
}
|
|
||||||
let data = Data(buffer: buffer)
|
|
||||||
guard let content = String(data: data, encoding: .utf8) else {
|
|
||||||
log("Invalid string body: \(request.body.description)")
|
|
||||||
throw CapError.invalidBody
|
|
||||||
}
|
|
||||||
server.updateTrainedClasses(content: content)
|
|
||||||
server.removeAllEntriesInImageChangeList(before: date)
|
server.removeAllEntriesInImageChangeList(before: date)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the list of missing thumbnails
|
||||||
|
app.get("thumbnails", "missing") { request in
|
||||||
|
let missingThumbnails = server.getListOfMissingThumbnails()
|
||||||
|
return missingThumbnails.map(String.init).joined(separator: ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
app.postCatching("thumbnails", ":cap") { request in
|
||||||
|
guard let cap = request.parameters.get("cap", as: Int.self) else {
|
||||||
|
log("Invalid cap parameter for thumbnail upload")
|
||||||
|
throw Abort(.badRequest)
|
||||||
|
}
|
||||||
|
let data = try request.getBodyData()
|
||||||
|
server.saveThumbnail(data, for: cap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension Request {
|
||||||
|
|
||||||
|
func getBodyData() throws -> Data {
|
||||||
|
guard let buffer = body.data else {
|
||||||
|
log("Missing body data")
|
||||||
|
throw CapError.invalidBody
|
||||||
|
}
|
||||||
|
return Data(buffer: buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStringBody() throws -> String {
|
||||||
|
let data = try getBodyData()
|
||||||
|
guard let content = String(data: data, encoding: .utf8) else {
|
||||||
|
log("Invalid string body")
|
||||||
|
throw CapError.invalidBody
|
||||||
|
}
|
||||||
|
return content
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user