Diagnoseanzeige fuer die Funktion "Zählen" ergaenzt

Der Nutzer meldet eine stark schwankende Zaehlanzeige im Livebetrieb
(3-60), obwohl dasselbe Verfahren an einem Standfoto stabil 18 liefert -
er kann aber keine Bilder hochladen und muss Messwerte daher vom
Bildschirm ablesen und durchgeben koennen.

- count-objects.js liefert additiv Zwischenwerte (Bildgroesse nach
  Normierung, Flaechen vor/nach Filterung, groesste Flaeche, typische
  Groesse, gewinnende Polaritaet) - auch bei count 0 sinnvoll belegt.
  Die eigentliche Zaehllogik bleibt unveraendert.
- count-history.js (neu): gleitender Median der letzten 9 Messungen,
  unterdrueckt einzelne Ausreisser ohne die Anzeige traege zu machen.
- main.js zeigt den Median als grosse Zahl, misst den Zeitbedarf des
  Zaehldurchlaufs und baut daraus die Diagnosezeile; der Verlauf wird
  bei jedem Funktionswechsel zurueckgesetzt.
- scan-view.js/styles.css: die grosse Zahl ist antippbar und blendet
  eine anfangs verborgene Diagnosezeile ein/aus, ohne selbst zu
  verrutschen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-30 08:56:26 +02:00
co-authored by Claude Opus 5
parent f0705a010c
commit d84c15e0d0
7 changed files with 509 additions and 68 deletions
+71
View File
@@ -0,0 +1,71 @@
// Gleitender Verlauf der letzten Zaehlmessungen (Funktion "Zählen") - die
// grosse Anzeige zeigt zusaetzlich zur rohen Messung deren Median ueber die
// letzten neun Durchlaeufe, damit ein einzelner Ausreisser (Bewegungs-
// unschaerfe, nachregelnder Autofokus) nicht sofort die Anzeige springen
// laesst. Reines, browserfreies Modul wie count-objects.js - hier ohne
// jeden Bezug zu Bilddaten, nur die Zahlenreihe selbst.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { createCountHistory, pushCount, HISTORY_WINDOW } from '../src/count-history.js';
test('leerer Verlauf: die erste Messung ist zugleich ihr eigener Median', () => {
const history = createCountHistory();
const result = pushCount(history, 18);
assert.deepEqual(result.history, [18]);
assert.equal(result.median, 18);
});
test('ein einzelner Ausreisser wird vom Median unterdrueckt', () => {
let history = createCountHistory();
// Acht stabile Messungen ...
for (let i = 0; i < 8; i += 1) {
({ history } = pushCount(history, 18));
}
// ... und ein einzelner Ausreisser (z. B. Bewegungsunschaerfe oder
// nachregelnder Autofokus, siehe Modul-Doku).
const result = pushCount(history, 60);
assert.equal(
result.median,
18,
'ein einzelner Ausreisser darf die geglaettete Anzeige nicht verschieben',
);
});
test('nach genuegend gleichbleibenden neuen Messungen folgt der Median (nicht traege)', () => {
// Der Median glaettet nur einzelne Ausreisser, nicht eine echte,
// anhaltende Aenderung (z. B. weil der Nutzer tatsaechlich Teile
// weggenommen hat) - sonst waere die Anzeige "beruhigt", aber nicht mehr
// ehrlich.
let history = createCountHistory();
for (let i = 0; i < 8; i += 1) {
({ history } = pushCount(history, 18));
}
let result;
for (let i = 0; i < HISTORY_WINDOW; i += 1) {
result = pushCount(history, 5);
history = result.history;
}
assert.equal(
result.median,
5,
'nach HISTORY_WINDOW gleichen neuen Messungen ist der alte Wert vollstaendig aus dem Fenster verdraengt',
);
});
test('das Fenster behaelt hoechstens HISTORY_WINDOW Messungen - aeltere fallen heraus', () => {
let history = createCountHistory();
for (let i = 1; i <= HISTORY_WINDOW + 3; i += 1) {
({ history } = pushCount(history, i));
}
assert.equal(history.length, HISTORY_WINDOW);
// Die drei aeltesten (1, 2, 3) sind bereits herausgefallen.
assert.deepEqual(history, [4, 5, 6, 7, 8, 9, 10, 11, 12]);
});
test('pushCount veraendert den uebergebenen Verlauf nicht (reine Funktion)', () => {
const history = createCountHistory();
const before = pushCount(history, 3).history;
const untouched = [...history];
pushCount(before, 4);
assert.deepEqual(history, untouched, 'der urspruengliche Verlauf bleibt unangetastet');
});