Improve route statistics
This commit is contained in:
@ -1,13 +1,7 @@
|
||||
|
||||
struct RouteLocalization {
|
||||
|
||||
let elevation: String
|
||||
|
||||
let speed: String
|
||||
|
||||
let pace: String
|
||||
|
||||
let heartRate: String
|
||||
let statistics: [RouteStatisticType : String]
|
||||
|
||||
let fallback: String
|
||||
|
||||
@ -25,10 +19,13 @@ struct RouteLocalization {
|
||||
extension RouteLocalization {
|
||||
|
||||
static let german: RouteLocalization = .init(
|
||||
elevation: "Höhe",
|
||||
speed: "Geschw.",
|
||||
pace: "Pace",
|
||||
heartRate: "Herzfrequenz",
|
||||
statistics: [
|
||||
.elevation: "Höhe",
|
||||
.speed: "Geschwindigkeit",
|
||||
.pace: "Pace",
|
||||
.heartRate: "Herzfrequenz",
|
||||
.energy: "Aktive Kalorien"
|
||||
],
|
||||
fallback: "Zur Anzeige der Statistiken wird JavaScript und Unterstützung für HTML5 Canvas benötigt.",
|
||||
hourUnit: "Std",
|
||||
duration: "Dauer",
|
||||
@ -37,10 +34,13 @@ extension RouteLocalization {
|
||||
loadFail: "Die Statistiken konnten nicht geladen werden")
|
||||
|
||||
static let english: RouteLocalization = .init(
|
||||
elevation: "Elevation",
|
||||
speed: "Speed",
|
||||
pace: "Pace",
|
||||
heartRate: "Heart Rate",
|
||||
statistics: [
|
||||
.elevation: "Elevation",
|
||||
.speed: "Speed",
|
||||
.pace: "Pace",
|
||||
.heartRate: "Heart Rate",
|
||||
.energy: "Active Energy"
|
||||
],
|
||||
fallback: "Javascript and HTML5 Canvas Support are required to display statistics",
|
||||
hourUnit: "h",
|
||||
duration: "Duration",
|
||||
|
@ -0,0 +1,65 @@
|
||||
|
||||
enum RouteStatisticType: String, CaseIterable {
|
||||
|
||||
case elevation
|
||||
|
||||
case speed
|
||||
|
||||
case pace
|
||||
|
||||
case heartRate = "heart-rate"
|
||||
|
||||
case energy
|
||||
|
||||
var order: Int {
|
||||
switch self {
|
||||
case .elevation: 1
|
||||
case .speed: 2
|
||||
case .pace: 3
|
||||
case .heartRate: 4
|
||||
case .energy: 5
|
||||
}
|
||||
}
|
||||
|
||||
var id: String {
|
||||
switch self {
|
||||
case .elevation: "elevation"
|
||||
case .speed: "speed"
|
||||
case .pace: "pace"
|
||||
case .heartRate: "hr"
|
||||
case .energy: "energy"
|
||||
}
|
||||
}
|
||||
|
||||
var unit: String {
|
||||
switch self {
|
||||
case .elevation: "m"
|
||||
case .speed: "km/h"
|
||||
case .pace: "min/km"
|
||||
case .heartRate: "bpm"
|
||||
case .energy: "kcal"
|
||||
}
|
||||
}
|
||||
|
||||
var icon: PageIcon {
|
||||
switch self {
|
||||
case .elevation: .statisticsElevationUp
|
||||
case .speed: .statisticsSpeedometer
|
||||
case .pace: .statisticsStopwatch
|
||||
case .heartRate: .statisticsHeart
|
||||
case .energy: .statisticsEnergy
|
||||
}
|
||||
}
|
||||
|
||||
func displayText(in language: ContentLanguage) -> String {
|
||||
let localization: RouteLocalization = language == .english ? .english : .german
|
||||
return localization.statistics[self]!
|
||||
}
|
||||
}
|
||||
|
||||
extension RouteStatisticType: Comparable {
|
||||
|
||||
static func < (lhs: RouteStatisticType, rhs: RouteStatisticType) -> Bool {
|
||||
lhs.order < rhs.order
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
|
||||
enum RouteViewComponents: String {
|
||||
case onlyElevation = "elevation"
|
||||
case all = "all"
|
||||
case withoutHeartRate = "no-hr"
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ struct RouteViews: HtmlProducer {
|
||||
/// The HTML id attribute used to enable fullscreen images
|
||||
let map: PageImage
|
||||
|
||||
let components: RouteViewComponents
|
||||
let displayedTypes: Set<RouteStatisticType>
|
||||
|
||||
let mapId: String
|
||||
|
||||
@ -21,7 +21,7 @@ struct RouteViews: HtmlProducer {
|
||||
init(localization: RouteLocalization,
|
||||
chartTitle: String?,
|
||||
chartId: String,
|
||||
components: RouteViewComponents,
|
||||
displayedTypes: Set<RouteStatisticType>,
|
||||
mapTitle: String?,
|
||||
mapId: String,
|
||||
filePath: String,
|
||||
@ -31,7 +31,7 @@ struct RouteViews: HtmlProducer {
|
||||
caption: String?
|
||||
) {
|
||||
self.localization = localization
|
||||
self.components = components
|
||||
self.displayedTypes = displayedTypes
|
||||
self.mapId = mapId
|
||||
self.filePath = filePath
|
||||
self.map = PageImage(
|
||||
@ -47,9 +47,9 @@ struct RouteViews: HtmlProducer {
|
||||
self.mapTitle = mapTitle
|
||||
}
|
||||
|
||||
var pickerHiddenText: String {
|
||||
guard components == .onlyElevation else { return "" }
|
||||
return " style='display:none'"
|
||||
private func button(series: RouteStatisticType) -> String {
|
||||
let label = localization.statistics[series]!
|
||||
return "<button data-type='\(series.id)' unit='\(series.unit)' name='\(label)'>\(series.icon.usageString)<span class='label'>\(label)</span></button>"
|
||||
}
|
||||
|
||||
func populate(_ result: inout String) {
|
||||
@ -58,18 +58,19 @@ struct RouteViews: HtmlProducer {
|
||||
}
|
||||
map.populate(&result)
|
||||
|
||||
let series = displayedTypes.sorted()
|
||||
guard !series.isEmpty else {
|
||||
return
|
||||
}
|
||||
if let chartTitle {
|
||||
result += "<h2>\(chartTitle)</h2>"
|
||||
}
|
||||
result += "<div id='\(chartId)' class='charts'>"
|
||||
result += "<div class='picker y-picker'\(pickerHiddenText)>"
|
||||
result += "<button data-type='elevation' unit='m' class='active'>\(localization.elevation)</button>"
|
||||
result += "<button data-type='speed' unit='km/h'>\(localization.speed)</button>"
|
||||
result += "<button data-type='pace' unit='min/km'>\(localization.pace)</button>"
|
||||
if components == .all {
|
||||
result += "<button data-type='hr' unit='bpm'>\(localization.heartRate)</button>"
|
||||
result += "<div class='picker icon-picker y-picker'>"
|
||||
for type in series {
|
||||
result += button(series: type)
|
||||
}
|
||||
result += "</div>"
|
||||
result += "</div>" // Picker
|
||||
result += "<div class='graph'>"
|
||||
result += "<canvas>"
|
||||
result += "<div class='fallback'>\(localization.fallback)</div>"
|
||||
@ -77,13 +78,13 @@ struct RouteViews: HtmlProducer {
|
||||
result += "<div class='line'></div>"
|
||||
result += "<div class='tooltip'></div>"
|
||||
result += "<div class='load-error'>\(localization.loadFail)</div>"
|
||||
result += "</div>"
|
||||
result += "<div class='picker x-picker'\(pickerHiddenText)>"
|
||||
result += "<button data-type='distance' unit='km' class='active'>\(localization.distance)</button>"
|
||||
result += "</div>" // Graph
|
||||
result += "<div class='picker text-picker x-picker'>"
|
||||
result += "<button data-type='distance' unit='km'>\(localization.distance)</button>"
|
||||
result += "<button data-type='duration' unit='\(localization.hourUnit)'>\(localization.duration)</button>"
|
||||
result += "<button data-type='time' unit=''>\(localization.time)</button>"
|
||||
result += "</div>"
|
||||
result += "</div>"
|
||||
result += "</div>" // Picker
|
||||
result += "</div>" // Chart
|
||||
}
|
||||
|
||||
var script: String {
|
||||
|
Reference in New Issue
Block a user