Add about page

This commit is contained in:
Jakob Kordež 2024-06-30 10:57:02 +02:00
parent dbf41a9a46
commit 58e5a6ac2b
6 changed files with 155 additions and 5 deletions

View File

@ -17,6 +17,7 @@
"@sveltejs/adapter-static": "^3.0.2",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@tailwindcss/typography": "^0.5.13",
"@types/eslint": "^8.56.7",
"@types/node": "^20.14.6",
"@types/xml2js": "^0.4.14",

View File

@ -6,7 +6,7 @@
<h1 class="text-5xl font-light">Callsign Checker</h1>
<div class="mx-auto mt-2">
<!-- <a href="/about" class="text-blue-300">About</a> -->
<a href="/about" class="text-blue-300">About</a>
</div>
</div>

View File

@ -0,0 +1,89 @@
<script>
import Mail from './mail.svelte';
</script>
<div class="mx-auto mb-6 text-blue-300">
<a href="/">&lt; Home</a>
</div>
<div class="prose prose-invert mx-auto max-w-none">
<h1>About <i>Callsign Checker</i></h1>
<p>
Callsign Checker uses a <a href="https://en.wikipedia.org/wiki/Trie">prefix trie</a>
to quickly find the country / DXCC entity, CQ and ITU zones, continent, latitude and longitude and
timezone offset for a given callsign.
</p>
<h2><i>Building</i> the Trie</h2>
<p>
The <i>trie</i> is built from the <a href="https://www.country-files.com/">Country Files</a> by AD1C.
These files are regularly updated to contain the latest information about callsign prefixes and exceptions.
Parsing the files and building the trie is done beforehand and the resulting trie is then saved in
a custom text format.
</p>
<p>
Each prefix and callsign exception is added to the trie, with the corresponding DXCC entity and
other information. Once the initial trie is built, it goes through a series of optimizations to
reduce the size and remove redundant data.
</p>
<h3>Trie <i>optimizations</i></h3>
<p>
The first step is to traverse the trie and remove any fields and nodes, that when traversed, do
not change the result of the lookup. The next step is to look for any nodes that have only one
outbound edge and contain no additional information. These nodes get compressed to form a so
called <a href="https://en.wikipedia.org/wiki/Radix_tree">Radix tree</a>. Compressing the trie
is not that useful when parsing only prefixes, as these are usually very short, but when parsing
exceptions, the trie gets significantly smaller with this optimization.
</p>
<p>
Once the trie is compressed, we can continue with the next step. Analyzing the trie, we can see
that there are many nodes that match when comparing them by their outbound edges. These nodes
can be merged into a single node, the only change being the inbound edges. We do this in
multiple passes, until no more nodes can be merged. Multiple passes are needed, as merging one
node can cause another node to be mergeable. This step is the most important one, as it reduces
the trie size most significantly.
</p>
<p>
After all the optimizations are done, the node ids are reassigned to be in a continuous range.
This is done to reduce the size of the trie in the final format. The trie is then saved in a
custom text format. The format is optimized for size and speed of parsing.
</p>
<h3>Resulting trie</h3>
<p>
Using the latest <a href="https://www.country-files.com/category/big-cty/">BIG CTY</a>
file (19 June 2024) that has 27.000 prefixes + exceptions and building the raw trie makes 78.000
nodes which written in the custom format is 1.2MB. With all the optimizations applied, the trie is
reduced to 5.700 nodes and a file size of 0.2MB.
</p>
<h2><i>Traversing</i> the Trie</h2>
<p>
The beauty of using tries is that the lookup time is <i>O(n)</i>, where <i>n</i> is the length of
the callsign. This means that the lookup time is constant, no matter how many prefixes or exceptions
are in the trie.
</p>
<h2>Questions?</h2>
<p>
If you have any questions or suggestions, feel free to contact me at <Mail />.
</p>
</div>
<style lang="postcss">
h1,
h2,
h3 {
@apply font-medium;
}
</style>

View File

@ -0,0 +1,15 @@
<script lang="ts">
import { onMount } from 'svelte';
export const ssr = false;
export const prerender = false;
export const csr = true;
let mail = '';
onMount(() => {
mail = ['si', '.', 'hamradio', '@', 's52kj'].reverse().join('');
});
</script>
<a href={`mailto:${mail}`}>{mail}</a>

View File

@ -1,8 +1,10 @@
import typography from '@tailwindcss/typography';
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {}
},
plugins: []
plugins: [typography]
};

View File

@ -403,6 +403,16 @@
svelte-hmr "^0.16.0"
vitefu "^0.2.5"
"@tailwindcss/typography@^0.5.13":
version "0.5.13"
resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.13.tgz#cd788a4fa4d0ca2506e242d512f377b22c1f7932"
integrity sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==
dependencies:
lodash.castarray "^4.4.0"
lodash.isplainobject "^4.0.6"
lodash.merge "^4.6.2"
postcss-selector-parser "6.0.10"
"@types/cookie@^0.6.0":
version "0.6.0"
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5"
@ -1545,6 +1555,16 @@ locate-path@^6.0.0:
dependencies:
p-locate "^5.0.0"
lodash.castarray@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115"
integrity sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==
lodash.isplainobject@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@ -1903,6 +1923,14 @@ postcss-scss@^4.0.9:
resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-4.0.9.tgz#a03c773cd4c9623cb04ce142a52afcec74806685"
integrity sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==
postcss-selector-parser@6.0.10:
version "6.0.10"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d"
integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
dependencies:
cssesc "^3.0.0"
util-deprecate "^1.0.2"
postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz#49694cb4e7c649299fea510a29fa6577104bcf53"
@ -2134,8 +2162,16 @@ std-env@^3.5.0:
resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2"
integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
name string-width-cjs
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.1.0:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -2153,7 +2189,14 @@ string-width@^5.0.1, string-width@^5.1.2:
emoji-regex "^9.2.2"
strip-ansi "^7.0.1"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==