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
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
      then install node with `n install <node-version>`
 | 
			
		||||
    - 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 (
 | 
			
		||||
   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
 | 
			
		||||
--------------------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										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"
 | 
			
		||||
  ],
 | 
			
		||||
  "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"
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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