From e968b4d3449ef2d90b152e453ec686072f55eed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20Korde=C5=BE?= Date: Mon, 24 Jun 2024 09:08:37 +0200 Subject: [PATCH] Smaller changes --- scripts/clublog_prefix.py | 208 -------------------------------------- src/lib/models/trie.ts | 18 ++++ src/routes/+page.svelte | 49 +++++---- 3 files changed, 49 insertions(+), 226 deletions(-) delete mode 100644 scripts/clublog_prefix.py diff --git a/scripts/clublog_prefix.py b/scripts/clublog_prefix.py deleted file mode 100644 index 6f283fb..0000000 --- a/scripts/clublog_prefix.py +++ /dev/null @@ -1,208 +0,0 @@ -import xml.etree.ElementTree as ET -from sys import argv -from collections import defaultdict -import re - -root = ET.parse(argv[1]).getroot() - -entities = {} -prefixes = [] - - -def capitalize(s: str): - s = s.lower() - for m in re.findall(r"\b\w+", s): - s = s.replace(m, m.capitalize(), 1) - return s - - -for child in root: - if child.tag == "entities": - for entity in child: - name = adif = None - for prop in entity: - if prop.tag == "name": - name = prop.text - if prop.tag == "adif": - adif = int(prop.text) - entities[adif] = capitalize(name) - if child.tag == "prefixes": - for prefix in child: - call = entity = end = None - for prop in prefix: - if prop.tag == "call": - call = prop.text - if prop.tag == "adif": - entity = int(prop.text) - if prop.tag == "end": - end = prop.text - if end and end < "2024-06-20": - continue - # if entity != 1: - # continue - prefixes.append((call, entity)) - -# print(len(prefixes), "prefixes found") - -# Build trie - - -class Node: - counter = 0 - - def __init__(self): - Node.counter += 1 - self.id = Node.counter - self.parent: Node = None - self.children: dict[str, Node] = {} - self.entity: int = None - - -root = Node() -allNodes = [] - - -# Build trie -def insert(node: Node, prefix, entity): - if not prefix: - if node.entity and node.entity != entity: - print(f"Conflict: {node.entity} vs {entity}") - node.entity = entity - return - nextNode = node.children.get(prefix[0]) - if not nextNode: - nextNode = Node() - nextNode.parent = node - node.children[prefix[0]] = nextNode - allNodes.append(nextNode) - insert(nextNode, prefix[1:], entity) - - -for call, entity in prefixes: - insert(root, call, entity) - - -# Merge nodes -# print("Merge start,", len(allNodes), "nodes") - - -def canMerge(node: Node, other: Node): - if node.entity != other.entity: - return False - l = set(node.children.keys()).union(other.children.keys()) - return all(node.children.get(k) == other.children.get(k) for k in l) - - -def merge(first: Node, second: Node): - # if first.id > second.id: - # first, second = second, first - for k, c in second.children.items(): - c.parent = first - for k, c in second.parent.children.items(): - if c == second: - second.parent.children[k] = first - allNodes.remove(second) - - -anyChanged = True -while anyChanged: - anyChanged = False - i = 0 - while i < len(allNodes): - node = allNodes[i] - for other in allNodes: - if node != other and canMerge(node, other): - anyChanged = True - merge(node, other) - break - else: - i += 1 - -for i in range(len(allNodes)): - for j in range(i + 1, len(allNodes)): - if canMerge(allNodes[i], allNodes[j]): - raise Exception("Merge not completed") - -# for n in allNodes: -# print(n.children.items()) -# print("Merge done,", len(allNodes), "nodes left") - -# Save compiled trie - -for node in [root, *allNodes]: - if node.entity: - print(f"{node.id}={node.entity}") - for c in set(node.children.values()): - print( - f"{node.id}-{''.join(sorted(k for k, v in node.children.items() if v == c))}-{c.id}" - ) - -# Print trie - - -def rangeToStr(a: str, b: str): - if a == b: - return a - if ord(b) - ord(a) > 1: - return f"{a}-{b}" - return f"{a}{b}" - - -def toRange(s: list[str]): - s = sorted(s) - ranges = [(s[0], s[0])] - for c in s[1:]: - if ord(c) == ord(ranges[-1][1]) + 1: - ranges[-1] = (ranges[-1][0], c) - else: - ranges.append((c, c)) - return "".join(rangeToStr(a, b) for a, b in ranges) - - -defined = set() - - -def genGraphvizNode(node: Node): - label = "" if not node.entity else entities[node.entity] - shape = "circle" if not node.entity else "box" - return f' {node.id} [label="{label}" shape="{shape}"];' - - -def toGraphviz(node: Node, root=True): - ret = [] - if node in defined: - return ret - defined.add(node) - - ret.append(genGraphvizNode(node)) - - dd = defaultdict(list) - for k, c in node.children.items(): - dd[c.id].append(k.replace("/", "_")) - ret += toGraphviz(c, False) - - for k in sorted(dd.keys()): - ret.append(f' {node.id} -> {k} [label="{toRange(dd[k])}"];') - - if root: - curr = node - while curr.parent: - ret.append(genGraphvizNode(curr.parent)) - label = toRange(k for k, v in curr.parent.children.items() if v == curr) - ret.append(f' {curr.parent.id} -> {curr.id} [label="{label}"];') - curr = curr.parent - ret = "\n".join(["digraph {", *ret, "}"]) - - return ret - - -def traverse(s: str, node: Node = root): - if not s: - return node - nextNode = node.children.get(s[0]) - if not nextNode: - return None - return traverse(s[1:], nextNode) - - -# print(toGraphviz(traverse("R"))) diff --git a/src/lib/models/trie.ts b/src/lib/models/trie.ts index 494e09e..a696b2e 100644 --- a/src/lib/models/trie.ts +++ b/src/lib/models/trie.ts @@ -12,6 +12,9 @@ export class TrieNode { else this.id = ++nodeCounter; } + /** + * Insert a prefix into the trie. + */ insert(prefix: string, entity: number): void { if (!prefix) { if (this.entity && this.entity !== entity) @@ -27,12 +30,18 @@ export class TrieNode { next.insert(prefix.slice(1), entity); } + /** + * Traverse the trie to find the node that matches the prefix. + */ findRaw(prefix: string): TrieNode | null { if (!prefix) return this; const next = this.children.get(prefix[0]); return next ? next.findRaw(prefix.slice(1)) : null; } + /** + * Returns all the nodes in the trie. + */ getAllNodes(): Set { const nodes: TrieNode[] = [this]; for (const child of this.children.values()) { @@ -41,6 +50,9 @@ export class TrieNode { return new Set(nodes); } + /** + * Checks if this node can be merged with another node. + */ canMerge(other: TrieNode): boolean { if (this === other) return false; if (this.entity !== other.entity) return false; @@ -54,6 +66,9 @@ export class TrieNode { return true; } + /** + * Returns an encoded string of the whole trie. + */ encodeToString(): string { return [...this.getAllNodes()].map((n) => n._encodeToString()).join('\n'); } @@ -74,6 +89,9 @@ export class TrieNode { return s.join('\n'); } + /** + * Decodes a trie from an encoded string. + */ static decodeFromString(s: string): TrieNode { let root: TrieNode | null = null; const nodes: Map = new Map(); diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 957f6d0..9cae08c 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,29 +1,33 @@ @@ -32,7 +36,7 @@

Callsign Tester

-
Enter a callsign
+
Enter a callsign
@@ -40,40 +44,49 @@
{#if callsignData.prefixDxcc}
-

Secondary prefix

+

Secondary prefix

{callsignData.secondaryPrefix}
-
{dxccEntities.get(callsignData.prefixDxcc)?.name}
+
{dxccEntities.get(callsignData.prefixDxcc)?.name ?? '?'}
{/if} {#if callsignData.baseDxcc}
-

Prefix

+

Prefix

{callsignData.basePrefix}
-
{dxccEntities.get(callsignData.baseDxcc)?.name}
+
{dxccEntities.get(callsignData.baseDxcc)?.name ?? '?'}
{/if} {#if callsignData.secondarySuffix}
-

Secondary suffix

+

Secondary suffix

{callsignData.secondarySuffix}
{getSecondarySuffixDescription(callsignData) ?? ''}
{/if}
+ {:else if rawDxcc} +
+

Prefix

+
{callsign.slice(0, rawDxcc.prefixLength)}
+
{dxccEntities.get(rawDxcc.entity)?.name ?? '?'}
+
{/if}