Updates GameMetadata + GamesDatabase to include release identifier
This commit is contained in:
parent
7695a800c6
commit
0c567de380
@ -8,9 +8,32 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
// Must be a class (not struct) so it can be used with Objective-C generics
|
// Must be an NSObject subclass so it can be used with RSTCellContentDataSource.
|
||||||
class GameMetadata
|
class GameMetadata: NSObject
|
||||||
{
|
{
|
||||||
var name: String?
|
let identifier: Int
|
||||||
var artworkURL: URL?
|
|
||||||
|
let name: String?
|
||||||
|
let artworkURL: URL?
|
||||||
|
|
||||||
|
init(identifier: Int, name: String?, artworkURL: URL?)
|
||||||
|
{
|
||||||
|
self.name = name
|
||||||
|
self.identifier = identifier
|
||||||
|
self.artworkURL = artworkURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension GameMetadata
|
||||||
|
{
|
||||||
|
override var hash: Int {
|
||||||
|
return self.identifier.hashValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override func isEqual(_ object: Any?) -> Bool
|
||||||
|
{
|
||||||
|
guard let metadata = object as? GameMetadata else { return false }
|
||||||
|
|
||||||
|
return self.identifier == metadata.identifier
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,11 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import SQLite
|
import SQLite
|
||||||
|
|
||||||
|
private extension UserDefaults
|
||||||
|
{
|
||||||
|
@NSManaged var previousGamesDatabaseVersion: Int
|
||||||
|
}
|
||||||
|
|
||||||
extension ExpressionType
|
extension ExpressionType
|
||||||
{
|
{
|
||||||
static var name: SQLite.Expression<String?> {
|
static var name: SQLite.Expression<String?> {
|
||||||
@ -19,13 +24,17 @@ extension ExpressionType
|
|||||||
return SQLite.Expression<String?>("releaseCoverFront")
|
return SQLite.Expression<String?>("releaseCoverFront")
|
||||||
}
|
}
|
||||||
|
|
||||||
static var hash: SQLite.Expression<String> {
|
static var sha1Hash: SQLite.Expression<String> {
|
||||||
return SQLite.Expression<String>("romHashSHA1")
|
return SQLite.Expression<String>("romHashSHA1")
|
||||||
}
|
}
|
||||||
|
|
||||||
static var romID: SQLite.Expression<Int> {
|
static var romID: SQLite.Expression<Int> {
|
||||||
return SQLite.Expression<Int>("romID")
|
return SQLite.Expression<Int>("romID")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static var releaseID: SQLite.Expression<Int> {
|
||||||
|
return SQLite.Expression<Int>("releaseID")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Table
|
extension Table
|
||||||
@ -57,6 +66,8 @@ extension GamesDatabase
|
|||||||
|
|
||||||
class GamesDatabase
|
class GamesDatabase
|
||||||
{
|
{
|
||||||
|
static let version = -1
|
||||||
|
|
||||||
fileprivate let connection: Connection
|
fileprivate let connection: Connection
|
||||||
|
|
||||||
init() throws
|
init() throws
|
||||||
@ -71,28 +82,36 @@ class GamesDatabase
|
|||||||
{
|
{
|
||||||
throw Error.connection(error)
|
throw Error.connection(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.invalidateVirtualTableIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
func metadataResults(forGameName gameName: String) -> [GameMetadata]
|
func metadataResults(forGameName gameName: String) -> [GameMetadata]
|
||||||
{
|
{
|
||||||
|
let releaseID = Expression<Any>.releaseID
|
||||||
let name = Expression<Any>.name
|
let name = Expression<Any>.name
|
||||||
let artworkAddress = Expression<Any>.artworkAddress
|
let artworkAddress = Expression<Any>.artworkAddress
|
||||||
|
|
||||||
let query = VirtualTable.search.select(name, artworkAddress).filter(name.match(gameName + "*"))
|
let query = VirtualTable.search.select(releaseID, name, artworkAddress).filter(name.match(gameName + "*"))
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
let rows = try self.connection.prepare(query)
|
let rows = try self.connection.prepare(query)
|
||||||
|
|
||||||
let results = rows.map { row -> GameMetadata in
|
let results = rows.map { (row) -> GameMetadata in
|
||||||
let metadata = GameMetadata()
|
|
||||||
metadata.name = row[name]
|
let artworkURL: URL?
|
||||||
|
|
||||||
if let address = row[artworkAddress]
|
if let address = row[artworkAddress]
|
||||||
{
|
{
|
||||||
metadata.artworkURL = URL(string: address)
|
artworkURL = URL(string: address)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
artworkURL = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let metadata = GameMetadata(identifier: row[releaseID], name: row[name], artworkURL: artworkURL)
|
||||||
return metadata
|
return metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,26 +137,31 @@ class GamesDatabase
|
|||||||
|
|
||||||
func metadata(for game: Game) -> GameMetadata?
|
func metadata(for game: Game) -> GameMetadata?
|
||||||
{
|
{
|
||||||
|
let releaseID = Expression<Any>.releaseID
|
||||||
let name = Expression<Any>.name
|
let name = Expression<Any>.name
|
||||||
let artworkAddress = Expression<Any>.artworkAddress
|
let artworkAddress = Expression<Any>.artworkAddress
|
||||||
let hash = Expression<Any>.hash
|
|
||||||
|
let sha1Hash = Expression<Any>.sha1Hash
|
||||||
let romID = Expression<Any>.romID
|
let romID = Expression<Any>.romID
|
||||||
|
|
||||||
let gameHash = game.identifier.uppercased()
|
let gameHash = game.identifier.uppercased()
|
||||||
let query = Table.roms.select(name, artworkAddress).filter(hash == gameHash).join(Table.releases, on: Table.roms[romID] == Table.releases[romID])
|
let query = Table.roms.select(releaseID, name, artworkAddress).filter(sha1Hash == gameHash).join(Table.releases, on: Table.roms[romID] == Table.releases[romID])
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if let row = try self.connection.pluck(query)
|
if let row = try self.connection.pluck(query)
|
||||||
{
|
{
|
||||||
let metadata = GameMetadata()
|
let artworkURL: URL?
|
||||||
metadata.name = row[name]
|
|
||||||
|
|
||||||
if let address = row[artworkAddress]
|
if let address = row[artworkAddress]
|
||||||
{
|
{
|
||||||
metadata.artworkURL = URL(string: address)
|
artworkURL = URL(string: address)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
artworkURL = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let metadata = GameMetadata(identifier: row[releaseID], name: row[name], artworkURL: artworkURL)
|
||||||
return metadata
|
return metadata
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,16 +176,33 @@ class GamesDatabase
|
|||||||
|
|
||||||
private extension GamesDatabase
|
private extension GamesDatabase
|
||||||
{
|
{
|
||||||
|
func invalidateVirtualTableIfNeeded()
|
||||||
|
{
|
||||||
|
guard UserDefaults.standard.previousGamesDatabaseVersion != GamesDatabase.version else { return }
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
try self.connection.run(VirtualTable.search.drop(ifExists: true))
|
||||||
|
|
||||||
|
UserDefaults.standard.previousGamesDatabaseVersion = GamesDatabase.version
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func prepareFTS() -> Bool
|
func prepareFTS() -> Bool
|
||||||
{
|
{
|
||||||
let name = Expression<Any>.name
|
let name = Expression<Any>.name
|
||||||
let artworkAddress = Expression<Any>.artworkAddress
|
let artworkAddress = Expression<Any>.artworkAddress
|
||||||
|
let releaseID = Expression<Any>.releaseID
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
try self.connection.run(VirtualTable.search.create(.FTS4([name, artworkAddress], tokenize: .Unicode61())))
|
try self.connection.run(VirtualTable.search.create(.FTS4([releaseID, name, artworkAddress], tokenize: .Unicode61())))
|
||||||
|
|
||||||
let update = VirtualTable.search.insert(Table.releases.select(name, artworkAddress))
|
let update = VirtualTable.search.insert(Table.releases.select(releaseID, name, artworkAddress))
|
||||||
_ = try self.connection.run(update)
|
_ = try self.connection.run(update)
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user