exclude lift-assisted ski types from ascent totals

This commit is contained in:
Vincent van der Wal
2026-07-22 16:08:36 +02:00
parent a24eef807c
commit 91775c4099
4 changed files with 28 additions and 6 deletions
+8
View File
@@ -0,0 +1,8 @@
// Lift-assisted downhill types: their recorded elevation gain comes from
// lifts, so it doesn't count toward ascent totals. Touring variants
// ("ski touring", "backcountry ski") earn their metres and do count.
export const LIFT_ASSISTED_TYPES = ['ski', 'alpine ski', 'downhill ski', 'snowboard'];
export function countsTowardAscent(type: string): boolean {
return !LIFT_ASSISTED_TYPES.includes(type.toLowerCase().trim());
}
+8 -2
View File
@@ -3,6 +3,12 @@ import fs from 'node:fs';
import path from 'node:path';
import { PEAKS } from './peaks-seed';
import { assignMinzoom, scorePeak } from './peak-score';
import { LIFT_ASSISTED_TYPES } from '$lib/activity-rules';
// SQL fragment: elevation gain that counts toward ascent totals
// (lift-assisted downhill types contribute 0)
const LIFT_LIST = LIFT_ASSISTED_TYPES.map((t) => `'${t}'`).join(', ');
export const COUNTED_GAIN = `CASE WHEN lower(trim(type)) IN (${LIFT_LIST}) THEN 0 ELSE elev_gain_m END`;
const DATA_DIR = process.env.STREBA_DATA_DIR ?? 'data';
fs.mkdirSync(DATA_DIR, { recursive: true });
@@ -234,7 +240,7 @@ export function userStats(userId: number): {
.prepare(
`SELECT count(*) activities,
coalesce(sum(distance_m), 0) distance_m,
coalesce(sum(elev_gain_m), 0) elev_gain_m,
coalesce(sum(${COUNTED_GAIN}), 0) elev_gain_m,
coalesce(sum(coalesce(moving_s, duration_s, 0)), 0) moving_s
FROM activities WHERE user_id = ?`
)
@@ -252,7 +258,7 @@ export function communityTotals(): {
`SELECT (SELECT count(*) FROM users) users,
count(*) activities,
coalesce(sum(distance_m), 0) distance_m,
coalesce(sum(elev_gain_m), 0) elev_gain_m
coalesce(sum(${COUNTED_GAIN}), 0) elev_gain_m
FROM activities`
)
.get() as { users: number; activities: number; distance_m: number; elev_gain_m: number };
+7 -3
View File
@@ -1,4 +1,5 @@
import { db, listActivities } from '$lib/server/db';
import { COUNTED_GAIN, db, listActivities } from '$lib/server/db';
import { countsTowardAscent } from '$lib/activity-rules';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = ({ locals }) => {
@@ -9,7 +10,7 @@ export const load: PageServerLoad = ({ locals }) => {
`SELECT substr(coalesce(date, substr(created_at, 1, 10)), 1, 4) year,
count(*) count,
sum(distance_m) distance_m,
sum(elev_gain_m) elev_gain_m,
sum(${COUNTED_GAIN}) elev_gain_m,
sum(coalesce(moving_s, duration_s, 0)) moving_s
FROM activities WHERE user_id = ?
GROUP BY year ORDER BY year DESC`
@@ -28,7 +29,10 @@ export const load: PageServerLoad = ({ locals }) => {
totals: {
count: activities.length,
distance_m: activities.reduce((sum, a) => sum + a.distance_m, 0),
elev_gain_m: activities.reduce((sum, a) => sum + a.elev_gain_m, 0),
elev_gain_m: activities.reduce(
(sum, a) => sum + (countsTowardAscent(a.type) ? a.elev_gain_m : 0),
0
),
moving_s: activities.reduce((sum, a) => sum + (a.moving_s ?? a.duration_s ?? 0), 0)
}
};
+5 -1
View File
@@ -1,6 +1,7 @@
<script lang="ts">
import ActivityItem from '$lib/components/ActivityItem.svelte';
import StatTile from '$lib/components/StatTile.svelte';
import { countsTowardAscent } from '$lib/activity-rules';
import { fmtDistance, fmtDuration, fmtElevation } from '$lib/format';
let { data } = $props();
@@ -19,7 +20,10 @@
const shown = $derived({
count: filtered.length,
distance_m: filtered.reduce((sum, a) => sum + a.distance_m, 0),
elev_gain_m: filtered.reduce((sum, a) => sum + a.elev_gain_m, 0),
elev_gain_m: filtered.reduce(
(sum, a) => sum + (countsTowardAscent(a.type) ? a.elev_gain_m : 0),
0
),
moving_s: filtered.reduce((sum, a) => sum + (a.moving_s ?? a.duration_s ?? 0), 0)
});
const suffix = $derived(selectedYear === null ? '' : ` (${selectedYear})`);