diff --git a/Docs/Development_deployment.md b/Docs/Development_deployment.md index ed18b9625..3590b92d8 100644 --- a/Docs/Development_deployment.md +++ b/Docs/Development_deployment.md @@ -27,7 +27,10 @@ Devcontainer (see more details later). To develop and build MapComplete, you 0. Make a fork and clone the repository. (We recommend a shallow clone with `git clone --filter=blob:none `) -0. Install the nodejs version specified in [.tool-versions](./.tool-versions) +0. Install `python3` if you do not have it already + - On linux: `sudo apt install python3` + - On windows: find the latest download on the [Python Releases for Windows page](https://www.python.org/downloads/windows/) +0. Install the nodejs version specified in [/.tool-versions](/.tool-versions) - On linux: install npm first `sudo apt install npm`, then install `n` using npm: ` npm install -g n`, which can then install node with `n install ` - You can [use asdf to manage your runtime versions](https://asdf-vm.com/). @@ -72,11 +75,12 @@ To use the WSL in Visual Studio Code: or `userlayout=true#` as [Query parameter](URL_Parameters.md). Note that the shorter URLs ( e.g. `bookcases.html`, `aed.html`, ...) _don't_ exist on the development version. -### Dependencie +Dependencies +------------ `make` , `python3` `g++` -(run `nix-env -iA nixos.gnumake nixos.gdc nixos.python3`) +(Nix users may run `nix-env -iA nixos.gnumake nixos.gdc nixos.python3`) Automatic deployment -------------------- diff --git a/UI/StatisticsGUI.ts b/UI/StatisticsGUI.ts new file mode 100644 index 000000000..fa454d50d --- /dev/null +++ b/UI/StatisticsGUI.ts @@ -0,0 +1,102 @@ +/** + * The statistics-gui shows statistics from previous MapComplete-edits + */ +import {UIEventSource} from "../Logic/UIEventSource"; +import {VariableUiElement} from "./Base/VariableUIElement"; +import ChartJs from "./Base/ChartJs"; +import Loading from "./Base/Loading"; +import {Utils} from "../Utils"; +import Combine from "./Base/Combine"; + +export default class StatisticsGUI { + + public static setup(): void{ + + + new VariableUiElement(index.map(paths => { + if (paths === undefined) { + return new Loading("Loading overview...") + } + const downloaded = new UIEventSource<{ features: ChangeSetData[] }[]>([]) + + for (const filepath of paths) { + Utils.downloadJson(homeUrl + filepath).then(data => { + downloaded.data.push(data) + downloaded.ping() + }) + } + + return new VariableUiElement(downloaded.map(downloaded => { + const themeBreakdown = new Map() + for (const feats of downloaded) { + console.log("Feats:", feats) + for (const feat of feats.features) { + const key = feat.properties.metadata.theme + const count = themeBreakdown.get(key) ?? 0 + themeBreakdown.set(key, count + 1) + } + } + + const keys = Array.from(themeBreakdown.keys()) + const values = keys.map( k => themeBreakdown.get(k)) + + console.log(keys, values) + return new Combine([ + "Got " + downloaded.length + " files out of " + paths.length, + new ChartJs({ + type: "pie", + data: { + datasets: [{data: values}], + labels: keys + } + }).SetClass("w-1/3 h-full") + ]).SetClass("block w-full h-full") + })).SetClass("block w-full h-full") + })).SetClass("block w-full h-full").AttachTo("maindiv") + + } + +} + +const homeUrl = "https://raw.githubusercontent.com/pietervdvn/MapComplete/develop/Docs/Tools/stats/" +const stats_files = "file-overview.json" +const index = UIEventSource.FromPromise(Utils.downloadJson(homeUrl + stats_files)) + + +interface ChangeSetData { + "id": number, + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [number, number][][] + }, + "properties": { + "check_user": null, + "reasons": [], + "tags": [], + "features": [], + "user": string, + "uid": string, + "editor": string, + "comment": string, + "comments_count": number, + "source": string, + "imagery_used": string, + "date": string, + "reviewed_features": [], + "create": number, + "modify": number, + "delete": number, + "area": number, + "is_suspect": boolean, + "harmful": any, + "checked": boolean, + "check_date": any, + "metadata": { + "host": string, + "theme": string, + "imagery": string, + "language": string + } + } +} diff --git a/assets/layers/hydrant/barcelona.jpg b/assets/layers/hydrant/barcelona.jpg new file mode 100644 index 000000000..404248ff4 Binary files /dev/null and b/assets/layers/hydrant/barcelona.jpg differ diff --git a/assets/layers/hydrant/hydrant.json b/assets/layers/hydrant/hydrant.json index 0615067b2..f1176762a 100644 --- a/assets/layers/hydrant/hydrant.json +++ b/assets/layers/hydrant/hydrant.json @@ -325,6 +325,82 @@ } ] }, + { + "id": "hydrant-diameter", + "question": { + "en": "What is the pipe diameter of this hydrant?" + }, + "freeform": { + "key": "fire_hydrant:diameter", + "placeholder": { + "en": "Pipe diameter" + }, + "type": "int" + }, + "render": { + "en": "Pipe diameter: {canonical(fire_hydrant:diameter)}" + } + }, + { + "id": "hydrant-couplings", + "question": { + "en": "What kind of couplings does this hydrant have?" + }, + "freeform": { + "key": "couplings:type", + "placeholder": { + "en": "Coupling type" + }, + "type": "string" + }, + "mappings": [ + { + "if": "couplings:type=Storz", + "then": { + "en": "Storz coupling" + }, + "icon": { + "path": "./assets/layers/hydrant/storz.jpg", + "class": "large" + } + }, + { + "if": "couplings:type=UNI", + "then": { + "en": "UNI coupling" + } + }, + { + "if": "couplings:type=Barcelona", + "then": { + "en": "Barcelona coupling" + }, + "icon": { + "path": "./assets/layers/hydrant/barcelona.jpg", + "class": "large" + } + } + ], + "multiAnswer": true, + "render": { + "en": "Couplings: {couplings:type}" + } + }, + { + "id": "hydrant-couplings-diameters", + "question": { + "en": "What diameter are the couplings of this hydrant?" + }, + "freeform": { + "key": "couplings:diameters", + "placeholder": { + "en": "Coupling diameters" + } + }, + "render": { + "en": "Coupling diameters: {couplings:diameters}" + } + }, "images" ], "presets": [ @@ -375,5 +451,31 @@ "render": "8" } } + ], + "units": [ + { + "applicableUnits": [ + { + "default": true, + "canonicalDenomination": "", + "alternativeDenomination": [ + "mm", + "millimeter", + "millimeters" + ], + "human": { + "en": "millimeters", + "nl": "millimeter" + }, + "humanSingular": { + "en": "millimeter", + "nl": "millimeter" + } + } + ], + "appliesToKey": [ + "fire_hydrant:diameter" + ] + } ] } \ No newline at end of file diff --git a/assets/layers/hydrant/license_info.json b/assets/layers/hydrant/license_info.json new file mode 100644 index 000000000..7b01ebaa2 --- /dev/null +++ b/assets/layers/hydrant/license_info.json @@ -0,0 +1,22 @@ +[ + { + "path": "barcelona.jpg", + "license": "CC-BY-SA", + "authors": [ + "CLIGNER" + ], + "sources": [ + "https://commons.wikimedia.org/wiki/File:Gama_racores_UNE23400_ligatura.JPG" + ] + }, + { + "path": "storz.jpg", + "license": "CC-BY-SA", + "authors": [ + "Karl Gruber" + ], + "sources": [ + "https://commons.wikimedia.org/wiki/File:Festkupplung.jpg" + ] + } +] \ No newline at end of file diff --git a/assets/layers/hydrant/storz.jpg b/assets/layers/hydrant/storz.jpg new file mode 100644 index 000000000..55dc2a5db Binary files /dev/null and b/assets/layers/hydrant/storz.jpg differ diff --git a/test.ts b/test.ts index 5db0859a6..e69de29bb 100644 --- a/test.ts +++ b/test.ts @@ -1,93 +0,0 @@ -import {Utils} from "./Utils"; -import Loading from "./UI/Base/Loading"; -import {UIEventSource} from "./Logic/UIEventSource"; -import {VariableUiElement} from "./UI/Base/VariableUIElement"; -import ChartJs from "./UI/Base/ChartJs"; -import Combine from "./UI/Base/Combine"; - - -const homeUrl = "https://raw.githubusercontent.com/pietervdvn/MapComplete/develop/Docs/Tools/stats/" -const stats_files = "file-overview.json" -const index = UIEventSource.FromPromise(Utils.downloadJson(homeUrl + stats_files)) - - -interface ChangeSetData { - "id": number, - "type": "Feature", - "geometry": { - "type": "Polygon", - "coordinates": [number, number][][] - }, - "properties": { - "check_user": null, - "reasons": [], - "tags": [], - "features": [], - "user": string, - "uid": string, - "editor": string, - "comment": string, - "comments_count": number, - "source": string, - "imagery_used": string, - "date": string, - "reviewed_features": [], - "create": number, - "modify": number, - "delete": number, - "area": number, - "is_suspect": boolean, - "harmful": any, - "checked": boolean, - "check_date": any, - "metadata": { - "host": string, - "theme": string, - "imagery": string, - "language": string - } - } -} - - -new VariableUiElement(index.map(paths => { - if (paths === undefined) { - return new Loading("Loading overview...") - } - const downloaded = new UIEventSource<{ features: ChangeSetData[] }[]>([]) - - for (const filepath of paths) { - Utils.downloadJson(homeUrl + filepath).then(data => { - downloaded.data.push(data) - downloaded.ping() - }) - } - - return new VariableUiElement(downloaded.map(downloaded => { - const themeBreakdown = new Map() - for (const feats of downloaded) { - console.log("Feats:", feats) - for (const feat of feats.features) { - const key = feat.properties.metadata.theme - const count = themeBreakdown.get(key) ?? 0 - themeBreakdown.set(key, count + 1) - } - } - - const keys = Array.from(themeBreakdown.keys()) - const values = keys.map( k => themeBreakdown.get(k)) - - console.log(keys, values) - return new Combine([ - "Got " + downloaded.length + " files out of " + paths.length, - new ChartJs({ - type: "pie", - data: { - datasets: [{data: values}], - labels: keys - } - }).SetClass("w-1/3 h-full") - ]).SetClass("block w-full h-full") - })).SetClass("block w-full h-full") -})).SetClass("block w-full h-full").AttachTo("maindiv") -