From 12635511af58636ee57fc39699f841f412e2b17f Mon Sep 17 00:00:00 2001 From: Pascal Syma Date: Sun, 7 Sep 2025 03:09:37 +0200 Subject: [PATCH] Add stats --- src/pages/HomeView.vue | 2 + src/pages/StatsView.vue | 66 +++++++++++++++++- src/stores/tram.ts | 6 +- src/utils/array.ts | 150 ++++++++++++++++++++++++++++++++++++++++ src/utils/typeGroup.ts | 9 +++ 5 files changed, 228 insertions(+), 5 deletions(-) create mode 100644 src/utils/array.ts create mode 100644 src/utils/typeGroup.ts diff --git a/src/pages/HomeView.vue b/src/pages/HomeView.vue index 43c20ae..123e7e5 100644 --- a/src/pages/HomeView.vue +++ b/src/pages/HomeView.vue @@ -11,6 +11,7 @@ import { VaCardActions, VaCardContent, VaCardTitle, + VaDivider, VaForm, VaIcon, VaInput @@ -88,6 +89,7 @@ function add() { >Gesehen + diff --git a/src/pages/StatsView.vue b/src/pages/StatsView.vue index 06c9c88..662dc6d 100644 --- a/src/pages/StatsView.vue +++ b/src/pages/StatsView.vue @@ -1,7 +1,69 @@ - + diff --git a/src/stores/tram.ts b/src/stores/tram.ts index 487f582..6e78100 100644 --- a/src/stores/tram.ts +++ b/src/stores/tram.ts @@ -1,12 +1,12 @@ import { defineStore } from 'pinia'; import { computed, reactive } from 'vue'; -export const type: [number, number, boolean, string][] = [ +export type CarType = [number, number, boolean, string]; +export const type: CarType[] = [ [3101, 3143, true, 'GT8N-1 - Bombardier Flexity Classic'], [3201, 3249, true, 'GT8N-2 - Siemens Avenio'], [3401, 3435, true, 'GT8N-2 - Siemens Avenio'], - [4001, 4005, false, 'Solobus Mercedes eCitaro O 530 C2'], - [4006, 4020, false, 'Solobus Mercedes eCitaro O 530 C2'], + [4001, 4020, false, 'Solobus Mercedes eCitaro O 530 C2'], [4061, 4075, false, 'Solobus Mercedes Citaro O 530 C2'], [4076, 4090, false, 'Solobus Mercedes Citaro O 530 C2 hybrid'], [4150, 4151, false, 'Solobus MAN Lion“s City A21 NL 280'], diff --git a/src/utils/array.ts b/src/utils/array.ts new file mode 100644 index 0000000..cd63da8 --- /dev/null +++ b/src/utils/array.ts @@ -0,0 +1,150 @@ +/** + * Returns the sum of all the elements of a numeric array. + * @param arr Numeric array. + */ +export function sumArray(arr: ReadonlyArray): number { + return sumBy(arr, (a) => a); +} + +/** + * Returns the sum of all the elements of any array, + * given a lamda function to receive the numeric representation of each element. + * @param arr Any array. + * @param by Map element to number or string, which will be interpreted as a number. + */ +export function sumBy(arr: ReadonlyArray, by: (element: E) => number | string): number { + return arr.reduce((sum, element) => sum + Number(by(element)), 0); +} + +/** + * Returns the product of a numeric array. + * @param arr Numeric array. + */ +export function multArray(arr: ReadonlyArray): number { + return multBy(arr, (a) => a); +} + +/** + * Returns the product of any array, + * given a lamda function to receive the numeric representation of each element. + * @param arr Any array. + * @param by Map element to number or string, which will be interpreted as a number. + */ +export function multBy(arr: ReadonlyArray, by: (element: E) => number | string): number { + if (arr.length <= 0) { + return 0; + } + return arr.reduce((sum, element) => sum * Number(by(element)), 1); +} + +/** + * Group an array by a given key. + * @param arr Any array. + * @param by Map element to key. + * @param equals Check if two keys are identical. Defaults to strict equality. + */ +export function groupBy( + arr: ReadonlyArray, + by: (element: E) => K, + equals: (a: K, b: K) => boolean = (a, b) => a === b +): { key: K; elements: Array }[] { + return arr.reduce( + (groups, element) => { + const key = by(element); + const index = groups.findIndex((e) => equals(e.key, key)); + + if (index < 0) { + // New key found, add to group array. + groups.push({ key, elements: [element] }); + return groups; + } + + const existing = groups[index]; + existing.elements.push(element); + + return groups; + }, + [] as { key: K; elements: Array }[] + ); +} + +/** + * Return the middle Element of an array, rounding up. + * Returns undefined for empty arrays without throwing! + * + * @example + * ```typescript + * getMiddleElement([1, 2, 3, 4]) === 3 + * getMiddleElement([1, 2, 3]) === 2 + * getMiddleElement([1]) === 1 + * getMiddleElement([]) === undefined + * ``` + * @param arr + */ +export function getMiddleElement(arr: ReadonlyArray) { + return arr[Math.floor(arr.length / 2)]; +} + +/** + * Returns an array with every combination of every element in an array. + * The combination array will have a length of `n * (n-1)` for an array of length `n`. + * @example + * ```typescript + * const arr = [0, 1, 2] + * + * combinations(arr) === [ + * {a: 0, b: 1}, + * {a: 0, b: 2}, + * {a: 1, b: 0}, + * {a: 1, b: 2}, + * {a: 2, b: 0}, + * {a: 2, b: 1}, + * ] + * ``` + * @param arr + */ +export function combinations(arr: ReadonlyArray): { a: E; b: E }[] { + return arr + .flatMap((a, _, arr) => arr.flatMap((b) => (a !== b ? [{ a, b }] : null))) + .filter((c) => !!c); +} + +/** + * Returns an array with every unique combination of every element in an array. + * The combination array will have a length of `n! / ((n-2)! * 2)` for an array of length `n`. + * @example + * ```typescript + * const arr = [0, 1, 2] + * + * combinations(arr) === [ + * {a: 0, b: 1}, + * {a: 0, b: 2}, + * {a: 1, b: 2} + * ] + * ``` + * @param arr + */ +export function uniqueCombinations(arr: ReadonlyArray): { a: E; b: E }[] { + return arr.flatMap((a, aI) => arr.flatMap((b, bI) => (a !== b && aI > bI ? [{ a, b }] : []))); +} + +/** + * Returns a filter lambda to be used in array.filter() to only allow the + * first occurrence of duplicate values. + * @param isEqual Custom equality check, defaults to `a === b` + */ +export function unique(isEqual: (a: E, b: E) => boolean = (a, b) => a === b) { + return (self: E, index: number, arr: ReadonlyArray) => + arr.findIndex((v) => isEqual(v, self)) === index; +} + +/** + * Replace a char in a two-dimensional array of strings. + * @param arr two-dimensional string array + * @param x column + * @param y row + * @param char Char + */ +export function replaceChar(arr: string[], x: number, y: number, char: string) { + arr[y] = arr[y].substring(0, x) + char + arr[y].substring(x + char.length); +} diff --git a/src/utils/typeGroup.ts b/src/utils/typeGroup.ts new file mode 100644 index 0000000..94024cd --- /dev/null +++ b/src/utils/typeGroup.ts @@ -0,0 +1,9 @@ +import type { CarType } from '@/stores/tram.ts'; + +export function idsOf(elements: CarType[]): string { + if (elements.length <= 0) { + return ''; + } + + return elements.map((t) => (t[0] === t[1] ? t[0] : `${t[0]}-${t[1]}`)).join(', '); +}