93 lines
4.3 KiB
Swift
93 lines
4.3 KiB
Swift
import Foundation
|
|
import SQLite
|
|
import CoreLocation
|
|
|
|
typealias LocationSample = CLLocation
|
|
|
|
extension LocationSample {
|
|
|
|
private static let table = Table("location_series_data")
|
|
|
|
/// `location_series_data[series_identifier]` <-> `workout_activities[ROW_ID]`
|
|
private static let columnSeriesIdentifier = Expression<Int>("series_identifier")
|
|
|
|
private static let columnTimestamp = Expression<Double>("timestamp")
|
|
|
|
private static let columnLongitude = Expression<Double>("longitude")
|
|
|
|
private static let columnLatitude = Expression<Double>("latitude")
|
|
|
|
private static let columnAltitude = Expression<Double>("altitude")
|
|
|
|
private static let columnSpeed = Expression<Double>("speed")
|
|
|
|
private static let columnCourse = Expression<Double>("course")
|
|
|
|
private static let columnHorizontalAccuracy = Expression<Double>("horizontal_accuracy")
|
|
|
|
private static let columnVerticalAccuracy = Expression<Double>("vertical_accuracy")
|
|
|
|
private static let columnSpeedAccuracy = Expression<Double>("speed_accuracy")
|
|
|
|
private static let columnCourseAccuracy = Expression<Double>("course_accuracy")
|
|
|
|
private static let columnSignalEnvironment = Expression<Double>("signal_environment")
|
|
|
|
static func locationSamples(for seriesId: Int, in database: Database) throws -> [LocationSample] {
|
|
try database.prepare(table.filter(columnSeriesIdentifier == seriesId)).map(location)
|
|
}
|
|
|
|
static func locationSampleCount(for seriesId: Int, in database: Database) throws -> Int {
|
|
try database.scalar(table.filter(columnSeriesIdentifier == seriesId).count)
|
|
}
|
|
|
|
static func locationSamples(from start: Date, to end: Date, in database: Database) throws -> [LocationSample] {
|
|
let startTime = start.timeIntervalSinceReferenceDate
|
|
let endTime = end.timeIntervalSinceReferenceDate
|
|
return try database.prepare(table.filter(columnTimestamp >= startTime && columnTimestamp <= endTime)).map(location)
|
|
}
|
|
|
|
static func locationSampleCount(from start: Date, to end: Date, in database: Database) throws -> Int {
|
|
let startTime = start.timeIntervalSinceReferenceDate
|
|
let endTime = end.timeIntervalSinceReferenceDate
|
|
return try database.scalar(table.filter(columnTimestamp >= startTime && columnTimestamp <= endTime).count)
|
|
}
|
|
|
|
private static func location(row: Row) -> LocationSample {
|
|
.init(
|
|
coordinate: .init(
|
|
latitude: row[columnLatitude],
|
|
longitude: row[columnLongitude]),
|
|
altitude: row[columnAltitude],
|
|
horizontalAccuracy: row[columnHorizontalAccuracy],
|
|
verticalAccuracy: row[columnHorizontalAccuracy],
|
|
course: row[columnCourse],
|
|
courseAccuracy: row[columnCourseAccuracy],
|
|
speed: row[columnSpeed],
|
|
speedAccuracy: row[columnSpeedAccuracy],
|
|
timestamp: .init(timeIntervalSinceReferenceDate: row[columnTimestamp]),
|
|
sourceInfo: .init())
|
|
}
|
|
|
|
static func createTable(in database: Connection) throws {
|
|
try database.execute("CREATE TABLE location_series_data (series_identifier INTEGER NOT NULL REFERENCES data_series(hfd_key) DEFERRABLE INITIALLY DEFERRED, timestamp REAL NOT NULL, longitude REAL NOT NULL, latitude REAL NOT NULL, altitude REAL NOT NULL, speed REAL NOT NULL, course REAL NOT NULL, horizontal_accuracy REAL NOT NULL, vertical_accuracy REAL NOT NULL, speed_accuracy REAL NOT NULL, course_accuracy REAL NOT NULL, signal_environment INTEGER NOT NULL, PRIMARY KEY (series_identifier, timestamp)) WITHOUT ROWID")
|
|
}
|
|
|
|
static func insert(_ sample: LocationSample, in database: Connection, seriesId: Int) throws {
|
|
try database.run(table.insert(
|
|
columnSeriesIdentifier <- seriesId,
|
|
columnTimestamp <- sample.timestamp.timeIntervalSinceReferenceDate,
|
|
columnLongitude <- sample.coordinate.longitude,
|
|
columnLatitude <- sample.coordinate.latitude,
|
|
columnAltitude <- sample.altitude,
|
|
columnSpeed <- sample.speed,
|
|
columnCourse <- sample.course,
|
|
columnHorizontalAccuracy <- sample.horizontalAccuracy,
|
|
columnHorizontalAccuracy <- sample.verticalAccuracy,
|
|
columnSpeedAccuracy <- sample.speedAccuracy,
|
|
columnCourseAccuracy <- sample.courseAccuracy,
|
|
columnSignalEnvironment <- 1
|
|
))
|
|
}
|
|
}
|