IBA verklaart: plaatsing van figuren in LaTeX

De plaatsing van figuren in LaTeX en in tekstverwerkers in het algemeen is soms lastig te doorgronden. In MS Word kunnen afbeeldingen verspringen naar schijnbaar willekeurige plaatsen in de tekst. LaTeX gooit nog wel eens alle afbeeldingen achter elkaar aan het einde van het document. Hoe bepaalt LaTeX wat de beste positie is van afbeeldingen in de tekst en hoe kun je daar handig gebruik van maken?

LaTeX kan zelf de plaatsing van een afbeelding of tabel bepalen, als deze in een float omgeving is geplaatst. De floatomgeving voor afbeeldingen wordt aangeroepen met \begin{figure}. Zoals de naam suggereert, kunnen de floats nu drijven in de lettersoep.

Voordat ik het over het zetten van afbeeldingen zal hebben, is het wellicht handig om te kijken wat LaTeX doet bij het compileren van de code. Zodra de LaTeX-code wordt gecompileerd, doet LaTeX het zetwerk vanaf het begin van de tekst naar het einde van de tekst. Als LaTeX vindt dat een pagina goed is, beschouwt hij die pagina als `af’ en wordt er niet meer naar gekeken. Voor gewone tekst maakt dat niet uit, maar voor floats heeft dit tot praktisch gevolg dat een float alleen op dezelfde pagina of op een pagina na de aanroep kan worden gezet. Dus, als LaTeX een afbeelding in een floatomgeving vindt, terwijl hij net met pagina n bezig is, zal de afbeelding op pagina p ≥ n komen. Het kan dus gebeuren dat de afbeelding een paar pagina’s verder wordt geplaatst, terwijl de pagina voor de aanroep een betere plaats zou kunnen zijn, omdat dit idee simpelweg niet bij LaTeX opkomt.

Op welke plaats op de pagina zet LaTeX de afbeelding neer? Als optionele parameter in de aanroep van de floatomgeving (d.w.z: Na het commando: \begin{figure}{[<optionele parameters>]} kan de gebruiker aan de floatomgeving aangeven waar op de pagina de float mag staan:

  • t: bovenaan de pagina.
  • h: midden in de tekst
  • b: onderaan de pagina
  • p: op een pagina met alleen afbeeldingen

Omdat dit aangeeft waar de float mag staan, zal een float met [tb] overal op de pagina mogen worden gezet. Deze optionele parameters commuteren met elkaar, dus [tb] is hetzelfde als [bt].

Figuur 1: Zowel Tux als Windows passen samen bovenin de pagina.

\begin{figure}[t]
\includegraphics{tux}
\end{figure}
\begin{figure}[t]
\includegraphics{windows}
\end{figure}

Figuur 2: Omdat Tux vrij groot is, heeft Apple niet genoeg ruimte. Daarom wordt Apple doorgeschoven naar de volgende pagina.

\begin{figure}[t]
\includegraphics{tux}
\end{figure}
\begin{figure}[t]
\includegraphics{apple}
\end{figure}

Figuur 3: Tux wil graag onderaan de pagina staan, omdat zijn floatomgeving wordt aangeroepen met \begin{figure}[b]. Omdat Tux langer is dan 30% van de paginahoogte, kan Tux alleen op een `afbeeldingpagina’. Omdat plaatjes in de PDF altijd in dezelfde volgorde staan waarin ze ook in het LaTeX-document staan, neemt Tux Windows en Apple mee naar beneden, terwijl er ruimte genoeg is voor Windows en Apple op eerdere pagina’s.

Wat is boven en wat is beneden? LaTeX beschouwt de bovenste 70% van de pagina als boven en de onderste 30% als beneden. (Deze waarden kunnen worden aangepast met \renewcommand{\topfraction}{<waarde>} en \renewcommand{\bottomfraction}{<waarde>} voor \begin{document}. Het is meestal niet nodig deze waarden aan te passen.) Dit betekent dat een plaatje, als het hoger is dan 30% van de paginahoogte, niet onderaan de pagina geplaatst kan worden. In het voorbeeld hiernaast is te zien hoe dit in zijn werk gaat. In Figuur 1 en 2 is te zien hoe LaTeX in normale omstandigheden werkt. Het plaatsen gaat echter mis in Figuur 3, omdat LaTeX Tux niet onderaan de pagina kan zetten. De plaatjes staan in dezelfde volgorde in de PDF, zoals LaTeX ze heeft aangetroffen in het LaTeX-bestand, dus Windows en Apple zullen pas na Tux gezet worden. Omdat geen van de afbeeldingen een [p] heeft meegekregen, kan er geen ‘afbeeldingpagina’ gemaakt worden tussen pagina  1 en pagina 2. Tux en alle afbeeldingen die hij heeft meegesleept, worden onderaan het document geplaatst.

Naar welk van de parameters tussen blokhaken kijkt LaTeX het eerst? Als LaTeX een float wil plaatsen, kijkt het dus naar de parameters [tbhp]. Eerst kijkt LaTeX of er een h in het rijtje staat, want de snelste methode om een afbeelding te plaatsen is natuurlijk om het plaatje meteen tussen de tekst in te zetten. De afbeelding zal niet meer verplaatsen, omdat LaTeX al geplaatste tekst of afbeeldingen niet meer verandert. Mocht het niet kunnen om het plaatje meteen te plaatsten, zal er daarna gekeken worden of er ook een t is aangegeven, omdat LaTeX het liefst plaatjes bovenaan de pagina heeft. Als het niet mogelijk is om een plaatje bovenaan de pagina te zetten (de floats die bovenaan staan, nemen niet meer dan 70% van de ruimte in en het aantal bovenin geplaatste afbeeldingen is niet hoger dan 2), zal gekeken worden of er beneden nog ruimte is. Als nergens aan voldaan kan worden, of alleen de optie p is aangegeven, zal LaTeX het plaatje in de wachtrij zetten. Zodra er een nieuwe pagina wordt gemaakt, zal de compiler weer kijken of het plaatje past. Dit zal in de meeste gevallen werken, omdat LaTeX nu de hele pagina ter beschikking heeft (dit gebeurt in Figuur 3). Als er meerdere floats in de wachtrij staan, zal LaTeX bij een nieuwe pagina proberen in één keer de rij te legen door een `afbeeldingpagina’ te maken. Voor zo een pagina gelden geen restricties meer over of een afbeelding boven of onder geplaatst moet worden of het aantal afbeeldingen dat maximaal geplaatst kan worden.

Tot slot nog wat praktische tips:

Bij het maken van een float kunnen de restricties wat betreft het aantal afbeeldingen per pagina worden uitgezet door een ! tussen de blokhaken te zetten. Om een plaatje op dezelfde plaats in de PDF te krijgen als in het TeX-bestand is [h!] mee te geven aan \begin{figure}. Er kan ook grover geschut in worden gezet: [H] zet altijd de float op de plaats neer als aangegeven en maakt zo nodig een nieuwe pagina aan. Hiervoor is de float package nodig.

Om te voorkomen dat floats ergens heen drijven naar plaatsen waar ze niet horen, kan de placeins package gebruikt worden. Deze package geeft het commando \FloatBarrier. Zoals de naam al suggereert, kunnen floats niet voorbij dit commando en zullen de altijd ervoor geplaatst worden. Dit is handig om te voorkomen dat verdwaalde floats van vorige hoofdstukken nog ronddrijven verderop in het document.

De voorgaande tekst ging alleen over de plaatsing van afbeeldingen die de hele breedte van het document in beslag nemen. Als de afbeelding klein is vergeleken met de paginabreedte, kun je ook de wrapfig-package gebruiken. De wrapfig-package geeft een wrapfigure-omgeving waarmee door tekst omringde afbeeldingen gemaakt kunnen worden. Natuurlijk zal LaTeX dit plaatje dicht bij de aanroep plaatsen.

Wellicht ten overvloedde: de manier van plaatsten zorgt ervoor dat afbeeldingen pas gezet worden, nadat ze zijn aangeroepen in de code. Ook worden alle floats geplaatst op volgorde waarin ze in de code voorkomen. Wees dus niet te restrictief: een float met alleen [b], zal niet altijd op een goede manier geplaatst kunnen worden en kan hierdoor andere floats wegduwen.

Dit artikel is eerder verschenen in de Vakidioot 1617-3 Figuur

IBA verklaart glob

Oh my Glob!

Met globben kun je heel efficiënt bestanden in de terminal selecteren, zodat je nog minder hoeft in te typen en wordt aangezien voor tovenaar door de mindere gebruikers. Welke doorgewinterde LaTeXgebruiker is het ook niet zat om na elke druk op de compilatieknop door tientallen meukbestanden te navigeren? De macht van het globben geeft je eindelijk de mogelijkheid een einde maken aan al die troep. Bovendien is het woord “glob” ook gewoon leuk om te zeggen.

Deze commando’s zijn allemaal getest in bash versie 4.2.46, wat je per default tegenkomt als je op het A–Eskwadraatsysteem een terminal opstart. Het voorbeeldmapje kun je op het A–Eskwadraatsysteem terugvinden in /home/mensjes/timb/troep/glob.

De allersimpelste glob is *, wat simpelweg alle zichtbare dingen in de huidige map betekent. Dat is voor ons meteen ook een beetje nutteloos, want rm * gooit ook al je niet-meukbestanden weg.

$ echo *
boot kat klok raket rat submapje zat

Gelukkig kun je de onderdelen die in de bestandsnaam moeten voorkomen ook aan * vastplakken, zodat je rm *.aux kunt gebruiken om alle .aux-meukbestanden die LaTeX maakt, weg te gooien. Je mag ook meerdere globs en verplichte stukken tegelijk gebruiken.

$ echo k*
kat klok


$ echo *k*t
kat raket

Daarnaast zijn er globs die maar één letter aangeven. Op de plek van ? mag elk karakter staan, maar niet meer dan één.

$ echo ?at
kat rat zat

Om een keuze tussen karakters aan te geven, is er de glob [...]. Tussen de haakjes zet je de karakters die je wilt hebben. Om niet een heel alfabet te hoeven typen, kun je ook een bereik aangeven met een streepje, zoals [a-z] voor alle kleine letters. Je hebt ook [^...] om juist alles behalve de inhoud van de haakjes te krijgen zoals:

$ echo [kr]at
kat rat
$ echo [p-z]at
rat zat
$ echo [^r]at
kat zat

Uitgebreidere globs

Om geavanceerdere trucs uit te halen, moet je uitgebreidere globs aanzetten. Het commando om dat te doen is shopt -s extglob globstar.Als je uit meerdere opties wilt kiezen, geeft extglob je de glob @(...). Zet de opties met een | ertussen in de haakjes. Aangeven hoe vaak iets herhaalt kan met ?(...) voor 0 of 1 keer, *(...) voor 0 of meer en +(...) voor 1 of meer. Tenslotte heb je nog !(...) die juist alles behalve de inhoud van de haakjes kiest.

$ echo ra@(ket|t)
raket rat
$ echo !(*at)
boot klok raket submapje

Het globstar-gedeelte slaat op de glob **, die niet alleen de inhoud van de huidige map kiest, maar ook alle submappen.

$ echo **
boot kat klok raket rat submapje submapje/ondergroep submapje/onderzeeboot submapje/verwisseling zat

Deze **-globs kun je niet zomaar uitbreiden met karakters erna, anders begrijpt bash het niet als glob. Gelukkig kun met een / ertussen toch verplichte onderdelen toevoegen. Let op: deze slash betekent niet dat de glob altijd naar een submap gaat.

$ echo **boot
-bash: no match: **boot
$ echo **/*boot
boot submapje/onderzeeboot

Creatief misbruik maken van glob

Je moet goed opletten dat globben ingebouwd is in bash, en een programma dus niet weet of zijn invoer ingetypt of geglobd is. Zo kunnen bestandsnamen per ongeluk opeens opties worden, wat ervoor zorgt dat je commando’s per ongeluk iets onverwachts gaan doen. Normaal weigert rm om mappen weg te gooien, tenzij je het de optie -r geeft.

$ rm submapje
rm: cannot remove `submapje': Is a directory
$ rm -r submapje
$

Als een of andere onverlaat het bestand -r aanmaakt, ziet rm * na globben uit als rm -r boot kat klok raket rat submapje zat, en gaan je mappen er dus toch aan.

$ touch -- -r
$ rm *
$ echo *
-bash: no match: *

Een andere populaire bron van bugs is de combinatie van glob en variabelen. Als je een variabele en een glob combineert, wordt eerst de waarde van de variabele ingevuld, en dan de glob uitgebreid.
Als je variabele geen waarde heeft (bijvoorbeeld door een typfout) kan je glob plots /* worden, wat als argument voor bijvoorbeeld rm nogal spectaculaire resultaten oplevert.

$ MAPJE=submapje echo $AMPJE/*
/archief /bin /boot /dev /etc /home /lib /lib64 /lost+found /media /mnt /opt /proc /rhev /root /run /sbin /scratch /srv /sys /tmp /usr /var

Aan de andere kant kun je misbruik van globben handig gebruiken om je bestanden juist te beschermen: als je rm de optie -I meegeeft, vraagt het commando eerst of je het wel zeker weet. Zet je dus een bestand genaamd -I in je belangrijke mappen, heb je een klein beetje extra bescherming tegen je eigen stommiteiten.

IBA verklaart Benamite

Je zult er waarschijnlijk nog nooit van gehoord hebben: Benamite. Toch gebruik je het iedere keer weer als je gebruik maakt van de A–Eskwadraatwebsite. Benamite is het virtuele filesystem van de website. Veel websites gebruiken een fysieke filesystem als structuur van de website. Dit houdt in dat er ergens op een server een mapje moet bestaan. Als je op de website naar bijvoorbeeld www.website.nl/index.html wilt gaan, betekent dat dat er in het mapje op de server een bestand index.html moet bestaan en dat de webserver ook nog de juiste rechten moet hebben om dat bestand te kunnen lezen. Je kunt wel begrijpen dat, als je website uit veel verschillende pagina’s bestaat, je dus heel veel verschillende bestanden nodig hebt, wat nogal veel overhead geeft. De A–Eskwadraatwebsite heeft op dit moment rond de 4000 verschillende unieke pagina’s waarbij de pagina’s die een variabele url hebben, zoals bijvoorbeeld a-eskwadraat.nl/Leden/5794, niet meegenomen zijn. Om de overhead te besparen is er ooit jaren geleden (in 2006 al) Benamite gemaakt.

Hoe werkt Benamite dan? Stel, je gaat naar de pagina https://www.a-eskwadraat.nl/Service/Bugweb/. We vergeten het https://www.a-eskwadraat.nl/-gedeelte want dat geeft alleen het domein aan waarmee de server gevonden kan worden en heeft voor Benamite geen verdere functie. We houden dus de uri /Service/Bugweb/ over. Deze gaan we door Benamite halen. Benamite gaat als eerste de eerste '/' bekijken, wat de root is van de site. Hij kijkt of het wel bestaat in Benamite, of het een map is en of de huidige gebruiker er wel bij mag. Als dit allemaal goed is, gaat Benamite door naar het volgende gedeelte: 'Service/'. Ook hier kijkt hij weer of het bestaat, etc, etc. Op die manier werkt Benamite de delen van de uri een voor een af. Eenmaal bij het laatste aangekomen, zijn er een aantal opties. Als het laatste element een bestand is in Benamite, dan opent hij het bestand. Als het een map betreft, probeert hij het bestand 'index.html' in die map te openen (de naamgeving is door de jaren heen niet veranderd en eigenlijk niet meer van toepassing, want we hebben nauwelijks nog html-bestanden op de website). Als dat bestand niet bestaat, stuurt hij een foutmelding naar de gebruiker.

Dan is er ook nog de speciale ‘variabele entry’. Dit zorgt ervoor dat je bijvoorbeeld elk lid kan bekijken op /Leden/*lidnr*. Een variabele entry is een map met wat extra’s: je kan eisen van de variabele entry wat het moet zijn, bijvoorbeeld een activiteit-id, een commissie-id etc en of het zichtbaar is voor de huidige gebruiker. Vervolgens accepteert de variabele entry alles wat hieraan voldoet. Wat gebeurt er dan, als je dus naar /Leden/5794/ gaat? Benamite handelt eerst /Leden/ af en als dit allemaal goed gaat, komt hij bij het gedeelte 5794/ uit. Er staat in de map /Leden/ geen map of bestand 5794, maar wel een variabele entry. Wat Benamite nu gaat doen, is: hij gaat kijken wat de variabele entry moet zijn. In dit geval moet de variabele entry een lidnummer zijn van een bestaand lid en moet degene die ingelogd is, het lid kunnen zien. Als dit allemaal goed is gegaan, stuurt Benamite het door naar het volgende gedeelte. In alle bestanden die in de map of submappen van de variabele entry staan kunnen we vervolgens met speciale php-functies alle variabele entries uit de url halen en op die manier de juiste objecten erbij halen.

Bestanden in Benamite kunnen verschillende types zijn en dus verschillende functies hebben. Het meest standaard is het normale bestand, waarmee we functies in php-bestanden kunnen aanroepen om op die manier een pagina te maken. Daarnaast hebben we geüploade bestanden, dit zijn bestanden die naar de site zijn geüpload, zoals bijvoorbeeld pdf’jes, afbeeldingen etc. Dan zijn er ook nog Publisherbestanden. Dit zijn bestanden waarvan de html wordt opgeslagen, zodat die later door gebruikers van de website aangepast kan worden en je dus niet in de code van de website hoeft te hekken om de html aan te passen. Dit wordt bijvoorbeeld gebruikt voor pagina’s zoals /Vereniging/Kamer/. Benamite heeft ook links, als een uri eindigt in een link, stuurt Benamite je meteen door naar waar de link naar toe linkt. Als laatste is er nog de php-haak. Dit is een soort midden tussen een normaal bestand en een variabele entry in. Bij een php-haak wordt de rest van de url die nog over is en niet door benamite verwerkt is, rechtstreeks aan de php-haak doorgegeven die er dan vervolgens mee kan doen wat ie wil. Php-haken werden vroeger voornamelijk gebruikt bij de menuutjes; zo werd bijvoorbeeld ‘Open de boekverkoop’, ‘Sluit de boekverkoop’ als de boekverkoop al geopend was. Tegenwoordig worden php-haken nauwelijks meer gebruikt op de A–Eskwadraatwebsite.

Al met al maakt Benamite het beheren van onze fantastische website een stuk eenvoudiger en hopelijk kijk ook jij nu weer anders tegen de website aan dan dat je voorheen deed. Lijkt het je nou leuk om nog meer over Benamite te weten te komen of wil je graag zelf knutselen aan de A–Eskwadraatwebsite, kom dan vooral een keertje langs op onze wekelijkse Werkfeestjes op de dinsdagavond in de A–Eskwadraatwerkkamer!

IBA Verklaart thuiswerken

Het nieuwe collegejaar staat voor de deur, dat betekent dat je binnenkort niet alleen voor je opleiding aan de slag gaat maar ook weer voor A–Eskwadraat! Dikke kans dat je in de zomervakantie allerlei dingen vergeten bent dus om je geheugen op te frissen is hier een korte handleiding thuiswerken.

Mail
Misschien wel het belangrijkste onderdeel van je commissiewerk: email. Er zijn twee manieren om commissiemail te regelen: via Gmail en via de A–Eskwadraat webmail (mail.a-eskwadraat.nl). Sysop heeft voor de beide scenario’s handleidingen geschreven.

Handleiding Webmail
→ Handleiding Gmail

Bestanden
De makkelijkste manier om vanuit Windows bij je bestanden te komen is via WinSCP. Je kunt WinSCP hier downloaden. Om verbinding te maken met A–Eskwadraat tik je in het startscherm je gegevens in (zie plaatje), klik je op ‘Save’ en vervolgens op ‘Login’. WinSCP geeft een waarschuwing omdat je voor het eerst inlogt, deze mag je negeren door op ‘Yes’ te klikken.

winscp
Startscherm WinSCP
WinSCP ingelogd
WinSCP ingelogd

Als alles goed gaat zou je iets moeten zien dat sterk lijkt op het bovenstaande plaatje. Aan de rechterkant van het scherm staan je A–Eskwadraatbestanden en aan de linkerkant de bestanden van je eigen computer. Zoals je ziet zit ik in de map cies en kan ik van daaruit eenvoudig naar de bestanden van mijn commissies.

Om vanuit macOS bij je bestanden te komen kun je bijvoorbeeld FileZilla gebruiken, dat werkt op ongeveer dezelfde manier als WinSCP. Linuxgebruikers hebben geen extra software nodig, de meeste filemanagers kunnen wel overweg met sftp.

SSH
Het is ook mogelijk om vanuit huis iets te doen op een computer bij A–Eskwadraat, dit doe je met SSH. Uitgebreide informatie over ssh is te vinden in het artikel IBA Verklaart ssh, hieronder volgen wat korte instructies.

Vanaf macOS of Linux is ssh eenvoudig: je opent een terminal, typt ssh -X gebruikersnaam@a-eskwadraat.nl en je bent binnen. Je kunt dan precies hetzelfde als in een terminal op een werkplek in de werkkamer. De optie -X zorgt er voor dat je ook grafische programma’s zoals nautilus of evince kan opstarten. Op Windows heb je extra programma’s nodig: PuTTY (kies voor putty.exe onder “For Windows on Intel x86”) en optioneel Xming. Xming heb je alleen nodig als je grafische programma’s wil gebruiken.

PuTTY werkt heel simpel, je vult in het beginscherm onder ‘Host Name’ a-eskwadraat.nl in en klikt op ‘Open’. Als je voor het eerst inlogt wordt er een waarschuwing gegeven, deze mag je gewoon negeren. Vul vervolgens je gebruikersnaam en wachtwoord in en zie daar, een terminal.

X forwarding in PuTTY
X forwarding in PuTTY

Om in Windows een grafisch programma te openen moet je Xming downloaden en installeren. Start Xming en vervolgens PuTTY, navigeer in PuTTY naar “Connection” -> “SSH” -> “X11” (zie plaatje) en vink “Enable X11 Forwarding” aan. Ga weer terug naar “Session” (het startscherm) en verbind met A–Eskwadraat. Je kunt nu gebruik maken van grafische programma’s. Protip: zet een & achter de naam van een grafisch programma om je terminal open te houden.

PuTTY en Xming
PuTTY en Xming

LaTeX
Volg de instructies van de TeXniCie om thuis aan de slag te kunnen met de LaTeX-packages van A–Eskwadraat.

Kom je ergens niet uit? Laat hieronder een reactie achter (inloggen met je A–Eskwadraataccount) of neem contact op met sysop of de TeXniCie.

IBA Verklaart Multiseat

Als je wel eens in de werkkamer van A–Eskwadraat bent geweest, heb je misschien wel gezien dat er 12 (op moment van schrijven staan er tijdelijk 8) werkplekken zijn, maar dat ze aangesloten zijn op slechts 3 computers. Dit wordt een multiseat opstelling genoemd. Toen vroeger de eerste computers bij bedrijven en universiteiten in gebruik werden genomen, waren computers nog zo groot dat ze een hele kamer innamen, en was het dus nog niet mogelijk om een aparte computer per gebruiker te hebben. Tegenwoordig is dat natuurlijk geen probleem meer, maar er zijn nog steeds goede redenen om een multiseat opstelling te hebben.

Iedere computer heeft een hoeveelheid geheugen. Maar waarschijnlijk gebruik je meestal een stuk minder geheugen dan dat je computer tot zijn beschikking heeft. Dit geheugen is voor het geval dat je een keer zwaardere software of veel programma’s tegelijk wilt gebruiken. Wanneer je vier werkplekken op één computer hebt, hoef je vaak minder geheugen te hebben dan dat vier losse computers zouden hebben, omdat niet alle vier de gebruikers tegelijk zware software willen draaien. Ditzelfde argument gaat bijvoorbeeld ook op voor hoe krachtig de processor moet zijn, en hierdoor kan het goedkoper en energiezuiniger zijn om één krachtige computer voor 4 werkplekken te kopen dan om 4 gewone losse computers te kopen.

Een ander voordeel is dat er door zo een opstelling minder onderhoud nodig is per werkplek. Je hoeft maar één keer software te installeren of instellingen aan te passen in plaats van 4 keer, dus dit kan heel veel werk besparen. Bij grotere organisaties zoals de Universiteit Utrecht maakt dit minder verschil, want daar zijn de update- en installatieprocessen grotendeels geautomatiseerd.

Besturingssystemen zoals Linux hebben de mogelijkheid om meerdere werkplekken aan te sluiten standaard meegeleverd. Als je dit op een computer met Linux leest, zou je kunnen proberen om control en alt ingedrukt te houden, en de toetsen F1 tot en met F8 een voor een in te drukken. Over het algemeen kom je met ctrl+alt+F7 terug waar je normaal bent. Hiermee wissel je standaard tussen zogehete virtual terminals, maar het is mogelijk om hier een aparte grafische omgeving te starten. Overigens zal je niet op alle Linux computers zomaar naar de virtuele terminals kunnen wisselen. Op de computers in de werkkamer staat het natuurlijk uit, zodat je niet per ongeluk het scherm van je buurman voor je krijgt.

Als je een Linux computer tot je beschikking hebt en zelf eens wilt proberen om een tweede grafische omgeving te starten, kan je met ctrl+alt+F1 naar een virtuele terminal gaan, daar inloggen en het volgende commando uit te voeren:

startx -- :1

Als het goed is kom je nu vanzelf bij je nieuwe inlogscherm terecht. Je kunt heen en weer gaan met control, alt en de F-toetsen. Om de tweede grafische omgeving weer te stoppen, kun je het nieuwste Xorg proces (degene met de hoogste process id) stoppen met de taskmanager, maar pas op dat je geen niet-opgeslagen werk open hebt staan in de nieuwe omgeving.

Om de nieuwe grafische omgeving echte werkplek te maken, heb je natuurlijk een extra scherm, toetsenbord en muis nodig. Helaas is het niet zo simpel dat je de extra apparatuur alleen hoeft aan te sluiten, maar gelukkig zijn er meerdere goede handleidingen op internet, zoals bijvoorbeeld deze (https://wiki.archlinux.org/index.php/xorg_multiseat), maar je Linux-distributie naar keuze heeft wellicht een eigen handleiding.

Zeker als je niet zo ervaren met Linux bent, is het een goed idee een backup te maken van je belangrijke bestanden voordat je dit probeert, omdat als je grafische interface interface niet meer werkt, je niet zo makkelijk het internet kan raadplegen om te vinden hoe je alles weer herstelt.

LaTeX-cursus Deel 5 in de praktijk: een eigen inleveropgaveklasse

\LaTeX kan veel beter overweg met formules dan Word of LibreOffice. Desalniettemin kan het veel werk zijn om lange uitwerkingen van inleveropgaven te \TeX-en. Het loont daarom om een eigen klasse te schrijven met daarin jouw meest gebruikte commando’s.

Om een eigen klasse te maken maak je een nieuw document met de extensie .cls. Bovenaan zet je welke versie van \LaTeX wordt gebruikt wordt. Dit doe je met \NeedsTeXFormat{LaTeX2e}, omdat je waarschijnlijk geen versie van voor 1994 wilt gebruiken. Om de computer te vertellen welke klasse je eigenlijk aan het maken bent, zet je daaronder ProvidesClass{opgave}. Deze twee commando’s zijn al genoeg voor een \LaTeX-klasse, maar we hebben er nog niet zoveel aan. Dit kunnen we verbeteren door de functionaliteit van een andere klasse te importeren. Sommige inleveropgaven zijn zo lang, dat het lijkt alsof ik een heel artikel moet schrijven, dus laten we de \article-klasse laden met \LoadClass[a4paper, 11pt]{article}. We zijn nu klaar om onze eigen inleveropgaveklasse te hekken.

In de mathmode maakt \LaTeX alle letters cursief en haalt alle spaties weg. Dit is meestal wat je wilt, maar dit betekent ook dat de ‘d’ in een differentiaal ($\text{d}x$) wat hulp nodig heeft om een mooie rechte ‘d’ te worden. Dit kan vervelend zijn met een tekst met veel integralen. Dit kan sneller met een eenvoudig nieuw commando: \newcommand{\dd}{\textbackslash,\text{d}}. Iedere keer als er \dd in een wiskundeomgeving staat, wordt er een korte spatie geplaatst: \, en en rechte ‘d’: \text{d}.

Met \newcommand kunnen ook parameters worden toegevoegd. Om snel een gemiddelde of een verwachtingswaarde in de tekst te zetten kun je het volgende definiëren:

\newcommand{\mean}[1]{\ensuremath{\left< #1 \right>}}

Hierin geeft [1] het aantal inputvelden van het nieuwe commando aan. Dat wil zeggen het aantal keer dat we iets achter het commando tussen accolades kunnen zetten. #1 is de parameter van het eerste inputveld. Dat is in dit geval makkelijk, want er is er maar één. Zo wordt \mean{x}: ⟨x⟩. Als je een commando definieert, weet je niet zeker of de gebruiker in mathmode is. Daarom is \ensuremath handig voor het maken van eigen commando’s, omdat \ensuremath een wiskundeomgeving start vanuit een tekstomgeving en in de wiskundeomgeving blijft als het wordt aangeroepen vanuit een wiskundeomgeving.

Een voorbeeld van wat ik vaak in \LaTeX schrijf, zijn afgeleiden. Het vervelende aan afgeleiden is dat er steeds breuken moeten worden geschreven en superscripten voor de hogere afgeleiden. Ik wil een commando \afg maken, waarmee ik:

  • De differentiatieoperator $\tfrac{\partial}{\partial t}$ krijg, als ik één parameter invul: \afg{t}
  • De afgeleide $\tfrac{\partial f}{\partial x}$ krijg als ik twee parameters invul: \afg{f}{x}
  • De ne afgeleide kan instellen met een optionele parameter tussen blokhaken: \afg{f}{x}[2]

Dit commando is makkelijker te maken met \NewDocumentCommand dan met \newcommand, omdat ik mijn commando wil ‘overloaden’. Dat wil zeggen dat ik andere dingen wil doen afhankelijk van het aantal opgegeven parameters. \NewDocumentCommand is onderdeel van de xparse-package. De xparse-package maakt het mogelijk om commando’s te maken met \LaTeX\ 3 in \LaTeX\ 2. Packages in een .cls-bestand laad je met \RequirePackage. Op deze manier kun je ook de preamble een stuk korter maken door je standaardpackages op deze manier in te laden, omdat je deze packages ook kunt gebruiken in jouw inleveropgave. \NewDocumentCommand ziet er als volgt uit:

\NewDocumentCommand{\mijnCommando}{opties voor parameters}{body}

De body werkt net zoals in \newcommand, maar voor de parameters zijn andere opties dan in \newcommand. Met de laatste kan men alleen tussen blokhaken het aantal parameters aangeven dat in het nieuwe commando gebruikt wordt, maar in \NewDocumentCommand is het een verplicht veld. Hierin wordt op volgorde van parameters #1 t/m #n met een letter aangegeven of het een optionele of verplichte parameter is[1]:

  • m van ‘mandatory’: geeft een verplicht veld aan, dus tussen accolades.
  • o van ‘optional’: geeft een optioneel veld aan, dus tussen blokhaken.
  • g van ‘overloaded’: geeft een optioneel veld aan, maar tussen accolades.

Het gebruik van g maakt het de gebruiker duidelijker dat de output van het commando anders kan reageren op het gebruiken van dit commando. Je ziet bij mijn eisenlijst dat de betekenis van het eerste inputveld verandert bij het toevoegen van een tweede parameter. Eerst staat de eerste parameter #1 onder de deelstreep en na het toevoegen van een tweede parameter staat #1 boven de deelstreep:
\afg{t} wordt:   \tfrac{\partial}{\partial t}
en   \afg{f}{x} wordt:   \tfrac{\partial f}{\partial x}
Het definiëren van afg ziet er als volgt uit:

\NewDocumentCommand{\afg}{mgo}{body}

Het aanroepen wordt dan:

\afg{#1 mandatory}{#2 overloaded}[#3 optional]

Ik mis nu slechts nog één detail: \LaTeX weet nog niet wat te doen met al onze mooie parameters. In de body kunnen we gebruik maken van IfValueTF. Wat dit doet is eenvoudig:

\IfValueTF{#n}{voer uit als #n bestaat}{voer uit als #n niet bestaat}

Dit kunnen we gebruiken voor zowel onze ‘overloaded’ als voor onze optionele parameter gebruiken. Voor de liefhebbers staat hieronder het commando voor de partiële afgeleide.

\NewDocumentCommand{\afg}{mgo}{
    \ensuremath{
        \IfValueTF{#3}{
            \IfValueTF{#2}{
                \frac{\partial^{#3} #1}{\partial #2^{#3}}
                }
                {
                \frac{\partial^{#3}}{\partial #1^{#3}}
                }
        }
        {
            \IfValueTF{#2}{
                \frac{\partial #1}{\partial #2}
            }
            {
                \frac{\partial}{\partial #1}
            }
        }
    }
}

Met de hierboven beschreven methoden kun je al ver komen met een eigen klasse, maar het zou leuk zijn, als je de nieuwe klasse ook met parameters kunt aanroepen. Dit kun je doen met DeclareOption:

\DeclareOption{parameter}{voer uit als 'parameter' is gegeven}

Je kunt op deze manier ook booleans uit of aan zetten, zodat je in het hele document deze parameter kunt gebruiken. Een voorbeeld waarmee je dit misschien wil doen, is de taal van het document. Als deze klasse wordt aangeroepen met \documentclass[english]{opgave} wil je de optie ‘english’ meegeven aan babel, maar ook, als je een kop- of voettekst hebt gedefinieerd, ‘Aantal pagina’s’ veranderen in ‘Number of pages’. Booleans kun je maken met het ietwat vreemde \newif[2]. Een voorbeeld van \newif is:

\newif\ifengels\engelsfalse

\DeclareOption{english}{\engelstrue}

Dit maakt een boolean \ifengels aan. Door daarna \engelsfalse te gebruiken wordt deze op ‘false’ gezet. \newif\ifengels maakt namelijk zelf \engelsfalse en \engelstrue aan. \DeclareOption{\engelstrue} zet \ifengels alleen op ‘true’, als deze klasse wordt aangeroepen met \documentclass}[english]{opgave}. Deze boolean kunnen we vervolgens gebruiken in een if-blok dat de taaloptie in babel stopt. Dit if-blok wordt afgesloten met \fi.

\ifengels\RequirePackage[english]{babel}
\else\RequirePackage[dutch]{babel}
\fi

Om te controleren of alle pagina’s compleet zijn, kan het handig zijn om op de eerste pagina te zetten hoeveel pagina’s er in totaal zijn. Dit kan met de packages fancyhdr en lastpage. Omdat we dit ook af en toe niet willen, is het handig dit alleen te doen, als er een optie ‘totpag’ in de klassenaanroep is meegegeven. Voor een tweede optie in documentclass gaat dit op dezelfde manier als in het vorige voorbeeld:

\newif\iftotpag\totpagfalse
\DeclareOption{totpag}{\totpagtrue}

Als iftotpag ‘true’ is, wordt de header weergegeven. Dit kan misschien het beste door de ‘fancypagestyle‘ van \maketitle aan te passen. Als \maketitle wordt aangeroepen, gebruikt de titelpagina de \fancypagestyle{plain}. Door deze aan te passen, kunnen we een header krijgen rechtsboven op de titelpagina.

\iftotpag
\fancypagestyle{plain}{
    \ifengels
    \fancyhead[R]{Number of pages: \pageref{LastPage}}
    \else
    \fancyhead[R]{Aantal pagina's: \pageref{LastPage}} 
    \fi
}
\fi

Tot slot wil ik nog code geven om de overgebleven opties van de klassenaanroep aan de article}-klasse te geven:

\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
\ProcessOptions

Dit zet je voor \LoadClass[a4paper,11pt]{article}.

Veel plezier met \TeX-en en een gezegend 2016.

\end{document}

[1]  Er zijn veel meer opties dan deze drie. Zie de documentatie van xparse op CTAN.
[2]  Meer TeX-commando’s, die ook worden gebruikt in de A–Eskwadraat-packages kun je vinden op https://en.wikibooks.org/wiki/LaTeX/Plain\_TeX

IBA Verklaart ssh

Al sinds de beginjaren van het internet werden er applicaties gemaakt om in te kunnen loggen op andere computers vanaf je eigen computer. Neem bijvoorbeeld programma’s zoals telnet en rsh (als deze programma’s je niks zeggen, wees gerust, we zullen ze niet behandelen). Echter, de bestaande programma’s hadden niet genoeg beveiliging en waren vatbaar voor bijvoorbeeld wachtwoordsniffers. Daarom besloot Tatu Ylönen in 1995 om een beter programma te maken voor het inloggen op andere computers en hij doopte het programma ‘ssh’ (secure shell). Al vanaf het begin bleek ssh populair en tegenwoordig is het niet meer weg te denken in de wereld van Linux en Macs en wordt het gebruikt om veilig bestanden over te sturen, applicaties op een andere computer te draaien en nog veel meer. Windowsgebruikers moeten zich nog wenden tot andere applicaties om hetzelfde doel te bereiken (denk bijvoorbeeld aan PuTTY) maar Microsoft heeft in 2015 aangekondigd dat het ssh in toekomstige generaties van Windows gaat integreren.

Hoe werkt ssh dan precies, vraag je je misschien af. Laten we eens gaan kijken wat er allemaal gebeurt als je een ssh-connectie probeert op te zetten. Het eerste wat je doet is verbinding maken met de ssh-poort op de ssh-server (meestal poort 22). Op dit moment krijgt de client (dat is de computer vanaf waar je connectie maakt) twee dingen toegestuurd: de protocolversie en de ssh-versie van de server. Als de client het protocol ondersteunt, kunnen ze verder. Op dit moment gaan zowel de client als de server over op een Binair Package Protocol, dat betekent dat de pakketjes die overgestuurd worden nu 32 bits groot zijn. De server stuurt nu zijn publieke sleutel (het publieke deel van de asymmetrische versleuteling, maar dat is weer een verhaal voor een andere keer), 8 willekeurige bits die de client moet terugsturen als antwoord en tenslotte alle soorten encryptie die ondersteund worden. Nu maakt de client een symmetrische sleutel aan en stuurt deze sleutel ook naar de server. Deze sleutel wordt gebruikt om de data die over de ssh gestuurd wordt te versleutelen. Merk natuurlijk wel op dat deze sleutel eerst versleuteld wordt met de publieke sleutel van de server. Ook geeft de client op dit moment aan welke versleutelingsmethode hij gebruikt voor het versleutelen van de data. Als laatste stap wacht de client op een bevestiging van de server. Deze bevestiging is uiteraard versleuteld met de symmetrische sleutel die de client heeft aangemaakt en is belangrijk voor de client; dit is namelijk nu de enige manier om te weten of de client met dezelfde server praat als waar hij net mee heeft gecommuniceerd, dit om zeker te zijn dat er niet iemand is die met alles loopt te rommelen om zo je geheime data te achterhalen. Als dit allemaal goed is gegaan kunnen de client en de server versleuteld en veilig met elkaar babbelen en kan je gaan inloggen op de server.

Dit is natuurlijk een hoop informatie om in 1 keer te bevatten, dus we gaan nu kijken wat er gebeurt als je vanaf thuis bij \aesnaam gaat inloggen. Je probeert dan dus vanaf thuis met poort 22 op de A-Eskwadraatserver te verbinden. Het eerste wat je tegenkomt is de router. De router zorgt voor poortforwarding. Dat houdt in dat de router een lijstje heeft staan met welke poortverbinding hij moet doorsturen naar welke poort op welke machine. Daar staat bijvoorbeeld dat als je op poort 22 probeert te verbinden, de router je doorstuurt naar poort 22 op de ssh-extern-machine van A-Eskwadraat, paul. Vervolgens maak je dus verbinding met poort 22 op paul en treedt het standaard ssh-protocol in werking. In de router staan echter nog meer regels, zo kan je bijvoorbeeld verbinding maken met poort 32022 om op de workstation dennis uit te komen. Probeer het zelf ook eens uit, Linux- en Mac-gebruikers kunnen het commando ssh gebruiken:

ssh [username]@a-eskwadraat.nl -p 32022

Windowsgebruikers kunnen als ze putty gebruiken in putty selecteren met welke poort ze verbinding willen maken.
Natuurlijk wordt de poortforwarding voor veel meer gebruikt dan alleen ssh, denk aan mail of een http-request, maar dat is een verhaal voor een andere keer!

IBA Verklaart POST Requests

Zo rond het begin van de jaren negentig kwam Tim Berners-Lee op het idee van het WereldWijde Web. Alle informatie op de wereld wordt daarmee aan elkaar gekoppeld met behulp van pagina’s die links bevatten naar andere pagina’s. Met een browserprogramma dat HTTP (Hypertext Transfer Protocol) spreekt, kan iedereen deze pagina’s ophalen van servercomputers die over de hele wereld verspreid zijn. Meer dan twintig jaar later is het principe van het web nog ongeveer hetzelfde gebleven, maar dan compleet anders opgevat. Pagina’s zijn geen statische documenten meer die ergens op een harde schijf staan, maar interactieve programma’s die doen alsof ze statische documenten zijn die ergens op een harde schijf staan. Daarbij komt nog aardig wat kijken.

Lees verder IBA Verklaart POST Requests

IBA Verklaart Achievements

Zoals velen van jullie al is opgevallen heeft de A–Eskwadraatwebsite sinds kort achievements voor alle ingelogde leden. Natuurlijk is het leuk om zoveel mogelijk achievements te verzamelen maar sommigen zijn misschien wel benieuwd hoe dat nou allemaal in z’n werk gaat, al die achievements.

Achievements kunnen we opdelen in twee categorieën, eenmalige achievements en de zogenaamde ‘medaille’-achievements. Voor eenmalige achievements hoeft 1 bepaalde actie 1 keer uitgevoerd te worden en bij medaille-achievements wordt je voortgang in een teller bijgehouden en er zijn oplopende drempelwaarden voor het halen van elk level van de achievement.

Voor elke eenmalige achievement houden we in een functie bij hoe de achievement gehaald kan worden. Op het moment dat een pagina geladen wordt kijken we of er een achievement gehaald is. Al onze pagina’s op de website worden met een speciale end-functie afgesloten. Aan deze end-functie is nu toegevoegd dat voor het lid dat ingelogd is de achievements gechecked worden. Als er nieuwe achievements zijn, worden deze met javascript bovenaan de pagina weergegeven. De achievementschecker wordt pas bij het afsluiten van de pagina aangeroepen, omdat als de functie bij het begin de pagina zou staan, zou het langer duren voordat de gebruiker een pagina te zien krijgt.

De check voor de medaille-achievements werkt net iets anders. Die functie ziet er als volgt uit:

static public function checkBSGPBadge($badgeNaam, Persoon $pers, $setlast = true)
{
    global $BADGES;

    $badgesBSGP = $BADGES['bsgp'];

    if(array_key_exists($badgeNaam, $badgesBSGP)) {
        $badge = $badgesBSGP[$badgeNaam];

        if($badge['multi'] == 'long') {
            $multiplier = array(1, 2, 5, 10);
        } elseif($badge['multi'] == 'short') {
            $multiplier = array(1, 2, 3, 4);
        }

        foreach($multiplier as $multi) {
            $res = PersoonBadge::badgeBSGPCount($badgeNaam, $pers);
            if($res &gt;= $badge['value'] * $multi) {
                $persoonBadges = $pers-&gt;getBadges();
                $persoonBadges-&gt;addBadge($badgeNaam . '_' . ($badge['value'] * $multi), $setlast);
            }
        }
    } else {
        user_error("Badge " . $badgeNaam . " bestaat niet!");
    }
}

Eerst wordt er gekeken of de achievement die je wilt controleren (variabele $badgeNaam) wel bestaat in de lijst met bestaande achievements. Dan zijn er twee soorten medailleachievements: short en long. De long-achievements hebben als vermenigvuldigingsfactor 1, 2, 5 en 10 voor brons, zilver, goud en A–Eskwadraat respectivelijk en de short hebben als vermenigvuldigingsfactor 1, 2, 3 en 4. Dan wordt er voor iedere vermenigvuldigingsfactor gekeken of het resulterende getal de drempelwaarde overschrijdt.

Om een zo breed mogelijk aanbod aan achievements te kunnen doen en makkelijk nieuwe achievements te kunnen toevoegen worden de achievements in een json-string opgeslagen. Hier kan je zien wat er gebeurt als er een nieuwe achievement wordt toegevoegd bij een gebruiker:

public function addBadge($badge, $setlast = true)
{
    $badges_json_string = $this-&gt;getBadges();
    $last_json_string = $this-&gt;getLast();
    
    $badges = json_decode($badges_json_string);
    $last = json_decode($last_json_string);
    
    if(sizeof($badges) != 0 &amp;&amp; in_array($badge, $badges)) {
        return;
    }   
    
    $badges[] = $badge;
    
    if($setlast) {
        if(sizeof($last) == 0 || (sizeof($last) != 0 &amp;&amp; !in_array($badge, $last))) {
            $last[] = $badge;
        }   
    }   
    
    $badges_json_string = json_encode($badges);
    $this-&gt;setBadges($badges_json_string);
    
    if(sizeof($last) != 0) {
        $last_json_string = json_encode($last);
        $this-&gt;setLast($last_json_string);
    }   
    
    $this-&gt;opslaan();
}

Je kan zien dat eerst de huidige json-string met achievements opgehaald wordt uit het $this-object. Als de achievement al bij de gebruiker staat doen we natuurlijk niets. Dan wordt aan de gedecodeerde json-string (die nu een array is) de nieuwe achievement toegevoegd. Dit wordt dan vervolgens weer als een json-string opgeslagen. Alles met $last in de bovenstaande functie wordt gebruikt om op te slaan wat de nieuwe achievements van de gebruiker zijn sinds de gebruiker voor het laatst is ingelogd.

Dit geeft je een klein beetje een idee hoe de achievements op de A–Eskwadraatsite werken. Heb je zelf nog goede ideeën voor leuke achievements, voel je vrij om ze te melden in de IBA-chat of op Bugweb!