| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  | import ChartJs from "../Base/ChartJs" | 
					
						
							|  |  |  | import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig" | 
					
						
							|  |  |  | import { ChartConfiguration } from "chart.js" | 
					
						
							|  |  |  | import Combine from "../Base/Combine" | 
					
						
							| 
									
										
										
										
											2022-07-20 14:06:39 +02:00
										 |  |  | import { TagUtils } from "../../Logic/Tags/TagUtils" | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  | import { Utils } from "../../Utils" | 
					
						
							|  |  |  | import { OsmFeature } from "../../Models/OsmFeature" | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  | export interface TagRenderingChartOptions { | 
					
						
							|  |  |  |     groupToOtherCutoff?: 3 | number | 
					
						
							|  |  |  |     sort?: boolean | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  | export class StackedRenderingChart extends ChartJs { | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |     constructor( | 
					
						
							|  |  |  |         tr: TagRenderingConfig, | 
					
						
							|  |  |  |         features: (OsmFeature & { properties: { date: string } })[], | 
					
						
							|  |  |  |         options?: { | 
					
						
							|  |  |  |             period: "day" | "month" | 
					
						
							|  |  |  |             groupToOtherCutoff?: 3 | number | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  |         const { labels, data } = TagRenderingChart.extractDataAndLabels(tr, features, { | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |             sort: true, | 
					
						
							|  |  |  |             groupToOtherCutoff: options?.groupToOtherCutoff, | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  |         }) | 
					
						
							|  |  |  |         if (labels === undefined || data === undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-02 21:40:13 +02:00
										 |  |  |             console.error("Could not extract data and labels for ", tr, " with features", features) | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  |             throw "No labels or data given..." | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // labels: ["cyclofix", "buurtnatuur", ...]; data : [ ["cyclofix-changeset", "cyclofix-changeset", ...], ["buurtnatuur-cs", "buurtnatuur-cs"], ... ]
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |         for (let i = labels.length; i >= 0; i--) { | 
					
						
							|  |  |  |             if (data[i]?.length != 0) { | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             data.splice(i, 1) | 
					
						
							|  |  |  |             labels.splice(i, 1) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const datasets: { | 
					
						
							|  |  |  |             label: string /*themename*/ | 
					
						
							|  |  |  |             data: number[] /*counts per day*/ | 
					
						
							|  |  |  |             backgroundColor: string | 
					
						
							|  |  |  |         }[] = [] | 
					
						
							|  |  |  |         const allDays = StackedRenderingChart.getAllDays(features) | 
					
						
							| 
									
										
										
										
											2022-09-02 21:40:13 +02:00
										 |  |  |         let trimmedDays = allDays.map((d) => d.substr(0, 10)) | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |         if (options?.period === "month") { | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  |             trimmedDays = trimmedDays.map((d) => d.substr(0, 7)) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         trimmedDays = Utils.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() | 
					
						
							| 
									
										
										
										
											2022-09-02 21:40:13 +02:00
										 |  |  |                 str = str.substr(0, 10) | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |                 if (options?.period === "month") { | 
					
						
							| 
									
										
										
										
											2022-09-02 21:40:13 +02:00
										 |  |  |                     str = str.substr(0, 7) | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 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] | 
					
						
							|  |  |  |                 countsPerDay[i] = perDay[day]?.length ?? 0 | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |             let backgroundColor = | 
					
						
							|  |  |  |                 TagRenderingChart.borderColors[i % TagRenderingChart.borderColors.length] | 
					
						
							|  |  |  |             if (label === "Unknown") { | 
					
						
							|  |  |  |                 backgroundColor = TagRenderingChart.unkownBorderColor | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (label === "Other") { | 
					
						
							|  |  |  |                 backgroundColor = TagRenderingChart.otherBorderColor | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  |             datasets.push({ | 
					
						
							|  |  |  |                 data: countsPerDay, | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |                 backgroundColor, | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  |                 label, | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const perDayData = { | 
					
						
							|  |  |  |             labels: trimmedDays, | 
					
						
							|  |  |  |             datasets, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const config = <ChartConfiguration>{ | 
					
						
							|  |  |  |             type: "bar", | 
					
						
							|  |  |  |             data: perDayData, | 
					
						
							|  |  |  |             options: { | 
					
						
							|  |  |  |                 responsive: true, | 
					
						
							|  |  |  |                 legend: { | 
					
						
							|  |  |  |                     display: false, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 scales: { | 
					
						
							|  |  |  |                     x: { | 
					
						
							|  |  |  |                         stacked: true, | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                     y: { | 
					
						
							|  |  |  |                         stacked: true, | 
					
						
							|  |  |  |                     }, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         super(config) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |     public static getAllDays( | 
					
						
							|  |  |  |         features: (OsmFeature & { properties: { date: string } })[] | 
					
						
							|  |  |  |     ): string[] { | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  |         let earliest: Date = undefined | 
					
						
							|  |  |  |         let latest: Date = undefined | 
					
						
							|  |  |  |         let allDates = new Set<string>() | 
					
						
							|  |  |  |         features.forEach((value, key) => { | 
					
						
							|  |  |  |             const d = new Date(value.properties.date) | 
					
						
							|  |  |  |             Utils.SetMidnight(d) | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  |             if (earliest === undefined) { | 
					
						
							|  |  |  |                 earliest = d | 
					
						
							|  |  |  |             } else if (d < earliest) { | 
					
						
							|  |  |  |                 earliest = d | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (latest === undefined) { | 
					
						
							|  |  |  |                 latest = d | 
					
						
							|  |  |  |             } else if (d > latest) { | 
					
						
							|  |  |  |                 latest = d | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             allDates.add(d.toISOString()) | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while (earliest < latest) { | 
					
						
							|  |  |  |             earliest.setDate(earliest.getDate() + 1) | 
					
						
							|  |  |  |             allDates.add(earliest.toISOString()) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const days = Array.from(allDates) | 
					
						
							|  |  |  |         days.sort() | 
					
						
							|  |  |  |         return days | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  | export default class TagRenderingChart extends Combine { | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |     public static readonly unkownColor = "rgba(128, 128, 128, 0.2)" | 
					
						
							|  |  |  |     public static readonly unkownBorderColor = "rgba(128, 128, 128, 0.2)" | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |     public static readonly otherColor = "rgba(128, 128, 128, 0.2)" | 
					
						
							|  |  |  |     public static readonly otherBorderColor = "rgba(128, 128, 255)" | 
					
						
							|  |  |  |     public static readonly notApplicableColor = "rgba(128, 128, 128, 0.2)" | 
					
						
							|  |  |  |     public static readonly notApplicableBorderColor = "rgba(255, 0, 0)" | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |     public static readonly backgroundColors = [ | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |         "rgba(255, 99, 132, 0.2)", | 
					
						
							|  |  |  |         "rgba(54, 162, 235, 0.2)", | 
					
						
							|  |  |  |         "rgba(255, 206, 86, 0.2)", | 
					
						
							|  |  |  |         "rgba(75, 192, 192, 0.2)", | 
					
						
							|  |  |  |         "rgba(153, 102, 255, 0.2)", | 
					
						
							|  |  |  |         "rgba(255, 159, 64, 0.2)", | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-20 12:46:33 +02:00
										 |  |  |     public static readonly borderColors = [ | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |         "rgba(255, 99, 132, 1)", | 
					
						
							|  |  |  |         "rgba(54, 162, 235, 1)", | 
					
						
							|  |  |  |         "rgba(255, 206, 86, 1)", | 
					
						
							|  |  |  |         "rgba(75, 192, 192, 1)", | 
					
						
							|  |  |  |         "rgba(153, 102, 255, 1)", | 
					
						
							|  |  |  |         "rgba(255, 159, 64, 1)", | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Creates a chart about this tagRendering for the given data | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |     constructor( | 
					
						
							|  |  |  |         features: { properties: Record<string, string> }[], | 
					
						
							|  |  |  |         tagRendering: TagRenderingConfig, | 
					
						
							|  |  |  |         options?: TagRenderingChartOptions & { | 
					
						
							|  |  |  |             chartclasses?: string | 
					
						
							| 
									
										
										
										
											2022-07-20 15:04:51 +02:00
										 |  |  |             chartstyle?: string | 
					
						
							|  |  |  |             includeTitle?: boolean | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |             chartType?: "pie" | "bar" | "doughnut" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |         if (tagRendering.mappings?.length === 0 && tagRendering.freeform?.key === undefined) { | 
					
						
							| 
									
										
										
										
											2022-07-20 14:39:19 +02:00
										 |  |  |             super([]) | 
					
						
							|  |  |  |             this.SetClass("hidden") | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |         const { labels, data } = TagRenderingChart.extractDataAndLabels( | 
					
						
							|  |  |  |             tagRendering, | 
					
						
							|  |  |  |             features, | 
					
						
							|  |  |  |             options | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         if (labels === undefined || data === undefined) { | 
					
						
							| 
									
										
										
										
											2022-07-20 14:39:19 +02:00
										 |  |  |             super([]) | 
					
						
							|  |  |  |             this.SetClass("hidden") | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2022-07-20 14:06:39 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |         const borderColor = [ | 
					
						
							|  |  |  |             TagRenderingChart.unkownBorderColor, | 
					
						
							|  |  |  |             TagRenderingChart.otherBorderColor, | 
					
						
							|  |  |  |             TagRenderingChart.notApplicableBorderColor, | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         const backgroundColor = [ | 
					
						
							|  |  |  |             TagRenderingChart.unkownColor, | 
					
						
							|  |  |  |             TagRenderingChart.otherColor, | 
					
						
							|  |  |  |             TagRenderingChart.notApplicableColor, | 
					
						
							|  |  |  |         ] | 
					
						
							| 
									
										
										
										
											2022-07-20 14:06:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |         while (borderColor.length < data.length) { | 
					
						
							|  |  |  |             borderColor.push(...TagRenderingChart.borderColors) | 
					
						
							|  |  |  |             backgroundColor.push(...TagRenderingChart.backgroundColors) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (let i = data.length; i >= 0; i--) { | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |             if (data[i]?.length === 0) { | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |                 labels.splice(i, 1) | 
					
						
							|  |  |  |                 data.splice(i, 1) | 
					
						
							|  |  |  |                 borderColor.splice(i, 1) | 
					
						
							|  |  |  |                 backgroundColor.splice(i, 1) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |         let barchartMode = tagRendering.multiAnswer | 
					
						
							|  |  |  |         if (labels.length > 9) { | 
					
						
							| 
									
										
										
										
											2022-07-20 15:04:51 +02:00
										 |  |  |             barchartMode = true | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-07-20 15:04:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |         const config = <ChartConfiguration>{ | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |             type: options.chartType ?? (barchartMode ? "bar" : "doughnut"), | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |             data: { | 
					
						
							|  |  |  |                 labels, | 
					
						
							|  |  |  |                 datasets: [ | 
					
						
							|  |  |  |                     { | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |                         data: data.map((l) => l.length), | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |                         backgroundColor, | 
					
						
							|  |  |  |                         borderColor, | 
					
						
							|  |  |  |                         borderWidth: 1, | 
					
						
							|  |  |  |                         label: undefined, | 
					
						
							|  |  |  |                     }, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 ], | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |             }, | 
					
						
							|  |  |  |             options: { | 
					
						
							|  |  |  |                 plugins: { | 
					
						
							|  |  |  |                     legend: { | 
					
						
							| 
									
										
										
										
											2022-07-20 14:06:39 +02:00
										 |  |  |                         display: !barchartMode, | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |                     }, | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const chart = new ChartJs(config).SetClass(options?.chartclasses ?? "w-32 h-32") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (options.chartstyle !== undefined) { | 
					
						
							|  |  |  |             chart.SetStyle(options.chartstyle) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-07-20 14:06:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |         super([ | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |             options?.includeTitle ? tagRendering.question.Clone() ?? tagRendering.id : undefined, | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |             chart, | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.SetClass("block") | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |     public static extractDataAndLabels<T extends { properties: Record<string, string> }>( | 
					
						
							|  |  |  |         tagRendering: TagRenderingConfig, | 
					
						
							|  |  |  |         features: T[], | 
					
						
							|  |  |  |         options?: TagRenderingChartOptions | 
					
						
							|  |  |  |     ): { labels: string[]; data: T[][] } { | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |         const mappings = tagRendering.mappings ?? [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         options = options ?? {} | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |         let unknownCount: T[] = [] | 
					
						
							|  |  |  |         const categoryCounts: T[][] = mappings.map((_) => []) | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |         const otherCounts: Record<string, T[]> = {} | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |         let notApplicable: T[] = [] | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |         for (const feature of features) { | 
					
						
							|  |  |  |             const props = feature.properties | 
					
						
							|  |  |  |             if ( | 
					
						
							|  |  |  |                 tagRendering.condition !== undefined && | 
					
						
							|  |  |  |                 !tagRendering.condition.matchesProperties(props) | 
					
						
							|  |  |  |             ) { | 
					
						
							|  |  |  |                 notApplicable.push(feature) | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!tagRendering.IsKnown(props)) { | 
					
						
							|  |  |  |                 unknownCount.push(feature) | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             let foundMatchingMapping = false | 
					
						
							|  |  |  |             if (!tagRendering.multiAnswer) { | 
					
						
							|  |  |  |                 for (let i = 0; i < mappings.length; i++) { | 
					
						
							|  |  |  |                     const mapping = mappings[i] | 
					
						
							|  |  |  |                     if (mapping.if.matchesProperties(props)) { | 
					
						
							|  |  |  |                         categoryCounts[i].push(feature) | 
					
						
							|  |  |  |                         foundMatchingMapping = true | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 for (let i = 0; i < mappings.length; i++) { | 
					
						
							|  |  |  |                     const mapping = mappings[i] | 
					
						
							|  |  |  |                     if (TagUtils.MatchesMultiAnswer(mapping.if, props)) { | 
					
						
							|  |  |  |                         categoryCounts[i].push(feature) | 
					
						
							|  |  |  |                         foundMatchingMapping = true | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (!foundMatchingMapping) { | 
					
						
							|  |  |  |                 if ( | 
					
						
							|  |  |  |                     tagRendering.freeform?.key !== undefined && | 
					
						
							|  |  |  |                     props[tagRendering.freeform.key] !== undefined | 
					
						
							|  |  |  |                 ) { | 
					
						
							|  |  |  |                     const otherValue = props[tagRendering.freeform.key] | 
					
						
							|  |  |  |                     otherCounts[otherValue] = otherCounts[otherValue] ?? [] | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |                     otherCounts[otherValue].push(feature) | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |                 } else { | 
					
						
							|  |  |  |                     unknownCount.push(feature) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (unknownCount.length + notApplicable.length === features.length) { | 
					
						
							|  |  |  |             console.log("Returning no label nor data: all features are unkown or notApplicable") | 
					
						
							|  |  |  |             return { labels: undefined, data: undefined } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |         let otherGrouped: T[] = [] | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |         const otherLabels: string[] = [] | 
					
						
							|  |  |  |         const otherData: T[][] = [] | 
					
						
							|  |  |  |         const sortedOtherCounts: [string, T[]][] = [] | 
					
						
							|  |  |  |         for (const v in otherCounts) { | 
					
						
							|  |  |  |             sortedOtherCounts.push([v, otherCounts[v]]) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (options?.sort) { | 
					
						
							|  |  |  |             sortedOtherCounts.sort((a, b) => b[1].length - a[1].length) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         for (const [v, count] of sortedOtherCounts) { | 
					
						
							|  |  |  |             if (count.length >= (options.groupToOtherCutoff ?? 3)) { | 
					
						
							|  |  |  |                 otherLabels.push(v) | 
					
						
							|  |  |  |                 otherData.push(otherCounts[v]) | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 otherGrouped.push(...count) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const labels = [ | 
					
						
							|  |  |  |             "Unknown", | 
					
						
							|  |  |  |             "Other", | 
					
						
							|  |  |  |             "Not applicable", | 
					
						
							|  |  |  |             ...(mappings?.map((m) => m.then.txt) ?? []), | 
					
						
							|  |  |  |             ...otherLabels, | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |         ] | 
					
						
							|  |  |  |         const data: T[][] = [ | 
					
						
							|  |  |  |             unknownCount, | 
					
						
							|  |  |  |             otherGrouped, | 
					
						
							|  |  |  |             notApplicable, | 
					
						
							|  |  |  |             ...categoryCounts, | 
					
						
							|  |  |  |             ...otherData, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 23:37:44 +02:00
										 |  |  |         return { labels, data } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  | } |