forked from MapComplete/MapComplete
Merge branch 'develop' into feature/upload-gpx-to-osm
This commit is contained in:
commit
9424364f3f
7 changed files with 233 additions and 96 deletions
|
@ -27,7 +27,10 @@ Devcontainer (see more details later).
|
||||||
To develop and build MapComplete, you
|
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 <repo>`)
|
0. Make a fork and clone the repository. (We recommend a shallow clone with `git clone --filter=blob:none <repo>`)
|
||||||
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
|
- 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 <node-version>`
|
then install node with `n install <node-version>`
|
||||||
- You can [use asdf to manage your runtime versions](https://asdf-vm.com/).
|
- 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#<layout configuration>` as [Query parameter](URL_Parameters.md). Note that the shorter URLs (
|
or `userlayout=true#<layout configuration>` as [Query parameter](URL_Parameters.md). Note that the shorter URLs (
|
||||||
e.g. `bookcases.html`, `aed.html`, ...) _don't_ exist on the development version.
|
e.g. `bookcases.html`, `aed.html`, ...) _don't_ exist on the development version.
|
||||||
|
|
||||||
### Dependencie
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
`make` , `python3` `g++`
|
`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
|
Automatic deployment
|
||||||
--------------------
|
--------------------
|
||||||
|
|
102
UI/StatisticsGUI.ts
Normal file
102
UI/StatisticsGUI.ts
Normal file
|
@ -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<string, number>()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
assets/layers/hydrant/barcelona.jpg
Normal file
BIN
assets/layers/hydrant/barcelona.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
|
@ -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"
|
"images"
|
||||||
],
|
],
|
||||||
"presets": [
|
"presets": [
|
||||||
|
@ -375,5 +451,31 @@
|
||||||
"render": "8"
|
"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"
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
22
assets/layers/hydrant/license_info.json
Normal file
22
assets/layers/hydrant/license_info.json
Normal file
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
assets/layers/hydrant/storz.jpg
Normal file
BIN
assets/layers/hydrant/storz.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
93
test.ts
93
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<string, number>()
|
|
||||||
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")
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue