forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			113 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { appendFileSync, existsSync, readFileSync, writeFileSync } from "fs"
 | 
						|
import { GeoOperations } from "../../Logic/GeoOperations"
 | 
						|
import ScriptUtils from "../ScriptUtils"
 | 
						|
import { Utils } from "../../Utils"
 | 
						|
 | 
						|
async function main(args: string[]) {
 | 
						|
    ScriptUtils.fixUtils()
 | 
						|
    const pointCandidates = JSON.parse(readFileSync(args[0], "utf8"))
 | 
						|
    const postcodes = JSON.parse(readFileSync(args[1], "utf8"))
 | 
						|
    const output = args[2] ?? "centralCoordinates.csv"
 | 
						|
 | 
						|
    const perPostCode = new Map<string, any[]>()
 | 
						|
 | 
						|
    const alreadyLoaded = new Set<number>()
 | 
						|
    if (existsSync(output)) {
 | 
						|
        const lines = readFileSync(output, { encoding: "utf8" }).split("\n")
 | 
						|
        lines.shift()
 | 
						|
        lines.forEach((line) => {
 | 
						|
            const postalCode = Number(line.split(",")[0])
 | 
						|
            alreadyLoaded.add(postalCode)
 | 
						|
        })
 | 
						|
    } else {
 | 
						|
        writeFileSync(output, "postal_code,lon,lat\n", { encoding: "utf8" })
 | 
						|
    }
 | 
						|
 | 
						|
    for (const boundary of postcodes.features) {
 | 
						|
        const postcode = boundary.properties.nouveau_PO
 | 
						|
        if (alreadyLoaded.has(Number(postcode))) {
 | 
						|
            console.log("Skipping ", postcode, "as already loaded")
 | 
						|
            continue
 | 
						|
        }
 | 
						|
        if (perPostCode.has(postcode)) {
 | 
						|
            perPostCode.get(postcode).push(boundary)
 | 
						|
        } else {
 | 
						|
            perPostCode.set(postcode, [boundary])
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    for (const postcode of Array.from(perPostCode.keys())) {
 | 
						|
        const boundaries = perPostCode.get(postcode)
 | 
						|
        const candidates = []
 | 
						|
        for (const boundary of boundaries) {
 | 
						|
            for (const candidate of pointCandidates.features) {
 | 
						|
                if (!GeoOperations.inside(candidate, boundary)) {
 | 
						|
                    // console.log(JSON.stringify(candidate))
 | 
						|
                    continue
 | 
						|
                }
 | 
						|
                candidates.push(candidate.geometry.coordinates)
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (candidates.length === 0) {
 | 
						|
            console.log(
 | 
						|
                "Postcode ",
 | 
						|
                postcode,
 | 
						|
                "has",
 | 
						|
                candidates.length,
 | 
						|
                "candidates, using centerpoint instead"
 | 
						|
            )
 | 
						|
            candidates.push(
 | 
						|
                ...boundaries.map((boundary) => GeoOperations.centerpointCoordinates(boundary))
 | 
						|
            )
 | 
						|
        }
 | 
						|
 | 
						|
        const url =
 | 
						|
            "https://staging.anyways.eu/routing-api/v1/routes?access_token=postal_code_script&turn_by_turn=false&format=geojson&language=en"
 | 
						|
        const depPoints: [number, number][] = Utils.NoNull(
 | 
						|
            await Promise.all(
 | 
						|
                candidates.map(async (candidate) => {
 | 
						|
                    try {
 | 
						|
                        const result = await Utils.downloadJson(
 | 
						|
                            url +
 | 
						|
                                "&loc=" +
 | 
						|
                                candidate.join("%2C") +
 | 
						|
                                "&loc=3.22000%2C51.21577&profile=car.short"
 | 
						|
                        )
 | 
						|
                        const depPoint = result.features.filter(
 | 
						|
                            (f) => f.geometry.type === "LineString"
 | 
						|
                        )[0].geometry.coordinates[0]
 | 
						|
                        return <[number, number]>[depPoint[0], depPoint[1]] // Drop elevation
 | 
						|
                    } catch (e) {
 | 
						|
                        console.error("No result or could not calculate a route")
 | 
						|
                    }
 | 
						|
                })
 | 
						|
            )
 | 
						|
        )
 | 
						|
 | 
						|
        const centers = boundaries.map((b) => GeoOperations.centerpointCoordinates(b))
 | 
						|
        const center = GeoOperations.centerpointCoordinates({
 | 
						|
            type: "Feature",
 | 
						|
            geometry: {
 | 
						|
                type: "LineString",
 | 
						|
                coordinates: centers,
 | 
						|
            },
 | 
						|
        })
 | 
						|
 | 
						|
        depPoints.sort(
 | 
						|
            (c0, c1) =>
 | 
						|
                GeoOperations.distanceBetween(c0, center) -
 | 
						|
                GeoOperations.distanceBetween(c1, center)
 | 
						|
        )
 | 
						|
        console.log(
 | 
						|
            "Sorted departure point candidates for ",
 | 
						|
            postcode,
 | 
						|
            " are ",
 | 
						|
            JSON.stringify(depPoints)
 | 
						|
        )
 | 
						|
        appendFileSync(output, [postcode, ...depPoints[0]].join(", ") + "\n", { encoding: "utf8" })
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
let args = [...process.argv]
 | 
						|
args.splice(0, 2)
 | 
						|
main(args).then((_) => console.log("Done!"))
 |