#!/usr/bin/env python3 # Simple as of now. import re def _dumbload(f) -> list[tuple[int, str]]: """Loads file into list of lines with their indentations""" tabs = re.compile(r'^\t*') return [(tabs.match(line).end(), line[tabs.match(line).end():]) for line in f] def _load(f): """Loads state file into tuples of the sections""" dumb = _dumbload(f) maxdepth = max(x[0] for x in dumb) state = [None] * (maxdepth+1) result = [] for depth, line in dumb: line = line.strip() if line == '': continue state[depth] = line for x in range(depth+1, maxdepth+1): state[x] = None result.append(state.copy()) # It's all strings, so OK. return result def load(f) -> dict[tuple[str, str], list[str]]: """Loads state file into dictionaries area+router/network -> list of parameters""" # FIXME: Shouldn't we just create a ton of ordered dictionaries? # i.e. area -> router -> param -> None; all string. params = _load(f) result = {} for x in params: if x[-1] is None: continue # FIXME: Not working for general output. k = (x[0], x[1]) if k not in result: result[k] = [] result[k].append(' '.join(x[2:])) return result def create_graph(d): """takes the dict from load() and returns list of edges. The graph is bipartite, one part is the routers, other is the networks""" edges = [] names = {} for k, v in d.items(): v1 = k[1] for l in v: # UGLY! if v1.startswith('router') and l.startswith(('network', 'stubnet', 'external')): m = re.match(r'^([^ ]+ [^ ]+) metric ([0-9]+)$', l) v2 = m.group(1) metric = int(m.group(2)) edges.append((v1, v2, metric)) if v1.startswith('network') and l.startswith('address'): names[v1] = l # NOTE: Not all networks have reasonable address (external, stubnets), so they will not be listed. return edges, names if __name__ == '__main__': #from pprint import pprint #pprint(create_graph(load(open('state')))) edges, names = create_graph(load(open('state'))) # Prologue: print(r'graph "Visualisation" {') for edge in edges: print(f'"{edge[0]}" -- "{edge[1]}" [label={edge[2]}];') for ident,name in names.items(): print(f'"{ident}" [label="{name}"]') # Dot falls back to vertex name, so this solves the missing keys in names. # Epi: print('}')