<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Digital Humanities |</title><link>https://clementgodbarge.com/nl/category/digital-humanities/</link><atom:link href="https://clementgodbarge.com/nl/category/digital-humanities/index.xml" rel="self" type="application/rss+xml"/><description>Digital Humanities</description><generator>HugoBlox Kit (https://hugoblox.com)</generator><language>nl-nl</language><lastBuildDate>Tue, 05 May 2026 00:00:00 +0000</lastBuildDate><image><url>https://clementgodbarge.com/media/icon_hu_64a6c3bec25b3d7b.png</url><title>Digital Humanities</title><link>https://clementgodbarge.com/nl/category/digital-humanities/</link></image><item><title>tei-mcp v0.3: TEI coderen zonder de bron te herschrijven</title><link>https://clementgodbarge.com/nl/post/tei-mcp-span-locked/</link><pubDate>Tue, 05 May 2026 00:00:00 +0000</pubDate><guid>https://clementgodbarge.com/nl/post/tei-mcp-span-locked/</guid><description>&lt;p&gt;Toen ik
, was het doel te
voorkomen dat AI-assistenten TEI-markup hallucineren. Schemaverankering loste
een deel van het probleem op: met rechtstreekse, op tools gebaseerde toegang
tot de P5-specificatie hoeft het model niet langer te raden wat een element
betekent of welke attributen het aanvaardt. De uitvoer valideert.&lt;/p&gt;
&lt;p&gt;Maar hallucinatie heeft bij TEI-codering twee gezichten, en het schema vangt
er maar één van op. Validatie tegen de specificatie vertelt je dat de &lt;em&gt;markup&lt;/em&gt;
welgevormd is. Ze zegt niets over de &lt;em&gt;tekst&lt;/em&gt; die de markup omsluit. En juist
daar – in de tekst zelf – schuilen de schadelijkste hallucinaties.
Span-locked composition, het paradepaardje van v0.3, is speciaal ontworpen
om die te voorkomen.&lt;/p&gt;
&lt;details class="print:hidden xl:hidden" &gt;
&lt;summary&gt;Inhoudsopgave&lt;/summary&gt;
&lt;div class="text-sm"&gt;
&lt;nav id="TableOfContents"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#de-hallucinatie-die-het-schema-niet-kan-vangen"&gt;De hallucinatie die het schema niet kan vangen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#span-locked-composition"&gt;Span-locked composition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#wat-dit-is-en-wat-het-niet-is"&gt;Wat dit is, en wat het niet is&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#waarom-dit-verder-reikt-dan-tei"&gt;Waarom dit verder reikt dan TEI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#de-update-ophalen"&gt;De update ophalen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;h2 id="de-hallucinatie-die-het-schema-niet-kan-vangen"&gt;De hallucinatie die het schema niet kan vangen&lt;/h2&gt;
&lt;p&gt;Vraag een model een zestiende-eeuwse Franse brief te coderen en je krijgt vaak
een TEI-document terug dat er onberispelijk uitziet. De header is ingevuld, de
&lt;code&gt;&amp;lt;persName&amp;gt;&lt;/code&gt;-tags staan op de juiste plaats, de &lt;code&gt;&amp;lt;dateline&amp;gt;&lt;/code&gt; is welgevormd. Haal
het door &lt;code&gt;validate_document&lt;/code&gt; en het slaagt.&lt;/p&gt;
&lt;p&gt;Vergelijk dan de lopende tekst met de bron.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mesme&lt;/code&gt; is &lt;code&gt;même&lt;/code&gt; geworden. Een komma is verhuisd. &lt;code&gt;luy&lt;/code&gt; is stilzwijgend
gemoderniseerd tot &lt;code&gt;lui&lt;/code&gt;. Een zinsdeel dat in het handschrift moeilijk leesbaar
was, is “verbeterd” tot iets netters. Om geen van die wijzigingen is gevraagd.
Geen ervan wordt gemeld. Het document is schemageldig en in alle stilte fout.&lt;/p&gt;
&lt;p&gt;Voor een archivistische workflow – waarin de gecodeerde tekst de blijvende
versie wordt waarop latere lezers, zoekindexen en citaties vertrouwen – is dit
de faalwijze die er het meest toe doet. Een misvormde tag is vervelend. Een
gemoderniseerde spelling die vijf jaar lang niemand opmerkt, is een corruptie.&lt;/p&gt;
&lt;h2 id="span-locked-composition"&gt;Span-locked composition&lt;/h2&gt;
&lt;p&gt;De nieuwe versie (v0.3) bevat een mechanisme tegen hallucinaties dat precies
op deze faalwijze mikt. Het ontwerpdoel is hallucinaties in de lopende tekst
per constructie onmogelijk te maken, niet alleen onwaarschijnlijk.&lt;/p&gt;
&lt;p&gt;Het idee is eenvoudig: &lt;strong&gt;het model typt nooit lopende tekst&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;De workflow ziet er in plaats daarvan zo uit:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Het model roept &lt;code&gt;get_source(&amp;quot;letter_001&amp;quot;)&lt;/code&gt; aan en ontvangt de platte
brontekst als onveranderlijke string.&lt;/li&gt;
&lt;li&gt;Voor elke tag die het wil aanbrengen, roept het
&lt;code&gt;tag_span(&amp;quot;letter_001&amp;quot;, start, end, element_path, attrs)&lt;/code&gt; aan – het
registreert daarmee een TEI-element op een tekenbereik in de bron.&lt;/li&gt;
&lt;li&gt;Is het klaar, dan roept het &lt;code&gt;compose(&amp;quot;letter_001&amp;quot;)&lt;/code&gt; aan. De server vlecht
de geregistreerde tags door de oorspronkelijke platte tekst, rendert de
definitieve TEI en controleert vervolgens &lt;em&gt;byte voor byte&lt;/em&gt; of de platte
tekstinhoud van het gerenderde document gelijk is aan de bron.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Komen de bytes overeen, dan komt het document terug. Zo niet – als de tags van
het model op een of andere manier een lopende tekst impliceren die ook maar één
teken van de bron afwijkt – dan werpt &lt;code&gt;compose()&lt;/code&gt; een fout op in plaats van een
corrupt document terug te geven.&lt;/p&gt;
&lt;p&gt;Er is geen route door deze workflow waarlangs het model een TEI-document
produceert waarvan de lopende tekst van de bron afwijkt. De invariant is
mechanisch, niet gedragsmatig. Je hoeft er niet op te vertrouwen dat het model
niet hallucineert; je hoeft alleen te vertrouwen op een &lt;code&gt;==&lt;/code&gt;-vergelijking
tussen twee bytestrings.&lt;/p&gt;
&lt;h2 id="wat-dit-is-en-wat-het-niet-is"&gt;Wat dit is, en wat het niet is&lt;/h2&gt;
&lt;p&gt;Span-locked composition is een &lt;strong&gt;aanvulling&lt;/strong&gt; op schemaverankering, geen
vervanging ervan. De tools voor schemaverankering (&lt;code&gt;validate_document&lt;/code&gt;,
&lt;code&gt;lookup_element&lt;/code&gt;, &lt;code&gt;valid_children&lt;/code&gt; en de rest van de oorspronkelijke zestien)
helpen het model &lt;em&gt;geldige&lt;/em&gt; TEI te produceren. Span-locked composition
garandeert dat de lopende tekst binnen die TEI &lt;em&gt;trouw&lt;/em&gt; is aan de bron. Een
inzetbare codeerworkflow moet aan beide eisen voldoen, en nu dekt één server
ze allebei.&lt;/p&gt;
&lt;p&gt;Het is ook geen wondermiddel voor alles. &lt;code&gt;compose()&lt;/code&gt; controleert nog niet of
de geregistreerde tags toelaatbaar zijn volgens een geladen ODD-customisatie –
dat komt later. Geregistreerde tags leven in het procesgeheugen en overleven
een herstart niet. En de bronbestanden moeten leesbaar zijn vanaf de plek waar
de server draait. Dat valt allemaal op te lossen; niets ervan ondergraaft de
kerninvariant.&lt;/p&gt;
&lt;h2 id="waarom-dit-verder-reikt-dan-tei"&gt;Waarom dit verder reikt dan TEI&lt;/h2&gt;
&lt;p&gt;Het patroon laat zich veralgemenen. Telkens wanneer een model wordt gevraagd
een stuk tekst te annoteren, te transformeren of te omsluiten – en telkens
wanneer de integriteit van de onderliggende tekst zwaarder weegt dan het
vermogen van het model om die te “verbeteren” – past dezelfde vorm van
oplossing. Vraag het model niet de tekst over te typen. Vraag het instructies
over de tekst te produceren, en laat een deterministische composer die
toepassen onder een gelijkheidsinvariant.&lt;/p&gt;
&lt;p&gt;Voor digitale edities in het bijzonder verandert dit wat je een model
verantwoord kunt vragen. Coderen wordt ineens een taak die je kunt delegeren
zonder elke uitvoer handmatig met de bron te hoeven vergelijken. De machine
neemt de saaie weg; de editeur beoordeelt de markup, niet de spelling.&lt;/p&gt;
&lt;h2 id="de-update-ophalen"&gt;De update ophalen&lt;/h2&gt;
&lt;p&gt;Heb je tei-mcp al geïnstalleerd:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uvx tei-mcp@latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of bij een nieuwe installatie:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install tei-mcp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Om span-locked composition te gebruiken, wijs je de server naar een map met
platte bronbestanden:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;TEI_MCP_SPAN_SOURCE_ROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/path/to/sources
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uvx tei-mcp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;De naam van elk bestand (zonder extensie) wordt zijn document-ID
(&lt;code&gt;letter_001.txt&lt;/code&gt; → &lt;code&gt;letter_001&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Broncode, volledige documentatie en de ontwerpnotities bij de invariant:
&lt;/p&gt;</description></item><item><title>Een ander soort digitale editie</title><link>https://clementgodbarge.com/nl/post/cavriana-edition/</link><pubDate>Tue, 24 Mar 2026 00:00:00 +0000</pubDate><guid>https://clementgodbarge.com/nl/post/cavriana-edition/</guid><description>&lt;p&gt;De meeste primaire bronnen worden nooit gepubliceerd. Het model waarop we vertrouwen om daar iets aan te doen – de gesubsidieerde digitale editie – is te duur, te gecentraliseerd en te kwetsbaar om op grote schaal te werken. Ik heb zojuist
gepubliceerd waarin ik uitleg waarom ik de kritische editie van Cavriana’s brieven anders opbouw: gedigitaliseerde primaire bronnen die organisch groeien, met minimale infrastructuur, geautomatiseerd onderhoud, open voor samenwerking, en zo goedkoop dat er niet eens subsidies voor nodig zijn. Het is een pleidooi voor een soort digital humanities dat werkt, met of zonder institutionele steun.&lt;/p&gt;</description></item><item><title>tei-mcp: TEI P5 voor AI-agents</title><link>https://clementgodbarge.com/nl/post/tei-mcp/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate><guid>https://clementgodbarge.com/nl/post/tei-mcp/</guid><description>&lt;p&gt;Wie ooit een AI-codeerassistent TEI-XML heeft laten schrijven, heeft het vast
gemerkt: het gaat mis. Elementen duiken op waar ze niet horen. Attributen worden
verzonnen. Nestingregels worden genegeerd. Het model heeft een ruw idee van hoe
TEI eruitziet, maar geen betrouwbare kennis van de specificatie.&lt;/p&gt;
&lt;p&gt;tei-mcp lost dat op door AI-agents rechtstreeks, via tools, toegang te geven tot
de TEI P5 Guidelines.&lt;/p&gt;
&lt;details class="print:hidden xl:hidden" &gt;
&lt;summary&gt;Inhoudsopgave&lt;/summary&gt;
&lt;div class="text-sm"&gt;
&lt;nav id="TableOfContents"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#wat-is-mcp"&gt;Wat is MCP?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#wat-tei-mcp-doet"&gt;Wat tei-mcp doet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#waarom-het-ertoe-doet"&gt;Waarom het ertoe doet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#aan-de-slag"&gt;Aan de slag&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;/details&gt;
&lt;h2 id="wat-is-mcp"&gt;Wat is MCP?&lt;/h2&gt;
&lt;p&gt;Het
(MCP) is een open
standaard waarmee AI-toepassingen verbinding kunnen maken met externe gegevensbronnen
en tools. Zie het als een USB-poort voor AI: één protocol waarmee elke compatibele
client – Claude, Cursor, Windsurf en andere – op gespecialiseerde diensten kan
aansluiten.&lt;/p&gt;
&lt;p&gt;Een MCP-server stelt &lt;em&gt;tools&lt;/em&gt; beschikbaar die de AI tijdens een gesprek kan aanroepen.
In plaats van te vertrouwen op uit het hoofd geleerde trainingsdata kan het model
een actuele, gezaghebbende bron bevragen.&lt;/p&gt;
&lt;h2 id="wat-tei-mcp-doet"&gt;Wat tei-mcp doet&lt;/h2&gt;
&lt;p&gt;tei-mcp parseert de ODD-specificatie van TEI P5 en biedt 16 tools aan die de meest
voorkomende vragen van een editeur of encoder beantwoorden:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Wat is dit element?&lt;/strong&gt; Zoek elk element, elke klasse, macro of module op naam
op, hoofdletterongevoelig en met suggesties bij tikfouten.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Welke attributen neemt het?&lt;/strong&gt; Los attributen op over de hele klassenhiërarchie
– eerst de lokale, dan de geërfde, in volgorde.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wat mag erin?&lt;/strong&gt; Klap inhoudsmodellen uit tot gestructureerde bomen, of vraag
een platte lijst van geldige kinderen op.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mag dit element hier staan?&lt;/strong&gt; Controleer de nesting van ouder en kind, of volg
de bereikbaarheid door de volledige elementenhiërarchie.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Is mijn document geldig?&lt;/strong&gt; Valideer een TEI-XML-bestand tegen de specificatie:
inhoudsmodellen, attribuutwaarden, gesloten waardelijsten, referentie-integriteit
en waarschuwingen bij verouderde elementen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;En mijn projectschema?&lt;/strong&gt; Laad een ODD-customisatiebestand om dit alles te
beperken tot de specifieke TEI-deelverzameling van je project.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="waarom-het-ertoe-doet"&gt;Waarom het ertoe doet&lt;/h2&gt;
&lt;p&gt;TEI-codering vereist dat je voortdurend de Guidelines raadpleegt. Ervaren encoders
kennen de gangbaarste patronen uit het hoofd, maar zelfs zij moeten de specificatie
erbij nemen voor minder vertrouwde elementen of ingewikkelde inhoudsmodellen. Voor
AI-assistenten, die zulke verinnerlijkte kennis niet hebben, is het probleem erger:
ze hallucineren markup die er plausibel uitziet maar niet klopt.&lt;/p&gt;
&lt;p&gt;Met tei-mcp hoeft de AI niet te gokken. Het kan het antwoord in de specificatie
opzoeken voordat het één punthaak schrijft. Het resultaat is markup die voldoet
aan TEI P5 – of aan de ODD-customisatie van je project.&lt;/p&gt;
&lt;h2 id="aan-de-slag"&gt;Aan de slag&lt;/h2&gt;
&lt;p&gt;Installeer vanaf PyPI:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install tei-mcp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Voeg de server daarna toe aan de configuratie van je MCP-client:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mcpServers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;tei&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;uvx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tei-mcp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;De server downloadt de TEI-specificatie bij de eerste start en werkt met elke
MCP-compatibele client.&lt;/p&gt;
&lt;p&gt;Broncode en volledige documentatie:
&lt;/p&gt;</description></item><item><title>Binaire codering onderwijzen met de ITA2-telegraafemulator</title><link>https://clementgodbarge.com/nl/post/baudot/</link><pubDate>Thu, 13 Feb 2025 00:00:00 +0000</pubDate><guid>https://clementgodbarge.com/nl/post/baudot/</guid><description>&lt;h2 id="abstracte-begrippen-tastbaar-maken"&gt;Abstracte begrippen tastbaar maken&lt;/h2&gt;
&lt;p&gt;Deze ITA2-emulator is een praktisch hulpmiddel voor de les. Door abstracte coderingsbegrippen zichtbaar en interactief te maken, laat hij studenten kennismaken met een kernbegrip uit de informatica en de telecommunicatie: de binaire voorstelling – hoe tekst verandert in patronen van enen en nullen.
Meestal onderwijzen we dat abstract; wie de gaatjes daadwerkelijk ziet verschijnen, begrijpt beter hoe een fysiek systeem digitale informatie kan weergeven.
&lt;div class="baudot-emulator"&gt;
&lt;h2&gt;ITA2 (Baudot-Murray) Telegraph Type Emulator&lt;/h2&gt;
&lt;p&gt;Type a word in the input below to see its representation on the ITA2 tape.&lt;/p&gt;
&lt;div class="baudot-controls"&gt;
&lt;label for="baudot-input"&gt;Type word:&lt;/label&gt;
&lt;input id="baudot-input" class="text-input" size="50" maxlength="50" /&gt;
&lt;button type="button" id="baudot-ltr-button" class="control-button active"&gt;LTR&lt;/button&gt;
&lt;button type="button" id="baudot-fig-button" class="control-button"&gt;FIG&lt;/button&gt;
&lt;/div&gt;
&lt;div class="tape-outer-container"&gt;
&lt;div class="tape-container"&gt;
&lt;table&gt;
&lt;tbody id="baudot-tape"&gt;&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;style&gt;
.baudot-emulator {
--light-color: #f3f4f6;
--dark-color: #1f2937;
--light-alt-color: #e5e7eb;
--dark-alt-color: #374151;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;
max-width: 100%;
margin: 2rem 0;
padding: 0;
box-sizing: border-box;
}
.baudot-emulator {
--tape-bg: var(--light-color);
--hole-bg: var(--light-color);
--hole-border: #d1d5db;
--punched-bg: var(--dark-color);
--punched-border: var(--dark-color);
--sprocket-bg: var(--light-color);
--sprocket-border: #9ca3af;
--button-bg: var(--light-color);
--button-bg-active: #d1d5db;
--button-text: var(--dark-color);
--button-border: #d1d5db;
--input-bg: white;
--input-border: #d1d5db;
--input-text: var(--dark-color);
--line-number: #6b7280;
}
html.dark .baudot-emulator,
html[data-theme='dark'] .baudot-emulator,
body.dark .baudot-emulator {
--tape-bg: var(--dark-alt-color);
--hole-bg: var(--dark-alt-color);
--hole-border: #4b5563;
--punched-bg: var(--light-color);
--punched-border: var(--light-color);
--sprocket-bg: var(--dark-alt-color);
--sprocket-border: #9ca3af;
--button-bg: var(--dark-alt-color);
--button-bg-active: #4b5563;
--button-text: var(--light-color);
--button-border: #4b5563;
--input-bg: var(--dark-alt-color);
--input-border: #4b5563;
--input-text: var(--light-color);
--line-number: #9ca3af;
}
.baudot-controls {
margin-bottom: 1.5rem;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem;
}
.baudot-emulator .text-input {
flex: 1;
min-width: 200px;
padding: 0.5rem;
font-size: 1rem;
border: 1px solid var(--input-border);
border-radius: 4px;
background: var(--input-bg);
color: var(--input-text);
}
.baudot-emulator .control-button {
padding: 0.5rem 1rem;
background: var(--button-bg);
color: var(--button-text);
border: 1px solid var(--button-border);
border-radius: 4px;
cursor: pointer;
font-size: 0.9rem;
}
.baudot-emulator .control-button.active {
background: var(--button-bg-active);
font-weight: bold;
}
.tape-outer-container {
padding: 0;
margin-bottom: 1.5rem;
border-radius: 4px;
overflow: hidden;
}
.tape-container {
width: 100%;
overflow-x: auto;
background: var(--tape-bg);
padding: 1rem 0.5rem;
}
.baudot-emulator table {
border-collapse: collapse;
width: 100%;
table-layout: fixed;
border: none;
}
.baudot-emulator tr {
height: 24px;
border: none;
}
.baudot-emulator td {
border: none;
padding: 0;
}
.baudot-emulator .line-number {
width: 20px;
text-align: center;
color: var(--line-number);
font-size: 0.8rem;
padding: 0 8px 0 0;
font-weight: bold;
}
.baudot-emulator .cell {
position: relative;
width: 20px;
height: 20px;
}
.baudot-emulator .cell-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--hole-bg);
border: 1px solid var(--hole-border);
}
.baudot-emulator .punched .cell-content {
background: var(--punched-bg);
border: 1px solid var(--punched-border);
}
.baudot-emulator .sprocket-hole {
position: absolute;
left: 50%;
top: 100%;
transform: translate(-50%, -50%);
width: 4px;
height: 4px;
border-radius: 50%;
background: var(--sprocket-bg);
border: 1px solid var(--sprocket-border);
z-index: 2;
}
&lt;/style&gt;
&lt;script&gt;
document.addEventListener('DOMContentLoaded', function() {
initBaudotEmulator();
});
function initBaudotEmulator() {
if (!document.getElementById('baudot-input')) return;
const textInput = document.getElementById('baudot-input');
const tape = document.getElementById('baudot-tape');
const ltrButton = document.getElementById('baudot-ltr-button');
const figButton = document.getElementById('baudot-fig-button');
const ita2Code = {
'A': '00011', 'B': '11001', 'C': '01110', 'D': '01001', 'E': '00001',
'F': '01101', 'G': '11010', 'H': '10100', 'I': '00110', 'J': '01011',
'K': '01111', 'L': '10010', 'M': '11100', 'N': '01100', 'O': '11000',
'P': '10110', 'Q': '10111', 'R': '01010', 'S': '00101', 'T': '10000',
'U': '00111', 'V': '11110', 'W': '10011', 'X': '11101', 'Y': '10101',
'Z': '10001',
'1': '00011', '2': '11001', '3': '01110', '4': '01001', '5': '00001',
'6': '01101', '7': '11010', '8': '10100', '9': '01011', '0': '11000',
'-': '00011', '?': '00100', ':': '01010', '(': '11000', ')': '11101',
'.': '01000', ',': '00010', "'": '10001', '=': '01111', '/': '10011',
'+': '11011', ' ': '00100',
'FIG': '11011', 'LTR': '11111',
};
function generateTape() {
let rows = '';
for (let row = 0; row &lt; 5; row++) {
rows += '&lt;tr&gt;';
rows += `&lt;td class="line-number"&gt;${row + 1}&lt;/td&gt;`;
for (let col = 0; col &lt; 50; col++) {
rows += `&lt;td id="baudot_${row}_${col}" class="cell unpunched"&gt;
&lt;div class="cell-content"&gt;&lt;/div&gt;
${row === 2 ? '&lt;div class="sprocket-hole"&gt;&lt;/div&gt;' : ''}
&lt;/td&gt;`;
}
rows += '&lt;/tr&gt;';
}
tape.innerHTML = rows;
}
function updateITA2Code(word) {
clearTape();
word = word.toUpperCase();
let tapePosition = 0;
let currentCharType = 'LTR';
ltrButton.classList.add('active');
figButton.classList.remove('active');
for (let i = 0; i &lt; word.length; i++) {
const char = word[i];
let code = ita2Code[char] || ita2Code[' '];
let requiredCharType = /[A-Z ]/.test(char) ? 'LTR' : 'FIG';
if (requiredCharType !== currentCharType) {
const shiftCode = requiredCharType === 'LTR' ? ita2Code['LTR'] : ita2Code['FIG'];
punchTape(shiftCode, tapePosition++);
currentCharType = requiredCharType;
ltrButton.classList.toggle('active', currentCharType === 'LTR');
figButton.classList.toggle('active', currentCharType === 'FIG');
}
punchTape(code, tapePosition++);
}
}
function punchTape(code, tapePosition) {
if (tapePosition &gt;= 50) return;
for (let bit = 0; bit &lt; 5; bit++) {
const cell = document.getElementById(`baudot_${bit}_${tapePosition}`);
if (cell) {
cell.className = code[bit] === '1' ? 'cell punched' : 'cell unpunched';
}
}
}
function clearTape() {
for (let i = 0; i &lt; 50; i++) {
for (let bit = 0; bit &lt; 5; bit++) {
const cell = document.getElementById(`baudot_${bit}_${i}`);
if (cell) {
cell.className = 'cell unpunched';
}
}
}
}
generateTape();
textInput.addEventListener('input', function() {
updateITA2Code(this.value);
});
ltrButton.addEventListener('click', function() {
this.classList.add('active');
figButton.classList.remove('active');
if (textInput.value) {
updateITA2Code(textInput.value);
}
});
figButton.addEventListener('click', function() {
this.classList.add('active');
ltrButton.classList.remove('active');
if (textInput.value) {
updateITA2Code(textInput.value);
}
});
if (textInput.value) {
updateITA2Code(textInput.value);
}
}
&lt;/script&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;h2 id="historische-context-van-telegraaf-tot-computer"&gt;Historische context: van telegraaf tot computer&lt;/h2&gt;
&lt;p&gt;De ITA2-code (International Telegraph Alphabet No. 2), ook bekend als de Baudot-Murray-code, werd in de jaren twintig van de vorige eeuw ontwikkeld als verfijning van de oorspronkelijke telegraafcode van Émile Baudot uit de jaren 1870. Deze vroege telecommunicatiesystemen hebben de latere ontwikkeling van de computer rechtstreeks beïnvloed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;De vijfbitscodering was een vroeg voorbeeld van tekencodering&lt;/li&gt;
&lt;li&gt;De beperkte tekenset (met vijf bits zijn maar 32 combinaties mogelijk) leidde tot het vernuftige LETTERS/FIGURES-schakelmechanisme&lt;/li&gt;
&lt;li&gt;Het systeem bleef tot ver in de twintigste eeuw in gebruik voor telexapparaten&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="toestandsmachines-leren-door-te-spelen"&gt;Toestandsmachines leren door te spelen&lt;/h2&gt;
&lt;p&gt;Het LETTERS/FIGURES-schakelmechanisme is een natuurlijke inleiding tot toestandsmachines. Studenten ontdekken al experimenterend dat hetzelfde patroon verschillende tekens kan voorstellen, afhankelijk van de actieve modus. Wie zo hands-on ervaring opdoet met toestandsafhankelijke codering, is beter voorbereid op ingewikkelder concepten uit de informatica.
Het bitpatroon &lt;code&gt;00011&lt;/code&gt; staat bijvoorbeeld voor:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;de letter ‘A’ in de LETTERS-modus&lt;/li&gt;
&lt;li&gt;het cijfer ‘1’ in de FIGURES-modus
Deze dubbele lezing, afhankelijk van de toestand, ligt aan de basis van hoe computers met gegevens omgaan.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="lesactiviteiten"&gt;Lesactiviteiten&lt;/h2&gt;
&lt;p&gt;Enkele manieren om de ITA2-emulator in het onderwijs in te zetten:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Codekraken&lt;/strong&gt;: laat studenten berichten ontcijferen die als ITA2-patronen zijn gecodeerd&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zuinig coderen&lt;/strong&gt;: bespreek waarom het schakelmechanisme belangrijk was om bandbreedte te sparen&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Evolutie van de codering&lt;/strong&gt;: vergelijk de vijfbitscode van ITA2 met ASCII (7 bits) en Unicode&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Physical computing&lt;/strong&gt;: leg het verband tussen dit historische systeem en moderne microcontrollers zoals Arduino&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="winst-voor-de-toegankelijkheid"&gt;Winst voor de toegankelijkheid&lt;/h2&gt;
&lt;p&gt;Los van het historische belang komt deze aanpak tegemoet aan uiteenlopende leerstijlen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;visueel ingestelde studenten zien de patronen&lt;/li&gt;
&lt;li&gt;wie al doende leert, grijpt rechtstreeks in het coderingsproces in&lt;/li&gt;
&lt;li&gt;conceptuele denkers kunnen de wiskundige kant van de informatietheorie verkennen&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="technische-details"&gt;Technische details&lt;/h2&gt;
&lt;p&gt;De emulator is geschreven in JavaScript en laat zich eenvoudig in elk webgebaseerd leerplatform inbouwen. De code is modulair en kan aan verschillende onderwijscontexten worden aangepast.
De broncode vind je hier, en je kunt de emulator er meteen zelf uitproberen:
&lt;/p&gt;</description></item></channel></rss>