waffensachkunde

Waffensachkunde – Lernsoftware für die Sachkundeprüfung nach § 7 WaffG. Barrierefrei, offline, EUPL-1.2.

/ app src shared druck umfang.ts

3,9 KB Rohdatei
app/src/shared/druck/umfang.ts — 112 Zeilen
1 /**
2 * Wie dick wird das Dokument? – die Schätzung, die vor dem Speichern dasteht.
3 *
4 * ## Warum das überhaupt nötig ist
5 *
6 * Der schlimmste gemessene Fall sind **982 Seiten**: 486 Fragen mit voller
7 * Begründung im Großdruck. Wer das ohne Vorwarnung an einen Drucker schickt,
8 * hat ein Problem. Die Zahl muss deshalb dastehen, bevor der Speicherdialog
9 * aufgeht.
10 *
11 * ## Warum die Stützstellen gemessen sind und nicht gerechnet
12 *
13 * Der erste Anlauf schätzte über eine Faustregel („rund 3000 Zeichen je
14 * A4-Seite“). Nachgemessen an wirklich gedruckten PDF lag sie um **Faktor
15 * 1,7 bis 2,8 zu niedrig** – die Fragenliste über den ganzen Katalog wurde
16 * mit 55 Seiten angekündigt und hatte 162. Eine Anzeige, die zugunsten des
17 * Nutzers irrt, ist genauso falsch wie eine, die gegen ihn irrt.
18 *
19 * Die Werte unten stammen deshalb aus Dokumenten, die mit demselben
20 * Stylesheet gebaut und mit echtem Chromium gedruckt wurden. Gezählt wurden
21 * die Seitenobjekte im PDF, nicht der erste Knoten des Seitenbaums – dieser
22 * Griff liefert bei jedem Dokument über acht Seiten die Zahl 8.
23 *
24 * ## Was die Zahl nicht ist
25 *
26 * Eine Zusage. Die Länge hängt daran, welche Fragen es trifft; eine Frage mit
27 * Abbildung und langer Begründung braucht ein Mehrfaches einer Ja/Nein-Frage.
28 * Die Oberfläche sagt deshalb „geschätzt etwa“ und nennt keine Nachkommastelle.
29 */
30
31 import type { Schriftgroesse } from './stil';
32
33 /**
34 * Gemessene Stützstellen, Seiten je Frage bei Schriftgröße „normal“.
35 *
36 * | Dokument | gemessen | Seiten |
37 * |---|---|---|
38 * | Fehlerprotokoll, Kurzerklärung | 150 Fragen | 70 |
39 * | Fehlerprotokoll, volle Begründung | 150 Fragen | 169 |
40 * | Fehlerprotokoll, volle Begründung | 486 Fragen | 539 |
41 * | Fragenliste | 575 Fragen | 162 |
42 * | Fragenliste mit Lösungsanhang | 575 Fragen | 185 |
43 */
44 const JE_FRAGE = Object.freeze({
45 fehlerKurz: 0.47,
46 fehlerVoll: 1.1,
47 fragenliste: 0.28,
48 /** Der Lösungsanhang kostet zusätzlich – 23 Seiten auf 575 Fragen. */
49 loesungsanhang: 0.04,
50 });
51
52 /** Vorspann, Quellenblock und Überschriften – unabhängig von der Fragenzahl. */
53 const GRUNDLAST = 2;
54
55 /**
56 * Großdruck gegen Normalgröße, gemessen.
57 *
58 * 162 gegen 279 Seiten bei derselben Fragenliste; beim Fehlerprotokoll mit
59 * voller Begründung 508 gegen 982. Der Faktor schwankt zwischen 1,7 und 1,9;
60 * genommen wird der obere Wert, damit die Schätzung eher zu hoch als zu
61 * niedrig ausfällt.
62 */
63 const GROSSDRUCK = 1.9;
64
65 function runden(seiten: number): number {
66 return Math.max(1, Math.round(seiten));
67 }
68
69 /** Geschätzte Seitenzahl des Fehlerprotokolls. */
70 export function seitenFehlerprotokoll(
71 fragen: number,
72 tiefe: 'kurz' | 'voll',
73 schriftgroesse: Schriftgroesse,
74 ): number {
75 if (fragen === 0) {
76 return 1;
77 }
78 const roh = GRUNDLAST + fragen * (tiefe === 'voll' ? JE_FRAGE.fehlerVoll : JE_FRAGE.fehlerKurz);
79 return runden(schriftgroesse === 'gross' ? roh * GROSSDRUCK : roh);
80 }
81
82 /** Geschätzte Seitenzahl der Fragenliste. */
83 export function seitenFragenliste(
84 fragen: number,
85 mitLoesungen: boolean,
86 schriftgroesse: Schriftgroesse,
87 ): number {
88 if (fragen === 0) {
89 return 1;
90 }
91 const roh =
92 GRUNDLAST + fragen * (JE_FRAGE.fragenliste + (mitLoesungen ? JE_FRAGE.loesungsanhang : 0));
93 return runden(schriftgroesse === 'gross' ? roh * GROSSDRUCK : roh);
94 }
95
96 /**
97 * Der Satz, der vor dem Speichern dasteht.
98 *
99 * Nennt Blatt **und** Seiten: Wer druckt, denkt in Blättern, und beidseitig
100 * ist die Hälfte. 982 Seiten sind 491 Blatt – erst diese Zahl macht klar,
101 * worum es geht.
102 */
103 export function umfangssatz(seiten: number): string {
104 const blatt = Math.ceil(seiten / 2);
105 if (seiten === 1) {
106 return 'Geschätzt eine Seite.';
107 }
108 return (
109 `Geschätzt etwa ${String(seiten)} Seiten – beidseitig gedruckt rund ${String(blatt)} Blatt. ` +
110 'Die genaue Länge hängt davon ab, welche Fragen es trifft.'
111 );
112 }