chore: automated housekeeping...

This commit is contained in:
Pieter Vander Vennet 2025-08-13 23:06:38 +02:00
parent 9cd7ad597d
commit 69ab755f29
520 changed files with 16616 additions and 13483 deletions

View file

@ -36,11 +36,10 @@ export interface TagRenderingChartOptions {
groupToOtherCutoff?: 3 | number
sort?: boolean
hideUnkown?: boolean
hideNotApplicable?: boolean,
hideNotApplicable?: boolean
chartType?: "pie" | "bar" | "doughnut"
}
export class ChartJsUtils {
/**
* Gets the 'date' out of all features.properties,
* returns a range with all dates from 'earliest' to 'latest' as to get one continuous range
@ -178,7 +177,7 @@ export class ChartJsUtils {
}
data.push(...categoryCounts, ...otherData)
labels.push(...(mappings?.map((m) => m.then.txt) ?? []), ...otherLabels)
if(data.length === 0){
if (data.length === 0) {
return undefined
}
return { labels, data }
@ -196,139 +195,139 @@ export class ChartJsUtils {
* @param options
*/
static createPerDayConfigForTagRendering(
tr: TagRenderingConfig,
features: (OsmFeature & { properties: { date: string } })[],
options?: {
period: "day" | "month"
groupToOtherCutoff?: 3 | number
// If given, take the sum of these fields to get the feature weight
sumFields?: ReadonlyArray<string>
hideUnknown?: boolean
hideNotApplicable?: boolean
}
tr: TagRenderingConfig,
features: (OsmFeature & { properties: { date: string } })[],
options?: {
period: "day" | "month"
groupToOtherCutoff?: 3 | number
// If given, take the sum of these fields to get the feature weight
sumFields?: ReadonlyArray<string>
hideUnknown?: boolean
hideNotApplicable?: boolean
}
): ChartConfiguration {
const { labels, data } = ChartJsUtils.extractDataAndLabels(tr, features, {
sort: true,
groupToOtherCutoff: options?.groupToOtherCutoff,
hideNotApplicable: options?.hideNotApplicable,
hideUnkown: options?.hideUnknown,
})
if (labels === undefined || data === undefined) {
console.error(
"Could not extract data and labels for ",
tr,
" with features",
features,
": no labels or no data"
)
throw "No labels or data given..."
const { labels, data } = ChartJsUtils.extractDataAndLabels(tr, features, {
sort: true,
groupToOtherCutoff: options?.groupToOtherCutoff,
hideNotApplicable: options?.hideNotApplicable,
hideUnkown: options?.hideUnknown,
})
if (labels === undefined || data === undefined) {
console.error(
"Could not extract data and labels for ",
tr,
" with features",
features,
": no labels or no data"
)
throw "No labels or data given..."
}
for (let i = labels.length; i >= 0; i--) {
if (data[i]?.length != 0) {
continue
}
data.splice(i, 1)
labels.splice(i, 1)
}
const datasets: {
label: string /*themename*/
data: number[] /*counts per day*/
backgroundColor: string
}[] = []
const allDays = ChartJsUtils.getAllDays(features)
let trimmedDays = allDays.map((d) => d.substring(0, 10))
if (options?.period === "month") {
trimmedDays = trimmedDays.map((d) => d.substring(0, 7))
}
trimmedDays = Lists.dedup(trimmedDays)
for (let i = 0; i < labels.length; i++) {
const label = labels[i]
const changesetsForTheme = data[i]
const perDay: Record<string, OsmFeature[]> = {}
for (const changeset of changesetsForTheme) {
const csDate = new Date(changeset.properties.date)
Utils.SetMidnight(csDate)
let str = csDate.toISOString()
str = str.substr(0, 10)
if (options?.period === "month") {
str = str.substr(0, 7)
}
if (perDay[str] === undefined) {
perDay[str] = [changeset]
} else {
perDay[str].push(changeset)
}
}
for (let i = labels.length; i >= 0; i--) {
if (data[i]?.length != 0) {
const countsPerDay: number[] = []
for (let i = 0; i < trimmedDays.length; i++) {
const day = trimmedDays[i]
const featuresForDay = perDay[day]
if (!featuresForDay) {
continue
}
data.splice(i, 1)
labels.splice(i, 1)
}
const datasets: {
label: string /*themename*/
data: number[] /*counts per day*/
backgroundColor: string
}[] = []
const allDays = ChartJsUtils.getAllDays(features)
let trimmedDays = allDays.map((d) => d.substring(0, 10))
if (options?.period === "month") {
trimmedDays = trimmedDays.map((d) => d.substring(0, 7))
}
trimmedDays = Lists.dedup(trimmedDays)
for (let i = 0; i < labels.length; i++) {
const label = labels[i]
const changesetsForTheme = data[i]
const perDay: Record<string, OsmFeature[]> = {}
for (const changeset of changesetsForTheme) {
const csDate = new Date(changeset.properties.date)
Utils.SetMidnight(csDate)
let str = csDate.toISOString()
str = str.substr(0, 10)
if (options?.period === "month") {
str = str.substr(0, 7)
}
if (perDay[str] === undefined) {
perDay[str] = [changeset]
} else {
perDay[str].push(changeset)
}
}
const countsPerDay: number[] = []
for (let i = 0; i < trimmedDays.length; i++) {
const day = trimmedDays[i]
const featuresForDay = perDay[day]
if (!featuresForDay) {
continue
}
if (options.sumFields !== undefined) {
let sum = 0
for (const featuresForDayElement of featuresForDay) {
const props = featuresForDayElement.properties
for (const key of options.sumFields) {
if (!props[key]) {
continue
}
const v = Number(props[key])
if (isNaN(v)) {
continue
}
sum += v
if (options.sumFields !== undefined) {
let sum = 0
for (const featuresForDayElement of featuresForDay) {
const props = featuresForDayElement.properties
for (const key of options.sumFields) {
if (!props[key]) {
continue
}
const v = Number(props[key])
if (isNaN(v)) {
continue
}
sum += v
}
countsPerDay[i] = sum
} else {
countsPerDay[i] = featuresForDay?.length ?? 0
}
countsPerDay[i] = sum
} else {
countsPerDay[i] = featuresForDay?.length ?? 0
}
let backgroundColor =
ChartJsColours.borderColors[i % ChartJsColours.borderColors.length]
if (label === "Unknown") {
backgroundColor = ChartJsColours.unknownBorderColor
}
if (label === "Other") {
backgroundColor = ChartJsColours.otherBorderColor
}
datasets.push({
data: countsPerDay,
backgroundColor,
label,
})
}
const perDayData = {
labels: trimmedDays,
datasets,
let backgroundColor =
ChartJsColours.borderColors[i % ChartJsColours.borderColors.length]
if (label === "Unknown") {
backgroundColor = ChartJsColours.unknownBorderColor
}
if (label === "Other") {
backgroundColor = ChartJsColours.otherBorderColor
}
datasets.push({
data: countsPerDay,
backgroundColor,
label,
})
}
return <ChartConfiguration>{
type: "bar",
data: perDayData,
options: {
responsive: true,
legend: {
display: false,
const perDayData = {
labels: trimmedDays,
datasets,
}
return <ChartConfiguration>{
type: "bar",
data: perDayData,
options: {
responsive: true,
legend: {
display: false,
},
scales: {
x: {
stacked: true,
},
scales: {
x: {
stacked: true,
},
y: {
stacked: true,
},
y: {
stacked: true,
},
},
}
},
}
}
/**
@ -336,17 +335,16 @@ export class ChartJsUtils {
*
* @returns undefined if not enough parameters
*/
static createConfigForTagRendering<T extends { properties: Record<string, string> }>(tagRendering: TagRenderingConfig, features: T[],
options?: TagRenderingChartOptions): ChartConfiguration{
static createConfigForTagRendering<T extends { properties: Record<string, string> }>(
tagRendering: TagRenderingConfig,
features: T[],
options?: TagRenderingChartOptions
): ChartConfiguration {
if (tagRendering.mappings?.length === 0 && tagRendering.freeform?.key === undefined) {
return undefined
}
const { labels, data } = ChartJsUtils.extractDataAndLabels(
tagRendering,
features,
options
)
const { labels, data } = ChartJsUtils.extractDataAndLabels(tagRendering, features, options)
if (labels === undefined || data === undefined) {
return undefined
}
@ -403,22 +401,18 @@ export class ChartJsUtils {
},
},
}
}
static createHistogramConfig(keys: string[], counts: Map<string, number>){
const borderColor = [
]
const backgroundColor = [
]
static createHistogramConfig(keys: string[], counts: Map<string, number>) {
const borderColor = []
const backgroundColor = []
while (borderColor.length < keys.length) {
borderColor.push(...ChartJsColours.borderColors)
backgroundColor.push(...ChartJsColours.backgroundColors)
}
return <ChartConfiguration>{
return <ChartConfiguration>{
type: "bar",
data: {
labels: keys,
@ -432,11 +426,12 @@ export class ChartJsUtils {
},
],
},
options: { scales: {
options: {
scales: {
y: {
ticks: {
stepSize: 1,
callback: (value) =>Number(value).toFixed(0),
callback: (value) => Number(value).toFixed(0),
},
},
},