mirror of
https://github.com/praktimarc/kst4contest.git
synced 2026-09-13 12:45:32 +02:00
refactoring project website landing page
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -170,6 +170,9 @@ After implementation use targeted documentation-impact checks. Do not run a comp
|
|||||||
|
|
||||||
The repository contains the KST4Contest website under `website/`, published separately from the desktop application build.
|
The repository contains the KST4Contest website under `website/`, published separately from the desktop application build.
|
||||||
|
|
||||||
|
- Historical GHz-Tagung papers are published as German and English PDF assets below `website/src/assets/papers/` and explained on `/background/`. Their editable ODT sources remain outside the public Eleventy input tree and must never be copied into the generated site.
|
||||||
|
- The home-page news teaser is derived from the date-sorted Eleventy `news` tag collection. It deliberately renders nothing when that collection is empty; it must not be pinned to a release version.
|
||||||
|
|
||||||
Current website/deployment scripts and update-feed behaviour must be inspected before changes; do not rely on historical assumptions.
|
Current website/deployment scripts and update-feed behaviour must be inspected before changes; do not rely on historical assumptions.
|
||||||
|
|
||||||
- `APPLICATION_CURRENT_VERSION` is the user-visible semantic version and must use the dotted `major.minor.patch` form. `APPLICATION_CURRENTVERSIONNUMBER` is retained only for older feeds and encodes patch releases by appending the patch digit, for example `1.43.1` as `1.431`.
|
- `APPLICATION_CURRENT_VERSION` is the user-visible semantic version and must use the dotted `major.minor.patch` form. `APPLICATION_CURRENTVERSIONNUMBER` is retained only for older feeds and encodes patch releases by appending the patch digit, for example `1.43.1` as `1.431`.
|
||||||
|
|||||||
@@ -73,6 +73,12 @@ function getManualPageOrder(lang, slug) {
|
|||||||
return index >= 0 ? index : 999;
|
return index >= 0 ? index : 999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectLatestNews(newsItems) {
|
||||||
|
return [...(newsItems || [])]
|
||||||
|
.sort((first, second) => second.date - first.date)
|
||||||
|
.slice(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
function githubCompatibleSlug(value) {
|
function githubCompatibleSlug(value) {
|
||||||
return (value || "")
|
return (value || "")
|
||||||
.trim()
|
.trim()
|
||||||
@@ -152,6 +158,12 @@ module.exports = function (eleventyConfig) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
eleventyConfig.addCollection("latestNews", function (collectionApi) {
|
||||||
|
return selectLatestNews(
|
||||||
|
collectionApi.getFilteredByTag("news")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
eleventyConfig.addFilter("whereTag", function(collection, tag) {
|
eleventyConfig.addFilter("whereTag", function(collection, tag) {
|
||||||
return collection.filter(item => item.data.tags && item.data.tags.includes(tag));
|
return collection.filter(item => item.data.tags && item.data.tags.includes(tag));
|
||||||
});
|
});
|
||||||
@@ -231,3 +243,5 @@ module.exports = function (eleventyConfig) {
|
|||||||
htmlTemplateEngine: "njk"
|
htmlTemplateEngine: "njk"
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports.selectLatestNews = selectLatestNews;
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ description: About KST4Contest and its contest-oriented ON4KST workflow.
|
|||||||
<p>
|
<p>
|
||||||
The project is open source and focused on practical contest station workflows.
|
The project is open source and focused on practical contest station workflows.
|
||||||
Features are designed around real operating pressure, not theoretical UI concepts.
|
Features are designed around real operating pressure, not theoretical UI concepts.
|
||||||
|
The <a href="/background/">background and conference papers</a> explain how
|
||||||
|
work at DM5M and later analysis of archived ON4KST chat data influenced the client.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Community supported</h2>
|
<h2>Community supported</h2>
|
||||||
@@ -42,4 +44,4 @@ description: About KST4Contest and its contest-oriented ON4KST workflow.
|
|||||||
|
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,98 @@
|
|||||||
|
---
|
||||||
|
layout: base.njk
|
||||||
|
lang: en
|
||||||
|
title: Background and conference papers
|
||||||
|
description: The operating background of KST4Contest and the German and English papers presented at GHz-Tagung Dorsten in 2025 and 2026.
|
||||||
|
---
|
||||||
|
|
||||||
|
<section class="hero">
|
||||||
|
<p class="badge">Project background</p>
|
||||||
|
<h1>Background and conference papers</h1>
|
||||||
|
<p class="lead">
|
||||||
|
KST4Contest grew out of practical contest operation at DM5M. Individual
|
||||||
|
functions started with concrete problems encountered while using the ON4KST
|
||||||
|
chat; later development was also influenced by analysis of archived chat data.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section narrow">
|
||||||
|
<div class="section-heading">
|
||||||
|
<p class="eyebrow">Two points in the project history</p>
|
||||||
|
<h2>What the papers document</h2>
|
||||||
|
<p>
|
||||||
|
These papers preserve the implementation and knowledge available at the
|
||||||
|
respective GHz-Tagung. Their historical version references and plans have
|
||||||
|
deliberately not been rewritten to match the current application.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid">
|
||||||
|
<article class="card" id="paper-2025">
|
||||||
|
<p class="eyebrow">GHz-Tagung Dorsten · 2025</p>
|
||||||
|
<h3>Softwaregestützte Optimierung der Betriebstechnik von Conteststationen am Beispiel von KST4Contest</h3>
|
||||||
|
<p><strong>English title:</strong> Software-assisted optimisation of contest station operating practice using KST4Contest</p>
|
||||||
|
<p>
|
||||||
|
The paper covers the development of KST4Contest, practical contest
|
||||||
|
operating technique, the limits of conventional chat clients, Worked
|
||||||
|
information, Genius frequency and message analysis, AirScout, logger,
|
||||||
|
rotator and DX Cluster integration, and the operating and UI concept.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Marc Fröhlich, “Softwaregestützte Optimierung der Betriebstechnik von
|
||||||
|
Conteststationen am Beispiel von KST4Contest”, paper for the presentation
|
||||||
|
at <a href="https://ghztagung.darc.de/">GHz-Tagung Dorsten 2025</a>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The English edition is a translation of the German original, not a
|
||||||
|
separate publication.
|
||||||
|
</p>
|
||||||
|
<div class="actions">
|
||||||
|
<a class="button" href="/assets/papers/kst4contest-ghz-tagung-2025-de.pdf">Download German PDF</a>
|
||||||
|
<a class="button secondary" href="/assets/papers/kst4contest-ghz-tagung-2025-en.pdf">Download English PDF</a>
|
||||||
|
</div>
|
||||||
|
<p><small>German PDF · 3.4 MB · English PDF · 3.4 MB</small></p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="card" id="paper-2026">
|
||||||
|
<p class="eyebrow">GHz-Tagung Dorsten · 2026</p>
|
||||||
|
<h3>Chat-Mining: Jagdinstinkte wecken mit KST4Contest</h3>
|
||||||
|
<p><strong>English title:</strong> Chat mining: awakening hunting instincts with KST4Contest</p>
|
||||||
|
<p>
|
||||||
|
The paper examines archived ON4KST chats, presence in both categories,
|
||||||
|
activity periods, sked requests and reply behaviour, the relationship
|
||||||
|
between useful information and reply rate, and the functions derived
|
||||||
|
from those observations.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Marc Fröhlich, “Chat-Mining: Jagdinstinkte wecken mit KST4Contest”, paper
|
||||||
|
for the presentation at <a href="https://ghztagung.darc.de/">GHz-Tagung
|
||||||
|
Dorsten 2026</a>, including section “Erfolgsrezept”.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The English edition is a translation of the German original, not a
|
||||||
|
separate study.
|
||||||
|
</p>
|
||||||
|
<div class="actions">
|
||||||
|
<a class="button" href="/assets/papers/kst4contest-ghz-tagung-2026-de.pdf">Download German PDF</a>
|
||||||
|
<a class="button secondary" href="/assets/papers/kst4contest-ghz-tagung-2026-en.pdf">Download English PDF</a>
|
||||||
|
</div>
|
||||||
|
<p><small>German PDF · 1.8 MB · English PDF · 1.7 MB</small></p>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section narrow">
|
||||||
|
<div class="cta-panel">
|
||||||
|
<p class="eyebrow">Current software</p>
|
||||||
|
<h2>The papers explain the background, not today's complete feature set</h2>
|
||||||
|
<p>
|
||||||
|
For current behaviour and configuration, use the complete function
|
||||||
|
overview and the manual. The conference papers remain historical sources.
|
||||||
|
</p>
|
||||||
|
<div class="actions">
|
||||||
|
<a class="button" href="/features/">Open all functions</a>
|
||||||
|
<a class="button secondary" href="/manual/">Read the current manual</a>
|
||||||
|
<a class="button ghost" href="/">Return to the home page</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
+117
-54
@@ -15,15 +15,15 @@ visitorCount: true
|
|||||||
<h1>KST4Contest</h1>
|
<h1>KST4Contest</h1>
|
||||||
|
|
||||||
<p class="lead">
|
<p class="lead">
|
||||||
ON4KST shows you the traffic. KST4Contest helps turn it into an operating
|
KST4Contest is an ON4KST client for VHF, UHF and SHF contest operation
|
||||||
decision by combining chat, candidate prioritisation, sked planning,
|
on 144 MHz and above. It keeps active stations, frequencies, skeds and
|
||||||
AirScout data and logger integration in one desktop client.
|
aircraft-scatter opportunities in view while connecting chat information
|
||||||
|
with logger and station interfaces.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The available information is filtered, related to active stations and
|
The client helps the operator choose the next useful station and prepare
|
||||||
presented in a contest-oriented workflow. The final decision still
|
the next operating step. It does not automate the radio contact itself.
|
||||||
belongs to the operator.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
@@ -36,57 +36,71 @@ visitorCount: true
|
|||||||
<div class="hero-panel">
|
<div class="hero-panel">
|
||||||
<div class="terminal-bar">
|
<div class="terminal-bar">
|
||||||
<span></span><span></span><span></span>
|
<span></span><span></span><span></span>
|
||||||
<strong>Functions sharing the same station context</strong>
|
<strong>Contest information ready for the next decision</strong>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mock-grid">
|
<div class="mock-grid">
|
||||||
{% for feature in collections.sortedFeatures %}
|
<div class="mini-card">
|
||||||
{% if loop.index <= 6 %}
|
<strong>Active stations and QRGs</strong>
|
||||||
<div class="mini-card">
|
<small>Chat messages, recognised frequencies and known bands stay connected to the station.</small>
|
||||||
<strong>{{ feature.data.icon }} {{ feature.data.title }}</strong>
|
</div>
|
||||||
<small>{{ feature.data.summary }}</small>
|
<div class="mini-card">
|
||||||
</div>
|
<strong>Skeds and AP windows</strong>
|
||||||
{% endif %}
|
<small>Scheduled contacts and AirScout timing remain visible while the contest continues.</small>
|
||||||
{% endfor %}
|
</div>
|
||||||
|
<div class="mini-card">
|
||||||
|
<strong>Logger and station status</strong>
|
||||||
|
<small>Worked information, the current TRX QRG and rotor direction inform the same workflow.</small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{% if collections.latestNews.length %}
|
||||||
|
{% set latestPost = collections.latestNews[0] %}
|
||||||
|
<section class="section narrow" aria-labelledby="latest-news-heading">
|
||||||
|
<article class="card">
|
||||||
|
<p class="eyebrow">Latest news · {{ latestPost.date | readableDate }}</p>
|
||||||
|
<h2 id="latest-news-heading"><a href="{{ latestPost.url }}">{{ latestPost.data.title }}</a></h2>
|
||||||
|
<p>{{ latestPost.data.summary }}</p>
|
||||||
|
<a href="{{ latestPost.url }}">Open this update →</a>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<section class="section">
|
<section class="section">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<p class="eyebrow">The operating problem</p>
|
<p class="eyebrow">Practical tasks</p>
|
||||||
<h2>The useful station is rarely the only station in the chat</h2>
|
<h2>From chat traffic to the next operating step</h2>
|
||||||
<p>
|
<p>
|
||||||
During an active contest, messages, sked requests, frequency information
|
Messages, station activity and station interfaces provide different
|
||||||
and band changes arrive continuously. The task is to identify which part
|
pieces of the same operating situation. KST4Contest brings them together
|
||||||
of that traffic matters now, which candidate should be monitored and
|
where they are needed.
|
||||||
which contact is better scheduled for later.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<article class="card">
|
<article class="card">
|
||||||
<h3>Observe</h3>
|
<h3>Keep track of chat and active stations</h3>
|
||||||
<p>
|
<p>
|
||||||
Messages, locators, detected frequencies and known band activity are
|
Follow messages across two ON4KST categories, see active bands and keep
|
||||||
assigned to stations across as many as two ON4KST chat categories.
|
recognised frequencies attached to the callsign that sent them.
|
||||||
</p>
|
</p>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article class="card">
|
<article class="card">
|
||||||
<h3>Evaluate</h3>
|
<h3>Select and plan contacts</h3>
|
||||||
<p>
|
<p>
|
||||||
Direction, distance, worked status, NOT-QRV information, chat activity,
|
Use filters and priorities to find candidates, schedule skeds and keep
|
||||||
sked context and aircraft scatter data feed filters and candidate scores.
|
their timing visible in the timeline together with AirScout data.
|
||||||
</p>
|
</p>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article class="card">
|
<article class="card">
|
||||||
<h3>Act</h3>
|
<h3>Connect logger and station components</h3>
|
||||||
<p>
|
<p>
|
||||||
Candidates can be contacted, scheduled or monitored. Skeds remain
|
Synchronise Worked status with supported loggers and pass useful context
|
||||||
visible, while supported loggers and station interfaces receive the
|
to the TRX, rotator and local DX Cluster interfaces.
|
||||||
information required for the next operating step.
|
|
||||||
</p>
|
</p>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
@@ -94,25 +108,77 @@ visitorCount: true
|
|||||||
|
|
||||||
<section class="section">
|
<section class="section">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<p class="eyebrow">Functions</p>
|
<p class="eyebrow">What the chat data showed</p>
|
||||||
<h2>One workflow, shared context</h2>
|
<h2>Useful detail makes a reply easier</h2>
|
||||||
<p>
|
<p>
|
||||||
The individual functions are not isolated tools. They use the same
|
Archived ON4KST chat logs from several IARU contests in the preceding two
|
||||||
station, message, band and timing information, so that a change in one
|
years were analysed. The concrete example comes from the July 2025 contest
|
||||||
part of the workflow can also affect filters, priorities and reminders.
|
and combines the 144/432 MHz and Microwave categories. It compares sked
|
||||||
|
requests with the replies and sked windows they produced.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The text analysis considered action and sked words, frequency, timing,
|
||||||
|
beam direction, aircraft-scatter information, locator, mode and courtesy
|
||||||
|
or anchor words. Within this sample, requests containing AP and beam
|
||||||
|
information were associated with an almost 30% higher chat reply rate
|
||||||
|
than short, unspecific requests such as “Hi noname, try 2m?”.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This measures chat replies, not completed QSOs. It is a correlation within
|
||||||
|
the investigated sample, not general proof of causation and not a promise
|
||||||
|
that an individual sked will succeed. The practical point is modest:
|
||||||
|
information that can be used immediately saves the other operator from
|
||||||
|
having to ask for it first. KST4Contest supplies part of that context when
|
||||||
|
preparing messages and skeds.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Source: Marc Fröhlich, “Chat-Mining: Jagdinstinkte wecken mit KST4Contest”,
|
||||||
|
conference paper for GHz-Tagung Dorsten 2026, section “Erfolgsrezept”.
|
||||||
|
<a href="/background/#paper-2026">Read the background and download the paper</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section">
|
||||||
|
<div class="section-heading">
|
||||||
|
<p class="eyebrow">Selected functions</p>
|
||||||
|
<h2>The parts most often used during a contest</h2>
|
||||||
|
<p>
|
||||||
|
These examples show how station, band, message and timing information is
|
||||||
|
used in practice. The complete function overview remains available for
|
||||||
|
configuration details and less frequently used tools.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
{% for feature in collections.sortedFeatures %}
|
<article class="card feature-card">
|
||||||
<article class="card feature-card">
|
<h3><a href="/features/global-message-views/">Chat overview and station filters</a></h3>
|
||||||
<div class="feature-icon">{{ feature.data.icon }}</div>
|
<p>Separate global and private views keep the traffic readable, while station filters narrow the candidate list without hiding the underlying chat context.</p>
|
||||||
<p class="eyebrow">{{ feature.data.category }}</p>
|
</article>
|
||||||
<h3><a href="{{ feature.url }}">{{ feature.data.title }}</a></h3>
|
<article class="card feature-card">
|
||||||
<p>{{ feature.data.summary }}</p>
|
<h3><a href="/features/priority-score/">Priority and band opportunities</a></h3>
|
||||||
<a href="{{ feature.url }}">Read how it works →</a>
|
<p>Candidate scores combine available station information with Worked and band state so that a useful next call is easier to find.</p>
|
||||||
</article>
|
</article>
|
||||||
{% endfor %}
|
<article class="card feature-card">
|
||||||
|
<h3><a href="/features/timeline/">Skeds and AP timeline</a></h3>
|
||||||
|
<p>Manual skeds, reminders and aircraft-scatter windows remain visible instead of disappearing in the continuing chat stream.</p>
|
||||||
|
</article>
|
||||||
|
<article class="card feature-card">
|
||||||
|
<h3><a href="/features/airscout/">AirScout and path information</a></h3>
|
||||||
|
<p>AirScout data adds timing and path context to a selected station without turning that assessment into a propagation promise.</p>
|
||||||
|
</article>
|
||||||
|
<article class="card feature-card">
|
||||||
|
<h3><a href="/features/log-sync/">Logger and Worked synchronisation</a></h3>
|
||||||
|
<p>Supported logger data updates global and per-band Worked information across the active callsign variants.</p>
|
||||||
|
</article>
|
||||||
|
<article class="card feature-card">
|
||||||
|
<h3><a href="/features/trx-qrg-synchronisation/">TRX, rotator and DX Cluster integration</a></h3>
|
||||||
|
<p>The current QRG, rotor direction and local spots carry selected station information into the next manual operating step.</p>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="actions">
|
||||||
|
<a class="button secondary" href="/features/">Open the complete function overview</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -121,10 +187,9 @@ visitorCount: true
|
|||||||
<p class="eyebrow">Limits</p>
|
<p class="eyebrow">Limits</p>
|
||||||
<h2>A priority score is not a propagation forecast</h2>
|
<h2>A priority score is not a propagation forecast</h2>
|
||||||
<p>
|
<p>
|
||||||
KST4Contest can only evaluate the information it knows. Scores, AP
|
Priorities are not a propagation forecast. Scores, filters and AP windows
|
||||||
windows, filters and path profiles support the operator's decision; they
|
depend on the data available to the client. They help with sorting and
|
||||||
do not guarantee a contact. If the input data is incomplete or outdated,
|
timing, but they do not guarantee a QSO.
|
||||||
the result can be incomplete or outdated as well.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
@@ -139,11 +204,9 @@ visitorCount: true
|
|||||||
<p class="eyebrow">Project status</p>
|
<p class="eyebrow">Project status</p>
|
||||||
<h2>Stable for operation, Nightly for testing</h2>
|
<h2>Stable for operation, Nightly for testing</h2>
|
||||||
<p>
|
<p>
|
||||||
KST4Contest is open-source software. The current stable release is the
|
Stable is the normal choice for contest operation. Nightly contains the
|
||||||
normal choice for contest operation. Nightly builds follow ongoing
|
latest development state and is intended for testing. Changing versions
|
||||||
development and are useful when a particular fix or feature needs
|
immediately before a contest is still not recommended.
|
||||||
testing. A few minutes before a contest is not the ideal time to discover
|
|
||||||
what changed.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
const assert = require("node:assert/strict");
|
||||||
|
const fs = require("node:fs");
|
||||||
|
const path = require("node:path");
|
||||||
|
const test = require("node:test");
|
||||||
|
|
||||||
|
const eleventyConfig = require("../.eleventy.js");
|
||||||
|
|
||||||
|
test("selects the newest news article without relying on a version", () => {
|
||||||
|
const older = { date: new Date("2026-08-22"), data: { title: "Older" } };
|
||||||
|
const newest = { date: new Date("2026-09-03"), data: { title: "Newest" } };
|
||||||
|
|
||||||
|
assert.deepEqual(
|
||||||
|
eleventyConfig.selectLatestNews([older, newest]),
|
||||||
|
[newest]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("an empty news collection omits the latest-news item safely", () => {
|
||||||
|
assert.deepEqual(eleventyConfig.selectLatestNews([]), []);
|
||||||
|
assert.deepEqual(eleventyConfig.selectLatestNews(), []);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("homepage keeps the statistical result tied to its limits", () => {
|
||||||
|
const source = fs.readFileSync(
|
||||||
|
path.join(__dirname, "../src/index.njk"),
|
||||||
|
"utf8"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.match(source, /almost 30% higher chat reply rate/);
|
||||||
|
assert.match(source, /chat replies, not completed QSOs/);
|
||||||
|
assert.match(source, /correlation within[\s\S]*not general proof of causation/);
|
||||||
|
assert.match(source, /July 2025 contest/);
|
||||||
|
assert.match(source, /144\/432 MHz and Microwave categories/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("background page links all public papers and no ODT source", () => {
|
||||||
|
const source = fs.readFileSync(
|
||||||
|
path.join(__dirname, "../src/background/index.njk"),
|
||||||
|
"utf8"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const name of [
|
||||||
|
"kst4contest-ghz-tagung-2025-de.pdf",
|
||||||
|
"kst4contest-ghz-tagung-2025-en.pdf",
|
||||||
|
"kst4contest-ghz-tagung-2026-de.pdf",
|
||||||
|
"kst4contest-ghz-tagung-2026-en.pdf"
|
||||||
|
]) {
|
||||||
|
assert.match(source, new RegExp(name.replaceAll(".", "\\.")));
|
||||||
|
}
|
||||||
|
assert.doesNotMatch(source, /\.odt\b/i);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("homepage contains one selected function grid and a complete-overview link", () => {
|
||||||
|
const source = fs.readFileSync(
|
||||||
|
path.join(__dirname, "../src/index.njk"),
|
||||||
|
"utf8"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal((source.match(/<h2>The parts most often used during a contest<\/h2>/g) || []).length, 1);
|
||||||
|
assert.match(source, /href="\/features\/"[^>]*>Open the complete function overview/);
|
||||||
|
assert.doesNotMatch(source, /Observe|Evaluate|>Act<|One workflow, shared context/);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user