#!/usr/bin/python import requests import json import pickle import os.path import svgwrite import math import sys import concurrent.futures URL = "https://directory.spaceapi.io/" NORTHERNMOST = 55.05 EASTERNMOST = 15.033333 SOUTHERNMOST = 47.270108 WESTERNMOST = 5.866667 threshold = 0.10 YSPAN = NORTHERNMOST - SOUTHERNMOST XSPAN = EASTERNMOST - WESTERNMOST locations = {} ignorelist = ["Chaostreff Salzburg", "DevLoL", "CCC Basel", "Chaostreff Zürich", "ChaosStuff", "Level2", "Bastli", "Maakplek", "TkkrLab", "Hack42", "Hackerspace Nijmegen", "TDvenlo", "ACKspace"] def dist(n1, n2): y = n1[0] - n2[0] x = n1[1] - n2[1] return math.sqrt(math.pow(x, 2) + math.pow(y, 2)) def conflict(targetlist, node): returner = None for element in targetlist: if dist(node, targetlist[element]) < threshold: returner = element continue return returner def merge(n1, n2): lat = (n1[0] + n2[0]) / 2 lon = (n1[1] + n2[1]) / 2 returner = [] returner.append(lat) returner.append(lon) for i in range(2, len(n1)): returner.append(n1[i]) for i in range(2, len(n2)): returner.append(n2[i]) return returner def get_space_location(space): try: spacerequest = requests.get(url=data[space], timeout=1) spacedata = spacerequest.json() except requests.exceptions.RequestException as _: return except json.JSONDecodeError as _: return if "location" in spacedata: if "lat" in spacedata["location"]: lat = spacedata["location"]["lat"] lon = spacedata["location"]["lon"] return [float(lat), float(lon), data[space]] if os.path.isfile('locations.bin'): print("using offline data...", file=sys.stderr) with open("locations.bin", "rb") as f: locations = pickle.load(f) else: print("offline data not available, downloading...", file=sys.stderr) r = requests.get(url=URL) data = r.json() with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor: futures = {} for space in data: futures[space] = executor.submit(get_space_location, space) for space in data: location = futures[space].result() if location: locations[space] = location print("done loading space data", file=sys.stderr) for space in locations: print(space + " " + str(locations[space])) with open("locations.bin", "wb") as f: pickle.dump(locations, f, pickle.HIGHEST_PROTOCOL) print("Removing non-german points...", file=sys.stderr) german_locations = locations.copy() for space in locations: if locations[space][0] > NORTHERNMOST: del german_locations[space] elif locations[space][0] < SOUTHERNMOST: del german_locations[space] elif locations[space][1] < WESTERNMOST: del german_locations[space] elif locations[space][1] > EASTERNMOST: del german_locations[space] for space in ignorelist: del german_locations[space] finallist = {} while german_locations: n1 = next(iter(german_locations)) conflictnode = conflict(finallist, german_locations[n1]) if conflictnode == None: finallist.update({n1: german_locations[n1]}) del german_locations[n1] else: mergenode = merge(german_locations[n1], finallist[conflictnode]) del german_locations[n1] del finallist[conflictnode] german_locations.update( {"MERGED: " + n1 + " " + conflictnode: mergenode}) for space in finallist: print(str(finallist[space][0]) + " " + str(finallist[space][1]) + " {" + space + "}") dwg = svgwrite.Drawing('dots.svg', profile='tiny') dwg.add(svgwrite.image.Image(href="Karte_Deutschland.svg", size=(586, 793))) for space in finallist: ypoint = (793 - (((finallist[space][0] - SOUTHERNMOST) / YSPAN) * 793)) xpoint = ((finallist[space][1] - WESTERNMOST) / XSPAN) * 586 dwg.add(dwg.circle(center=(xpoint, ypoint), r=5, fill='green')) dwg.save() ledconf = open("conf.yml", "w") i = 0 for space in finallist: ledconf.write("#led" + str(i) + ":\n-\n") for u in range(2, len(finallist[space])): ledconf.write(" - " + finallist[space][u] + "\n") i = i + 1