Merge master
This commit is contained in:
commit
470e9acc64
66 changed files with 10798 additions and 414 deletions
89
scripts/csvToGeojson.ts
Normal file
89
scripts/csvToGeojson.ts
Normal file
|
@ -0,0 +1,89 @@
|
|||
import {parse} from 'csv-parse/sync';
|
||||
import {readFileSync} from "fs";
|
||||
|
||||
var lambert72toWGS84 = function(x, y){
|
||||
|
||||
var newLongitude, newLatitude;
|
||||
|
||||
var n = 0.77164219,
|
||||
F = 1.81329763,
|
||||
thetaFudge = 0.00014204,
|
||||
e = 0.08199189,
|
||||
a = 6378388,
|
||||
xDiff = 149910,
|
||||
yDiff = 5400150,
|
||||
theta0 = 0.07604294;
|
||||
|
||||
var xReal = xDiff - x,
|
||||
yReal = yDiff - y;
|
||||
|
||||
var rho = Math.sqrt(xReal * xReal + yReal * yReal),
|
||||
theta = Math.atan(xReal / -yReal);
|
||||
|
||||
newLongitude = (theta0 + (theta + thetaFudge) / n) * 180 / Math.PI;
|
||||
newLatitude = 0;
|
||||
|
||||
for (var i = 0; i < 5 ; ++i) {
|
||||
newLatitude = (2 * Math.atan(Math.pow(F * a / rho, 1 / n) * Math.pow((1 + e * Math.sin(newLatitude)) / (1 - e * Math.sin(newLatitude)), e / 2))) - Math.PI / 2;
|
||||
}
|
||||
newLatitude *= 180 / Math.PI;
|
||||
return [newLongitude, newLatitude];
|
||||
|
||||
}
|
||||
|
||||
function main(args: string[]): void {
|
||||
|
||||
|
||||
|
||||
if (args.length == 0) {
|
||||
/* args = ["/home/pietervdvn/Downloads/Scholen/aantallen.csv",
|
||||
"/home/pietervdvn/Downloads/Scholen/perschool.csv",
|
||||
"/home/pietervdvn/Downloads/Scholen/Vestigingsplaatsen-van-scholen-gewoon-secundair-onderwijs-cleaned.csv"]
|
||||
*/
|
||||
console.log("Usage: csvToGeojson input.csv name-of-lat-field name-of-lon-field")
|
||||
return
|
||||
}
|
||||
|
||||
let file = args[0]
|
||||
if(file.startsWith("file://")){
|
||||
file = file.substr("file://".length)
|
||||
}
|
||||
const latField = args[1]
|
||||
const lonField = args[2]
|
||||
|
||||
const csvOptions = {
|
||||
columns: true,
|
||||
skip_empty_lines: true,
|
||||
trim: true
|
||||
}
|
||||
|
||||
const csv: Record<any, string>[] = parse(readFileSync(file), csvOptions)
|
||||
|
||||
const features = csv.map((csvElement, i) => {
|
||||
const lat = Number(csvElement[latField])
|
||||
const lon = Number(csvElement[lonField])
|
||||
if(isNaN(lat) || isNaN(lon)){
|
||||
throw `Not a valid lat or lon for entry ${i}: ${JSON.stringify(csvElement)}`
|
||||
}
|
||||
|
||||
|
||||
|
||||
return {
|
||||
type: "Feature",
|
||||
properties: csvElement,
|
||||
geometry: {
|
||||
type: "Point",
|
||||
coordinates: lambert72toWGS84(lon, lat)
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
console.log(JSON.stringify({
|
||||
type: "FeatureCollection",
|
||||
features
|
||||
}))
|
||||
|
||||
}
|
||||
|
||||
main(process.argv.slice(2))
|
|
@ -13,8 +13,6 @@ import PointRenderingConfigJson from "../Models/ThemeConfig/Json/PointRenderingC
|
|||
import {PrepareLayer} from "../Models/ThemeConfig/Conversion/PrepareLayer";
|
||||
import {PrepareTheme} from "../Models/ThemeConfig/Conversion/PrepareTheme";
|
||||
import {DesugaringContext} from "../Models/ThemeConfig/Conversion/Conversion";
|
||||
import LayerConfig from "../Models/ThemeConfig/LayerConfig";
|
||||
import LayerConfigJsonJSC from "../Docs/Schemas/LayerConfigJsonJSC";
|
||||
import {Utils} from "../Utils";
|
||||
|
||||
// This scripts scans 'assets/layers/*.json' for layer definition files and 'assets/themes/*.json' for theme definition files.
|
||||
|
@ -210,15 +208,43 @@ class LayerOverviewUtils {
|
|||
}
|
||||
return sharedLayers;
|
||||
}
|
||||
|
||||
private static publicLayerIdsFrom(themefiles: LayoutConfigJson[]): Set<string>{
|
||||
const publicLayers = [].concat(...themefiles
|
||||
.filter(th => !th.hideFromOverview)
|
||||
.map(th => th.layers))
|
||||
|
||||
const publicLayerIds = new Set<string>()
|
||||
for (const publicLayer of publicLayers) {
|
||||
if(typeof publicLayer === "string"){
|
||||
publicLayerIds.add(publicLayer)
|
||||
continue
|
||||
}
|
||||
if(publicLayer["builtin"] !== undefined){
|
||||
const bi = publicLayer["builtin"]
|
||||
if(typeof bi === "string"){
|
||||
publicLayerIds.add(bi)
|
||||
continue
|
||||
}
|
||||
bi.forEach(id=>publicLayerIds.add(id))
|
||||
continue
|
||||
}
|
||||
publicLayerIds.add(publicLayer.id)
|
||||
}
|
||||
return publicLayerIds
|
||||
}
|
||||
|
||||
private buildThemeIndex(knownImagePaths: Set<string>, sharedLayers: Map<string, LayerConfigJson>): Map<string, LayoutConfigJson> {
|
||||
console.log(" ---------- VALIDATING BUILTIN THEMES ---------")
|
||||
const themeFiles = ScriptUtils.getThemeFiles();
|
||||
const fixed = new Map<string, LayoutConfigJson>();
|
||||
|
||||
const publicLayers = LayerOverviewUtils.publicLayerIdsFrom(themeFiles.map(th => th.parsed))
|
||||
|
||||
const convertState: DesugaringContext = {
|
||||
sharedLayers,
|
||||
tagRenderings: this.getSharedTagRenderings()
|
||||
tagRenderings: this.getSharedTagRenderings(),
|
||||
publicLayers
|
||||
}
|
||||
for (const themeInfo of themeFiles) {
|
||||
let themeFile = themeInfo.parsed
|
||||
|
|
4098
scripts/schools/Onderwijsinstellingen.csv
Normal file
4098
scripts/schools/Onderwijsinstellingen.csv
Normal file
File diff suppressed because it is too large
Load diff
3
scripts/schools/README.md
Normal file
3
scripts/schools/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Little scripts to parse Belgian school data
|
||||
|
||||
|
152
scripts/schools/amendSchoolData.ts
Normal file
152
scripts/schools/amendSchoolData.ts
Normal file
|
@ -0,0 +1,152 @@
|
|||
import {parse} from 'csv-parse/sync';
|
||||
import {readFileSync, writeFileSync} from "fs";
|
||||
import {Utils} from "../../Utils";
|
||||
|
||||
function parseAndClean(filename: string): Record<any, string>[] {
|
||||
const csvOptions = {
|
||||
columns: true,
|
||||
skip_empty_lines: true,
|
||||
trim: true
|
||||
}
|
||||
const records: Record<any, string>[] = parse(readFileSync(filename), csvOptions)
|
||||
return records.map(r => {
|
||||
|
||||
for (const key of Object.keys(r)) {
|
||||
if (r[key].endsWith("niet van toepassing")) {
|
||||
delete r[key]
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
})
|
||||
}
|
||||
|
||||
const structuren = {
|
||||
"Voltijds Gewoon Secundair Onderwijs": "secondary",
|
||||
"Gewoon Lager Onderwijs": "primary",
|
||||
"Gewoon Kleuteronderwijs": "kindergarten",
|
||||
"Kleuteronderwijs": "kindergarten",
|
||||
"Buitengewoon Lager Onderwijs": "primary",
|
||||
"Buitengewoon Secundair Onderwijs": "secondary",
|
||||
"Buitengewoon Kleuteronderwijs": "kindergarten",
|
||||
"Deeltijds Beroepssecundair Onderwijs": "secondary"
|
||||
|
||||
}
|
||||
|
||||
const rmKeys = ["schoolnummer", "instellingstype",
|
||||
"adres", "begindatum","hoofdzetel","huisnummer","kbo-nummer",
|
||||
"beheerder(s)", "bestuur", "clb", "ingerichte hoofdstructuren", "busnummer", "crab-code", "crab-huisnr",
|
||||
"einddatum", "fax", "gemeente", "intern_vplnummer", "kbo_nummer", "lx", "ly", "niscode",
|
||||
"onderwijsniveau","onderwijsvorm","scholengemeenschap",
|
||||
"postcode", "provincie",
|
||||
"provinciecode", "soort instelling", "status erkenning", "straat", "VWO-vestigingsplaatscode", "taalstelsel",
|
||||
"net"]
|
||||
|
||||
const rename = {
|
||||
"e-mail":"email",
|
||||
"naam":"name",
|
||||
"telefoon":"phone"
|
||||
|
||||
}
|
||||
|
||||
function main() {
|
||||
const aantallen = "/home/pietervdvn/Downloads/Scholen/aantallen.csv"
|
||||
const perSchool = "/home/pietervdvn/Downloads/Scholen/perschool.csv"
|
||||
|
||||
const schoolfields = ["schoolnummer", "intern_vplnummer", "net", "naam", "hoofdzetel", "adres", "straat", "huisnummer", "busnummer", "postcode", "gemeente", "niscode", "provinciecode", "provincie", "VWO-vestigingsplaatscode", "crab-code", "crab-huisnr", "lx", "ly", "kbo-nummer", "telefoon", "fax", "e-mail", "website", "beheerder(s)", "soort instelling", "onderwijsniveau", "instellingstype", "begindatum", "einddatum", "status erkenning", "clb", "bestuur", "scholengemeenschap", "taalstelsel", "ingerichte hoofdstructuren"] as const
|
||||
|
||||
const schoolGeojson: {
|
||||
features: {
|
||||
properties: Record<(typeof schoolfields)[number], string>
|
||||
}[]
|
||||
} = JSON.parse(readFileSync("scholen.geojson", "utf8"))
|
||||
|
||||
const aantallenFields = ["schooljaar", "nr koepel", "koepel", "instellingscode", "intern volgnr vpl", "volgnr vpl", "naam instelling", "GON-school", "GOK-school", "instellingsnummer scholengemeenschap", "scholengemeenschap", "code schoolbestuur", "schoolbestuur", "type vestigingsplaats", "fusiegemeente hoofdvestigingsplaats", "straatnaam vestigingsplaats", "huisnr vestigingsplaats", "bus vestigingsplaats", "postcode vestigingsplaats", "deelgemeente vestigingsplaats", "fusiegemeente vestigingsplaats", "hoofdstructuur (code)", "hoofdstructuur", "administratieve groep (code)", "administratieve groep", "graad lager onderwijs", "pedagogische methode", "graad secundair onderwijs", "leerjaar", "A of B-stroom", "basisopties", "beroepenveld", "onderwijsvorm", "studiegebied", "studierichting", "stelsel", "okan cluster", "type buitengewoon onderwijs", "opleidingsvorm (code)", "opleidingsvorm", "fase", "opleidingen", "geslacht", "aantal inschrijvingen"] as const
|
||||
const aantallenParsed: Record<(typeof aantallenFields)[number], string>[] = parseAndClean(aantallen)
|
||||
const perschoolFields = ["schooljaar", "nr koepel", "koepel", "instellingscode", "naam instelling", "straatnaam", "huisnr", "bus", "postcode", "deelgemeente", "fusiegemeente", "aantal inschrijvingen"] as const
|
||||
const perschoolParsed: Record<(typeof perschoolFields)[number], string>[] = parseAndClean(perSchool)
|
||||
|
||||
schoolGeojson.features = schoolGeojson.features
|
||||
.filter(sch => sch.properties.lx != "0" && sch.properties.ly != "0")
|
||||
.filter(sch => sch.properties.instellingstype !== "Universiteit")
|
||||
|
||||
for (const feature of schoolGeojson.features) {
|
||||
|
||||
const props = feature.properties
|
||||
|
||||
const aantallen = aantallenParsed.filter(i => i.instellingscode == props.schoolnummer)
|
||||
|
||||
if (aantallen.length > 0) {
|
||||
|
||||
const fetch = (key: (typeof aantallenFields)[number]) => Utils.NoNull(Utils.Dedup(aantallen.map(x => x[key])))
|
||||
|
||||
props["onderwijsvorm"] = fetch("onderwijsvorm").join(";")
|
||||
|
||||
const gonSchool = aantallen.some(x => x["GON-school"] === "GON-school")
|
||||
const gokSchool = aantallen.some(x => x["GOK-school"] === "GON-school")
|
||||
const hoofdstructuur = fetch("hoofdstructuur")
|
||||
const onderwijsvorm = fetch("onderwijsvorm")
|
||||
const koepel = fetch("koepel")
|
||||
const stelsel = fetch("stelsel")
|
||||
const scholengemeenschap = fetch("scholengemeenschap")
|
||||
const graden =fetch("graad secundair onderwijs")
|
||||
graden.sort()
|
||||
let specialEducation = false
|
||||
const classification = hoofdstructuur.map(s => {
|
||||
const v = structuren[s]
|
||||
if (s.startsWith("Buitengewoon")) {
|
||||
specialEducation = true;
|
||||
}
|
||||
if (v === undefined) {
|
||||
console.error("Type not found: " + s)
|
||||
return ""
|
||||
}
|
||||
return v
|
||||
})
|
||||
props["school"] = Utils.Dedup(classification).join("; ")
|
||||
props["degrees"] = graden.join(";")
|
||||
props["koepel"] = koepel.join(";")
|
||||
props["scholengemeenschap"] = scholengemeenschap.join(";")
|
||||
props["stelsel"] = stelsel
|
||||
if (specialEducation) {
|
||||
props["school:for"] = "special_education"
|
||||
}
|
||||
if (props.taalstelsel === "Nederlandstalig") {
|
||||
props["language:nl"] = "yes"
|
||||
}
|
||||
|
||||
if(props.instellingstype === "Instelling voor deeltijds kunstonderwijs") {
|
||||
props["amenity"] = "college"
|
||||
props["school:subject"] = "art"
|
||||
}
|
||||
}
|
||||
|
||||
const schoolinfo = perschoolParsed.filter(i => i.instellingscode == props.schoolnummer)
|
||||
if (schoolinfo.length == 0) {
|
||||
// pass
|
||||
} else if (schoolinfo.length == 1) {
|
||||
props["capacity"] = schoolinfo[0]["aantal inschrijvingen"].split(";").map(i => Number(i)).reduce((sum, i) => sum + i, 0)
|
||||
} else {
|
||||
throw "Multiple schoolinfo's found for " + props.schoolnummer
|
||||
}
|
||||
|
||||
props["source:ref"] = props.schoolnummer
|
||||
|
||||
for (const renameKey in rename) {
|
||||
const into = rename[renameKey]
|
||||
if(props[renameKey] !== undefined){
|
||||
props[into] = props[renameKey]
|
||||
delete props[renameKey]
|
||||
}
|
||||
}
|
||||
|
||||
for (const rmKey of rmKeys) {
|
||||
delete props[rmKey]
|
||||
}
|
||||
|
||||
}
|
||||
writeFileSync("amended_schools.geojson", JSON.stringify(schoolGeojson), "utf8")
|
||||
|
||||
}
|
||||
|
||||
main()
|
1
scripts/schools/amended_schools.geojson
Normal file
1
scripts/schools/amended_schools.geojson
Normal file
File diff suppressed because one or more lines are too long
4098
scripts/schools/scholen.csv
Normal file
4098
scripts/schools/scholen.csv
Normal file
File diff suppressed because it is too large
Load diff
1
scripts/schools/scholen.geojson
Normal file
1
scripts/schools/scholen.geojson
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue