Onze mensen in de spotlight: Sjors Koevoets Onze mensen in de spotlight: Jurrie Zaat Onze mensen in de spotlight: Jacco Rijkaart Onze mensen in de spotlight: Bart Lemstra Onze mensen in de spotlight: Wouter Verkuijl Leren programmeren animeren

Leren programmeren animeren

Het is pakweg 2 jaar geleden dat ik met deze serie ben begonnen en daarmee de missie om jou, mijn trouwe lezer te leren programmeren. In mijn tweede blog hebben we samen een spel geprogrammeerd, maar omdat we samen tot de conclusie waren gekomen dat OrcadoInvaders iets te hoog gegrepen was voor je eerste introductie tot programmeren, was dat een tekstgebaseerd_computerspel spel. Herinner je je het weer? Ondertussen heb je al heel wat meer geleerd en ook zeker niet onbelangrijk is de P5js webeditor uitgekomen. Ik vermoed dat ik P5 wel eens eerder heb genoemd; het is de JavaScript bibliotheek die ik gebruik in de meeste van mijn code voorbeelden, waaronder TicTacToe en OrcadoInvaders. P5 is gebaseerd op processing.org een organisatie die net als ik, de ambitie heeft om meer mensen te leren programmeren. Maar als ik jou was zou ik mijn blog lezen, dan krijg je tenminste ooit nog uitgelegd wat 3-waarden-logica nou precies is en hoe dat werkt.

Maar niet vandaag. Vandaag gaan we weer samen een spelletje programmeren, maar nu met graphics. Na wat overwegingen wat nou een goed spel zou zijn om samen te maken is de keuze gevallen op ‘hooghouden’, er is een heel sub genre van dit spel op bijvoorbeeld funny games, maar volgens mij zijn die allemaal in flash, en gezien flash vanwege de vele veiligheidsproblemen binnenkort in geen enkele browsers meer draait, zijn dat allemaal niet echt goede voorbeelden. Gelukkig is het spelletje heel simpel; je hebt een bal, die valt naar beneden, als je er op klikt ‘schiet’ je hem omhoog, het doel is om de bal zo lang mogelijk hoog te houden voor dat die valt. We gaan dat doen in de hiervoor genoemde P5js webeditor.

Zodra je de webeditor opent zie je links de code en als je op de play-knop drukt zie je rechts het resultaat van de code. Klik maar eens op play, je ziet rechts een vierkant verschijnen. De code die daar voor zorgt staat links onder setup en draw. Setup wordt aan het begin 1x uitgevoerd en draw elke seconde 60x. In setup wordt een canvas aangemaakt van 400 breed en 400 hoog. Ik denk graag zo groot mogelijk dus dat mag je direct veranderen in:
createCanvas(windowWidth, windowHeight);
Hiermee maken we het canvas (waar we op gaan schilderen) zo breed en hoog als in het scherm past. In draw krijgt het canvas een grijze achtergrond kleur, dat is wat saai en aangezien hooghouden een voetbal spelletje is maken we dat meteen gras groen:
background(0,180,0);
Als het goed is, is het hele rechtervlak nu groen. Mocht dat nou niet zo zijn of als je ergens verderop de draad kwijt bent, dit is het eind resultaat, kan je spieken wat er mis is gegaan.

Ok, het gras is er, nu een bal. Daarvoor gaan we een object maken (ik heb je niet voor niets leren objectificeren). P5 ondersteunt om hiervoor een apart bestand aan te maken, en dat is eigenlijk mooier, maar voor de eenvoud hou ik het even in één bestand. Eerst maken we een bal functie die als ons object gaan dienen:

function Bal(){
}

De computer moet weten hoe groot de bal is en waar die op het scherm moet worden getekend, dus daarvoor maken we variabelen aan in de functie.

function Bal() {
  this.diameter = 50;
  this.x = 0;
  this.y = 0;
}

En de bal moet getekend worden, daarvoor maken we een functie aan:

function Bal() {
  this.diameter = 50;
  this.x = 0;
  this.y = 0;

  this.teken = function() {
    ellipse(this.x, this.y, this.diameter, this.diameter);
  };
}

In die functie staat nu dat we een ellips tekenen op coördinaten (0,0) en met de breedte en hoogte van de diameter. Aangezien een ellips met gelijke breedte en hoogte een perfecte cirkel is, gaat dit een cirkel tekenen. Om de bal te laten tekenen moeten we dit aanroepen in de draw functie. Eerst maken we de bal variabele aan in setup

function setup() {
  createCanvas(windowWidth, windowHeight);
  bal = new Bal();
}

Zodat we daarna in de draw functie hem kunnen laten tekenen.

function draw() {
  background(0,180,0);
  bal.teken()
}

Er verschijnt nu een witte kwart cirkel in de linker bovenhoek, laten we hem even in het midden zetten voor het gemak, verander daarvoor in het bal object de x en y waarden respectievelijk  windowWidth/2 en windowHeight/2. De bal staat nu midden in het scherm.

Nu gaan we wat leven in de bal brengen. Dat gaan we doen door zwaartekracht toe te voegen. In een hele volwassen versie van dit spel gebruiken we daarvoor een physics engine, dat is software die natuurkundige krachten nabootst, daarmee kunnen we rekening houden met het gewicht van de bal, de luchtweerstand, de gravitatie constante en dat soort dingen. Dat is echter overkill voor wat we aan het doen zijn, we gaan de bal een verticale snelheid geven, en de zwaartekracht verhoogt die snelheid neerwaarts. Eerst maar verticale snelheid aan het bal object toevoegen:

this.verticalesnelheid = 0;

En we maken een zwaartekracht functie die die snelheid beïnvloed en dan ook de y coördinaat van onze bal:

this.zwaartekracht = function() {
  this.verticalesnelheid += 0.2;
  this.y += this.verticalesnelheid;
};

Dan alleen nog zorgen dat de zwaartekracht toegepast wordt elke keer als we de bal tekenen, daarvoor zetten we onder bal.teken(), bal.zwaartekracht() en voilá de bal valt naar beneden. Klein probleempje, de bal verdwijnt al snel onder de grond. Dat is natuurlijk niet goed. We zullen in onze super eenvoudige versie van een physics engine de grond de bal laten stuiteren door een opwaartse kracht toe te voegen als de grond geraakt wordt, soort derde wet van Newton zeg maar:

if (this.y + this.diameter / 2 > windowHeight) {
  this.y = windowHeight - this.diameter / 2; // zorg dat de bal niet vastkomt in de grond
  this.verticalesnelheid *= -0.8;
} else {
  this.verticalesnelheid += 0.2;
}

En hup, de bal stuitert, het verdient geen nobelprijs voor de natuurkunde, of zelfs maar een voldoende op een middelbare school toets, maar dit is soort van hoe zwaartekracht werkt, en goed genoeg voor ons spelletje.

Nu moeten we de bal nog hoog kunnen houden, dat gaan we doen door er op te klikken. P5 heeft een ingebouwde functie om muisklikken te herkennen, alle functies die P5 ondersteunt kan je vinden in de referentie. We gaan gebruik maken va de touchStarted functie, in mijn ervaring werkt het dan goed met zowel muizen als met aanraakgevoelige schermen zoals mobiele telefoons.

function touchStarted() {
  bal.verticalesnelheid -= 20;
  return false;
}

Die return false wordt aangeraden in de reference dus dat doen we maar braaf. Het zal je inmiddels opgevallen zijn dat een negatieve snelheid de bal naar boven brengt en een positieve snelheid de bal naar beneden. Dat komt omdat het y-coördinaat 0 helemaal boven in het scherm ligt en het y-coördinaat met de schermhoogte helemaal onderin het scherm.

Dit werkt, alleen het maakt nu niet uit waar je klikt, dat maakt het een suf spelletje. Dit kan je nu makkelijk winnen door in je console met een interval muisklikken te genereren (je hebt immers leren automatiseren). We moeten dus kijken of er op de muis wordt geklikt. We hebben gelukkig ook de x en y coördinaten van de muis (of vinger) dus we hoeven alleen maar te controleren of de afstand tussen de muis en de bal gelijk of kleiner is dan de straal van de bal. Dit is normaal het moment dat ik me realiseer dat ik meer de straal dan de diameter gebruik en de code daar op aanpas, maar ik begin inmiddels de spreekwoordelijk prangende ogen van mijn redactrice in mijn rug te voelen gezien ik al ver over het aantal streefwoorden per blog ben (ik geef persoonlijk de ellenlange zinnen die ik maak de schuld, alsof ik een kommarecord probeer te verbreken…), dus dat mag je straks zelf doen. Dat is overigens ook de reden dat ik onze gezamenlijke flashback naar middelbare school wiskunde en de stelling va Pythagoras)  oversla (ja, daar hadden we nu eindelijk een keer ‘in het echt’ gebruik van kunnen maken) en gebruik maak van de euclidische afstandsfunctie die in P5 zit ingebakken:

if (dist(bal.x, bal.y, mouseX, mouseY) <= bal.diameter / 2) {
  bal.verticalesnelheid -= 20;
}

Op zich werkt het nu, maar het is wel een erg verticale aanpak, dat is wel heel erg agile, maar voor het spelletje niet echt leuk. Probeer zelf eens toe te voegen dat als je de bal links van het midden raakt hij naar rechts gaat en andersom (en vergeet niet van de zijkant muren te maken zodat je de bal niet kwijt raakt). Ik heb het in het eindresultaat zit, maar ik geloof dat je dit zonder spieken kan!

Als je dat gedaan hebt is het tijd voor het testen, dan blijkt dat het spelletje misschien iets te uitdagend is geworden. Met een klein beetje tweaken aan de gebruikte getallen en een scoreteller toe te voegen hebben we in de basis het spelletje. Dat valt echter ook buiten de scope van dit blog, maar dat moet je niet laten weerhouden om het zelf te doen en hoewel het het beste is om dat zonder hulp op te lossen hoeveel moeite je dat kost, kan ik me herinneren hoe frustrerend dat kon zijn toen ik net begon met programmeren, dus ook daarvoor een spiekbriefje.

Leren programmeren automatiseren

Leren programmeren automatiseren

Ik heb lang getwijfeld over dit blog, voor de beste uitleg zou ik jullie namelijk mee willen nemen in de wereld van autohotkey (https://www.autohotkey.com/) dat is een programma waarmee je op Windows heel makkelijk een heleboel dingen kan automatiseren. Het gebruikt echter zijn eigen programmeer taal, en ik doe mijn best om al het programmeren dat ik samen met jullie doe, in javascript te doen, zodat jullie makkelijk mee kunnen blijven doen. Een aardige uitleg waarom ik jullie autohotkey wilde laten zien en waarom ik het niet heb gedaan, is dit filmpje van Tom Scott.

Een nadeel van javascript voor het uitleggen van automatisering is dat je browser veilig is gemaakt. Elke keer dat je naar een andere pagina gaat  wordt je console opnieuw gestart. Dat is maar goed ook, want als dat niet zou gebeuren zou je daar vreselijk misbruik van kunnen maken. Maar dat betekent dus dat je alleen maar dingen in je browser kunt automatiseren die binnen hetzelfde scherm gebeuren. Wat je dan nog wel kunt doen is data van een andere website ophalen via een API en dat vervolgens gebruiken tijdens je automatisering. Dus mocht je straks de smaak te pakken hebben, pak mijn vorige blog er nog een keer bij.

Maar laten we iets simpeler beginnen. Het idee van iets automatiseren is dat je een taak die saai is of die je vaak moet doen, door de computer kan laten doen. Dat klinkt heel aanlokkelijk, maar het is niet altijd de moeite waard. Xkcd heeft een tabel waarin je kunt opzoeken of het zinvol is om iets te optimaliseren door het te automatiseren:  (bron: xkcd.com)

Als je er dan ook nog een andere xkcd bij pakt over automatiseren schetst dat een plaatje waarin het automatiseren van taken niet altijd de heilige graal is die het soms lijkt te zijn:

Dat neemt niet weg dat je soms door iets te automatiseren enorm veel werk door een computer kan laten doen in plaats van mensen, of de computer taken kan laten doen waar je zelf eigenlijk geen zin in hebt. Uit ervaring blijkt dat totaal fictieve onrealistische voorbeelden vaak het beste zijn, het zet de lezer namelijk aan tot zelf een realistisch scenario te bedenken. Bovendien is het voor mij het minste werk en dat is toch een beetje waar dit blog over gaat. Dus we doen een raar hypothetisch voorbeeld.

Stel je doet een online survey over een video en om te zorgen dat je de video blijft kijken en dat je niet bij je computer wegloopt moet je van de website elke 20 seconden op een knop drukken, dat reset een timer,als die timer niet op tijd gereset wordt is je aandacht er schijnbaar niet genoeg bij en krijg je niet betaald. De ethische oplossing is elke 20 seconden op de knop drukken, de makkelijkste manier, automatiseer het drukken op de knop. Hier is de site: https://undercover.horse/automatiseren/resettimer.htm

Het automatiseren van deze taak is vrij eenvoudig. Wat we willen doen is  elke X seconde op de knop drukken, omdat te doen moeten we eerst weten hoe de knop heet, daarvoor kijken we naar de broncode van de site. Daarin vinden we:

<button id="btn" onclick="set20()">reset de timer</button>

Dat is makkelijk, de knop heeft een id attribuut. Javascript heeft een manier om een object te selecteren bij zijn id:

document.getElementById()

We geven het id “btn” mee en dan gebruiken we de click functie om er op te  klikken:

document.getElementById("btn").click()

Dat is 1 klik, we willen het echter elke X seconden, omdat te doen kunnen we er een interval van maken:

setInterval('document.getElementById("btn").click()',5000);

Deze code zorgt er voor dat er elke 5000 milliseconden (gelijk aan 5 seconden) op de knop wordt geklikt. Als je dat in je console plakt ben je klaar, de timer komt niet meer voorbij 15.

Dit is een truc die je op elke pagina toe kan passen die een knop heeft waar je op moet klikken die niet de hele pagina ververst. Ander voorbeeld: stel je voor je wilt een kaartje kopen, om dat te doen moet je op de bestelknop op een pagina klikken. Deze wordt echter pas klikbaar op een bepaald moment. Je kan geduldig op de site wachten en toeslaan zodra de knop beschikbaar wordt, of je blijft er constant op klikken en loopt er bij weg. Hier is een demo pagina: https://undercover.horse/automatiseren/klikzsm.htm

Kleine tegenvaller, als we naar de knop kijken zien we dat hij geen id heeft:

setInterval('document.getElementById("btn").click()',5);

Dat is echter makkelijk op te lossen, als je in je console zit kan je naar het tabblad elements waar je de html van de pagina ziet staan. Als je vervolgens met je rechtermuisknop op de html code van de button klikt, kan je kiezen voor “edit as HTML” en dan kan je er zelf gewoon id=”btn” bij zetten. (Je moet buiten het edit-blokje klikken om het te bevestigen) Omdat we zo snel mogelijk willen zijn zetten we de interval waarde wat lager:

setInterval('document.getElementById("btn").click()',5);

Nu gebeurt het elke 5 milliseconden, daar kan je zelf nooit tegenop klikken. In het huidige voorbeeld is het alleen wel zo dat je al die acties binnen 20 seconden moet doen anders is de knop al beschikbaar. Als alternatief kan je ook de knop zoeken door alle knoppen te zoeken en dan de eerste uit de lijst te kiezen:

setInterval('document.getElementsByTagName("button")[0].click()',5);

Het klikken op een knop is handig, maar vaak moet je meer op een pagina doen dan alleen een knop indrukken. Gelukkig kan je met javascript een heleboel van die dingen gewoon doen. Neem bijvoorbeeld een pagina met  een formulier zoals deze: https://undercover.horse/automatiseren/formulier.htm

Stel we willen blauw een heel aantal keer kiezen. Dan kunnen we het formulier een aantal keer achter elkaar invullen. Of we automatiseren het:

let y = function () {
  document.getElementsByTagName("input")[0].value = "Daan";
  document.getElementsByTagName("input")[1].value = "Veraart";
  document.getElementsByTagName("input")[4].checked = true;
  document.getElementsByTagName("button")[0].click();
}
setInterval(y, 100);

Dit lijkt allemaal vrij triviaal, maar dit zijn dan ook nog maar hele simpele voorbeelden, die je allemaal in je browser kunt uitvoeren. De essentie is echter dat je een taak opsplitst in kleine subtaakjes en dan kijkt of je die met een stukje code kan oplossen. Dat is iets wat je bij programmeren eigenlijk heel vaak gebruikt. Alleen dan in de vorm van helper functies. Als je en stuk code meerdere keren in je applicatie hebt staan, dan kan je beter van dat stuk code een functie maken. Elke keer dat je dan dat stuk code nodig hebt, automatiseer je dat door in plaats van dat stuk code te typen, de functie aan te roepen. Bijkomend voordeel is dat als je iets aanpast in dat stuk code, het meteen op alle plekken in je programma aangepast is.

Het leukste van iets automatiseren is kijken hoe de computer voor je aan het werk is. Zo heb ik laatst het verplaatsten van Vimeofilmpjes naar Youtube geautomatiseerd. Als je het dan opstart (de foutmelding oplost waar je tegenaan loopt (voor degene die het filmpje van Tom Scott hebben gezien, het was een beetje een bodge) en nog een keer opstart) en je ziet dat hij logregel voor logregel braaf bezig is, en dan op Youtube het filmpje ziet verschijnen met dezelfde titel en omschrijving als dat het op Vimeo heeft, dat geeft een voldaan gevoel. Het is wel een klein beetje zonde dat we de tijd die we gewonnen hebben met automatiseren besteden aan het kijken naar hoe de computer het werkt doet, die hadden we beter kunnen besteden aan het uitleggen van drie waarde logica… Misschien moet ik dat maar eens proberen te automatiseren. 

Leren programmeren APIreciëren

Leren programmeren APIreciëren

Belofte maakt schuld, vandaag hebben we het over APIs. API is de afkorting voor application programming interface. Een interface gebruik je om te communiceren met een applicatie. De bekendste vorm daarvan is de GUI (graphical user interface); als je een applicatie opstart op je computer of telefoon dan is wat je ziet de GUI, het is de manier waarmee jij met de applicatie kan communiceren. Je kijkt nu naar de GUI van je browser, je kan communiceren door bijvoorbeeld te scrollen en je browser beantwoord door de pagina naar boven of beneden te verschuiven. Voor mensen is een grafische interface handig, een plaatje zegt immers meer dan 1000 woorden. Voor een computer is dat anders, die communiceert een stuk makkelijker met alleen tekst.

Nu vraag je je misschien af, hoe vaak gebeurt het nou dat een applicatie met een andere applicatie communiceert? Dat ligt een beetje aan je definitie. Als je het heel sec bekijkt, communiceert jouw browser nu met een server om deze tekst op te halen, met de driver van je scherm om het op je scherm te laten zien, met je muis of touchscreen om je invoer te registreren enzovoort. Er is dus heel veel interactie, maar we gaan het over een heel klein gedeelte hebben, want ik ratel altijd al veel te veel en anders komt er geen eind aan.

We gaan het hebben over WebAPIs, dat is waar de meeste mensen het over hebben als ze API zeggen, dus dat is wel zo makkelijk. WebAPIs zijn functies die je aan kan roepen via het internet die informatie terug geven van de applicatie waar ze voor geschreven zijn. Dat is vrij abstract, dus het is zoals altijd tijd voor een voorbeeld. Stel je wilt iemand 3-waarden logica uitleggen… Wacht ik heb jullie nog steeds geen 3-waarden logica uitgelegd en ik zit alweer boven de 300 woorden en ik ben nog niet eens begonnen met het voorbeeld, we doen wel iets anders… Stel je wilt iemand Engels leren, maar aangezien je het wel leuk wilt houden besluit je een spelletje te maken.

Het spelletje is heel simpel je pakt een plaatje, je geeft er een aantal woorden bij en dan moet er geraden worden welk woord er bij het plaatje hoort. Klinkt simpel toch? Als je er nog een beter beeld bij wilt hebben kan je het hier spelen. Ik heb het basic gehouden dus er is bijvoorbeeld geen score, maar ik heb wel een hint optie toegevoegd, want het spelletje is zonder soms niet te doen.

Voor het spelletje heb ik 2 dingen nodig, een heleboel Engelse woorden en een heleboel bijpassende plaatjes. Die kan ik natuurlijk zelf samenstellen, maar er zijn applicaties op het internet die dit al hebben dus die kan ik ook gebruiken. In dit voorbeeld gebruik ik de wordnik.com API. Wordnik is een online woordenboek en daar mag je gratis gebruik van maken. Tenminste als je het niet te zot maakt, om dat een beetje in de gaten te houden heb je een sleutel nodig om gebruik te maken van hun API, deze kan je gratis aanvragen en daarmee mag je dan een 100 aantal aanvragen per uur doen.  Dus als je het spelletje heel enthousiast speelt dan zal hij het op een gegeven moment een uur niet doen. Wil je meer aanvragen doen, dan moet je daar voor betalen. De andere API is die van imgur.com, zelfde idee maar dan een plaatjes site.

We beginnen met het ophalen van 12 willekeurige Engelse woorden. Dat doen we met een API call. De Wordnik API heeft daar deze functie voor. Die roepen we aan met een URL:  https://api.wordnik.com/v4/words.json/randomWords?hasDictionaryDef=true
&minCorpusCount=50
&maxCorpusCount=-1
&minDictionaryCount=20
&maxDictionaryCount=-1
&minLength=6
&maxLength=6
&limit=12
&api_key=APISLEUTEL
. Deze URL vertaalt ongeveer naar: Op de v4 versie van de api.wordnik.com applicatie roepen we van de words.json functies de functie randomWords aan met een aantal argumenten. Voor de leesbaarheid heb ik alle argumenten op een eigen regel gezet. Alles achter het vraagteken zijn de argumenten waarmee ik woorden terug laat komen van 6 letters die niet super obscuur zijn. Ja, trouwe lezer, daar staat words.json. Tegenwoordig gebruikt het leeuwendeel van de WebAPIs JSON strings om te communiceren. Zoals je in het vorige blog hebt kunnen lezen zijn dat javascript objecten en dat is makkelijk want ik programmeer dit spelletje in javascript.

In de code ziet dit er zo uit:

async function laadApi() {
  //code niet belangrijk voor de uitleg// 
  let wordnik_res =  await fetch(url1+x);
  woorden = await wordnik_res.json();

Voor wie al sinds blog 1 enthousiast mee aan het programmeren is valt het waarschijnlijk op dat er ineens iets voor function staat. Het woord async geeft aan javascript aan dat er dingen asynchroon gaan gebeuren. Dit is volgens mij ook de eerste keer dat ik het gebruik, voor nu ga er maar even vanuit dat het hetzelfde is als var. De functie fetch haalt gegevens uit vanuit de url die je meegeeft. Ik geef de url van hierboven mee met mijn API sleutel. Normaal gesproken als je fetch afvuurt gaat daarna direct de volgende regel van je code af. De fetch functie kan even duren, maar daar wil je browser als het niet hoeft niet op wachten. Wij kunnen echter niet verder voor we die data hebben, dus we zeggen met het woord await tegen de browser dat hij moet wachten tot fetch klaar is voordat hij verder mag gaan met de rest van de code. Hetzelfde geldt voor de json functie, die het resultaat omzet in een javascript object. Na deze twee regels code is ‘ woorden’ dit:

[{
  "id": 234698,
  "word": "Yankee"
}, {
  "id": 16370,
  "word": "beggar"
}, {
  "id": 31968,
  "word": "chorus"
}, {
  "id": 47154,
  "word": "dental"
}, {
  "id": 129143,
  "word": "magpie"
}, {
  "id": 133965,
  "word": "miller"
}, {
  "id": 81088,
  "word": "patrol"
}, {
  "id": 70598,
  "word": "reform"
}, {
  "id": 73645,
  "word": "severe"
}, {
  "id": 228047,
  "word": "vector"
}, {
  "id": 81488,
  "word": "volley"
}, {
  "id": 74147,
  "word": "worthy"
}]

Tenminste, deze keer, elke keer dat we die code uitvoeren krijgen we andere woorden terug van Wordnik. Het is een lijst met 12 objecten, alle objecten hebben een id, een nummer waar we verder niets mee doen, en een word, het woord waar we naar opzoek waren.

Als we dat hebben zoeken we daar een plaatje bij:

woord = random(woorden).word
let imgur_res = await fetch(url2+woord, {
    method: "GET", 
    headers: {
        "Authorization": "Client-ID "+ clientID
    }});
  plaatjes = await imgur_res.json()

Eerst pakken we een willekeurig woord uit de rij en dan geven we die mee aan de fetch voor Imgur. De Imgur API heeft de API sleutel niet in de URL staan, maar gebruikt een header voor die informatie. Een header is informatie die je browser meestuurt met een URL. Ook Imgur werkt met json dus we roepen met het resultaat de json functie aan om het bericht weer om te zetten naar een javascript object. De Imgur API geeft veel meer informatie terug dan alleen het plaatje. Zo geeft hij bijvoorbeeld ook terug hoe vaak er gereageerd is op dit plaatje, wie het plaatje heeft geüpload en wat de titel van het plaatje is.  Waar we in eerste instantie in geïnteresseerd zijn is het plaatje zelf.

Tenminste als er een plaatje is. Het kan namelijk best zo zijn dat we van Wordnik een woord hebben gekregen waar Imgur helemaal geen plaatjes bij kan vinden. We moeten dus controleren of er wel plaatjes zijn, als dat zo is dan halen we de link uit het object en laten het plaatje zien waar de link naar verwijst. Vervolgens maken we linkjes van de 12 woorden die we van Wordnik hebben gekregen en zetten die er onder en het spelletje is af. Wil je de rest van de code ook zien, dan kan dat hier; ik heb er ook wat commentaar bij gezet.

Dat zijn dus WebAPIs, je vraagt aan een website gegevens door een specifieke URL aan te roepen en je krijgt die (meestal) in de vorm van een JSON string terug. Waarmee je dan vervolgens weer verder kan programmeren. WebAPIs zijn hip, dus als je denkt ‘dit is leuk!’ ik wil zelf ook wel met een API spelen, hier zijn een aantal voorbeelden van WebAPIs waar je mee kan praten.

Leren programmeren objectificeren

Leren programmeren objectificeren

Voordat ik dit blog ben gaan schrijven heb ik een aantal van mijn trouwe blog lezers toegezegd dat ik in mijn onophoudende missie om te laten zien dat programmeren geen magie is (voor de woordgrap is het belangrijk dat je ons wie-zijn-wij filmpje even kijkt) een blog zou schrijven over APIs. Terwijl ik daar mee bezig ben en aan het kijken wat ik daar voor uit wil leggen loop ik tegen JSON aan, wat staat voor JavaScript Object Notation. JavaScript is al wel een heel aantal keer voorbij gekomen, maar objects heb ik nog niet echt uitgelegd. In eerste instantie wilde ik een kleine paragraaf er aan wijden, maar dat voelde wat karig. Het alternatief was om het te noemen en dan later toe te lichten, maar ik moet ook ooit nog een keer 3-waarde logica uitleggen en het was eigenlijk logischer om dat eerst te doen. De APIs komen volgende keer (of de keer daarop) maar vandaag: object georiënteerd programmeren.

Misschien dat je de term object georiënteerd programmeren of de afkorting OO/OOP wel eens voorbij hebt zien komen. Object georiënteerd programmeren is een manier van programmeren, andere vormen zijn bijvoorbeeld functioneel, logisch of declaratief. De code die ik jullie tot nu toe heb laten zien is allemaal declaratief; het is een opsomming van constructies. Bij OOP ga je uit van objecten. Stel je maakt een spelletje zeg monopolie, dan is eigenlijk alles wat je vast kan houden een object: het bord, het geld, de pionnen, de kanskaarten, de straten etc. Als voorbeeld ga ik de dobbelstenen nemen, vooral omdat die vrij universeel in een heleboel andere spellen gebruikt worden.

Omdat ik geloof dat je moet blijven proberen om programmeren een beetje onder de knie te krijgen ga ik de objecten als een functie implementeren, dat is misschien niet de manier waarop de meeste tutorials het uitleggen, maar het zorgt er voor dat je de script snippets die ik straks laat zien zo in je browser console kunt plakken en uit proberen. Bovendien kan ik daarmee in een later blog heel makkelijk JSON uitleggen, maar dat is voor later. Laten we een object gaan maken.

Voor het maken van een object moeten we eerst bedenken wat de eigenschappen van dat object zijn. Voor een standaard dobbelsteen is dat een kubus met dus een 6 tal zijdes, met op die zijdes een aantal ogen oplopend van 1 t/m 6. Ook is het zo dat de som van het aantal ogen van de twee zijdes die het verst van elkaar afliggen 7 is, maar daar gaan we ons in het voorbeeld geen zorgen over maken. Eerst gaan we het aantal zijdes toevoegen.

var dobbelsteen = {
  aantalZijdes: 6
}

Dat was nog niet heel ingewikkeld toch? Laten we ook nog de ogen toevoegen, dat is een lijstje, dus dat zetten we tussen blokhaken.

var dobbelsteen = {
  aantalZijdes: 6,
  ogen: [1, 2, 3, 4, 5, 6]
}

Als we dat in onze browser console gooien en we proberen vervolgens het 3de oog te laten zien ziet dat er zo uit:

var dobbelsteen = {
  aantalZijdes: 6,
  ogen: [1, 2, 3, 4, 5, 6]
}
dobbelsteen.ogen[2];
> 3

Dat komt een lijstje in JavaScript begint bij 0, dus als we het 3de element willen hebben moeten we het item uit het lijstje hebben met het nummertje 2. Nu hoor ik je denken, leuk, maar wat is hier nou het voordeel van boven:

var dobbelsteenZijdes = 6;
var dobbelsteenOgen = [1,2,3,4,5,6];

Goede vraag, ik had hem zelf kunnen stellen. Een voordeel is dat je de variabelen mooi groepeert en die groepering vervolgens weer gemakkelijk ergens anders kunt gebruiken. Ook geeft het je code een gestructureerde logica, alles is een object en heeft eigenschappen. Maar een object kan meer dan alleen variabelen groeperen. Hij ondersteunt naast eigenschappen ook acties en in JavaScript zijn acties functies. Dobbelstenen moeten rollen, dus laten we een functie maken om dat te ondersteunen.

var dobbelsteen = {
  aantalZijdes: 6,
  ogen: [1, 2, 3, 4, 5, 6],
  dobbel: function () {
    return this.ogen[Math.floor(Math.random() * this.aantalZijdes)]
  }
}

Nu kunnen we dobbelen door de functie aan te roepen als actie van de dobbelsteen:

dobbelsteen.dobbel();
> 4

Met monopolie heb je twee dobbelstenen en het aantal zetten dat je mag doen is het totaal van de twee dobbelstenen, dat is nu simpel te doen:

dobbelsteen.dobbel()+dobbelsteen.dobbel()
> 7
dobbelsteen.dobbel()+dobbelsteen.dobbel()
> 6

Bij de 7 gaat dit goed, bij 6 echter kan het zijn dat we dubbel hebben gegooid, namelijk 2x 3, als dat zo is mogen we nog een keer gooien, dus dat is wel belangrijk om te weten. Of een worp ‘dubbel’ is eigenlijk een eigenschap van beide dobbelstenen. Als beide dobbelstenen samen één eigenschap hebben, dan zijn ze eigenlijk samen voor ons ook  een object dat bestaat uit 2 dobbelsteen objecten. Dat ziet er zo uit:

var dobbelstenen = {
  aantalDobbelstenen: 2,
  dobbelstenen: [dobbelsteen, dobbelsteen]
}

Dat is wel heel vaak het woord dobbelsteen, en we mogen zelf de namen kiezen, dus laten we dit object worp noemen:

var worp = {
  aantalDobbelstenen: 2,
  dobbelstenen: [dobbelsteen, dobbelsteen]
}

De worp heeft dan natuurlijk ook een actie dobbel, waar in beide dobbelstenen worden gedobbeld:

var worp = {
  aantalDobbelstenen: 2,
  dobbelstenen: [dobbelsteen, dobbelsteen],
  dobbel: function () {
    return this.dobbelstenen[0].dobbel() + this.dobbelstenen[1].dobbel()
  }
}

Dit lost ons probleem nog niet op, maar we hebben nu de twee dobbelstenen samen, dus we kunnen nu kijken of er dubbel gegooid is, daarvoor voegen we een klein beetje extra logica toe:

var worp = {
  aantalDobbelstenen: 2,
  dobbelstenen: [dobbelsteen, dobbelsteen],
  dobbel: function () {
    let dobbel1 = this.dobbelstenen[0].dobbel();
    let dobbel2 = this.dobbelstenen[1].dobbel();
    let dubbelIndicator = ""
    if (dobbel1 == dobbel2) {
      dubbelIndicator = " dubbel!"
    }
    return dobbel1 + dobbel2 + dubbelIndicator
  }
}

Dan nog even testen of het werkt.

worp.dobbel()
> "6"
worp.dobbel()
> "11"
worp.dobbel()
> "8"
worp.dobbel()
> "4"
worp.dobbel()
> "12 dubbel!"

Aah ja daar is die, nou is het voor 12 natuurlijk altijd dubbel, maar we weten ook dat de 6 8 en 4 die we daarvoor hebben gedobbeld niet dubbel waren.

Nou zijn er ook dobbelstenen met een andere vorm en andere hoeveelheden ogen, in het spel D&D (Dungeons and Dragons) heb je verschillende dobbelstenen en daarmee bedoel ik dit soort dobbelstenen:

Een veelgebruikte is er één met 20 zijdes, die noem je d20 (dobbelsteen met 20 zijdes). We hebben nu het object dobbelsteen met 6 zijdes, maar we kunnen daar ook prima 20 zijdes van maken.

dobbelsteen.aantalZijdes = 20;
dobbelsteen.ogen = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];

Omdat we nu het bestaande object dobbelsteen hebben aangepast is dat ook meteen aangepast in het worp opject, dus als we nu de worp dobbelen kunnen we veel hogere getallen krijgen:

worp.dobbel()
> "21"
worp.dobbel()
> "19"

Dat zijn objecten. Ergens in het begin zei ik dat dit waarschijnlijk niet de manier is waarop het in de meeste tutorials uitgelegd wordt. Wat ik nu heb laten zien is hoe je losse objecten aanmaakt door een variabele te vullen met JSON (JavaScript Object Notation.) Wat je meestal zult zien is dat er een model van een object wordt gemaakt, en dat je daar vervolgens versies van kan maken. Ik zal daar ook nog een voorbeeld van laten zien, maar daar ga ik iets sneller; ik heb het verzoek gekregen de blogs niet te lang te maken, en ik zit al weer op ruim 1000 woorden.

Wat we gaan doen is functie objecten maken, in plaats van JSON gebruiken we een functie om het object te defineren.

//standaard aantal zijdes is 6
function d(az = 6, o = []) {
  this.aantalZijdes = az;
  this.ogen = o;
  //als je alleen het aantal zijdes op geeft vullen we die met getallen
  if (o.length == 0) {
    for (let i = 1; i <= az; i++)
      o.push(i);
  }
  this.dobbel = function () {
    return this.ogen[Math.floor(Math.random() * this.aantalZijdes)]
  }
}

Nu kunnen we simpel zeggen:

var d20 = new d(20);

En nu is d20 een dobbelsteen met 20 zijdes. Maar we kunnen ook een kleuren dobbelsteen maken met:

var dkleur = new d(6,["rood", "geel","groen","paars","oranje","blauw"] );

Als je dan dobbelt krijg je één van die kleuren terug.

dkleur.dobbel()
> "blauw"

Dat kunnen we dan natuurlijk ook voor de worp doen:

function w(ds, aantal = 0) {
  //als er 1 dobbelsteen wordt meegegeven vul het lijstje met aantal stuks er van
  if (aantal > 0) {
    this.dobbelstenen = [];
    for (let i = 1; i <= aantal; i++)
      this.dobbelstenen.push(ds);
  } 
  //anders gebruik de opgegeven dobbelstenen
  else
    this.dobbelstenen = ds;
  this.dobbel = function (show = false) {
    let totaal = 0;
    let resultaat = ""
    for (d of this.dobbelstenen) {
      let ogen = d.dobbel()
      totaal += ogen;
      resultaat += ogen + "+";
    }
    resultaat = resultaat.substr(0, resultaat.length - 1);
    resultaat += "=" + totaal
    if (!show)
      resultaat = "" + totaal
    return resultaat;
  }
  this.dobbelShow = function () {
    return this.dobbel(true);
  }
}

In D&D kan je een spreuk doen die 8d8 aan schade doet (Je moet dan 8 keer met een dobbelsteen met 8 zijdes rollen en het totaal optellen, Dungeons and Dragons ga ik verder niet uitleggen hoor, dat moet je maar een keer bingen), als we dat in onze object georiënteerde functies willen doen kans dat nu zo:

var d8 = new d(8);
var w8x8 = new w(d8,8)
w8x8.dobbelShow()
> "3+1+8+8+7+3+7+6=43"
w8x8.dobbel()
> "30"

Dat zijn kort samengevat objecten. Ik heb het voorbeeld gegeven van dobbelstenen, maar deze techniek kan je voor vrijwel alles toepassen. Kleine tip: als je mensen of dieren objectificeert, zorg dan wel dat je dat alleen tijdens het programmeren doet, sommige dingen vertalen slecht naar de echte wereld.

APEX 18.1

Oracle APEX 18.1
Oracle apex 18.1 is inmiddels alweer twee maanden beschikbaar; hoog tijd dus om er eens iets over te schrijven. Met deze nieuwe versie van APEX heeft het team achter APEX wederom een flinke stap gezet om het leven van de ontwikkelaars gemakkelijker te maken. Ik zal een aantal grote nieuwe/aangepaste features  benoemen, los daarvan zijn er natuurlijk ook nog heel veel kleine aanpassingen gedaan.

Application Builder
In de application builder zijn de wizards aangepakt waardoor ze slimmer zijn geworden en er minder stappen nodig zijn om diverse componenten te maken. De nieuwe create app wizard (APEX blueprint) is echt een nuttige toevoeging. Je kan met deze wizard op een simpele manier een nieuwe applicatie maken zonder één regel code te gebruiken. Bij de property editor is een zogenaamd “sticky filter” gekomen, hierdoor kan je de filter waarden vasthouden. De algemene zoekfunctie is tevens verbeterd deze lijkt nu op de veel gebruikte spotlight search op een Mac computer. Op één plek zoeken binnen de gehele APEX applicatie.

REST
Er zijn diverse verbeteringen en toevoegingen aan de REST functies van APEX gedaan. Zo is er nu REST enabled SQL support, met behulp van de feature kan je SQL statements laten uitvoeren in een andere database met behulp van HTTP en REST. Het resultaat krijg je vervolgens aangeleverd in JSON formaat. Je hoeft dus geen database link meer te gebruiken. Je kan zelfs grafieken, reports en andere APEX componenten maken met behulp van deze functie. Ook kunnen er andere REST services gebruikt worden binnen de APEX applicatie. Binnen APEX is nu een complete REST Workshop gekomen. Hier kan je zelf je REST services definiëren en onderhouden. Van deze services kan je vervolgens ook documentatie laten genereren met één click.

Grafieken
De Oracle JET engine is geüpgraded naar version 4.2. Met JET kan je binnen APEX de mooiste grafieken maken die gebaseerd zijn op HTML5, CSS3 en JavaScript. Een aantal nieuwe grafieken zoals Gannt, Box-Plot en Pyramide zijn toegevoegd.

Mobile ontwikkeling
Ontwikkelen voor mobiele devices was natuurlijk al prima te doen met het Universal theme. Hier is echter ook weer een flinke stap gezet door een aantal componenten die regelmatig gebruikt worden in een mobiele UI zoals Listview, Column Toggle en Reflow Report standaard beschikbaar te maken in dit theme. Tevens zijn er nog een aantal wijzigingen in het Universal theme doorgevoerd specifiek voor mobiele devices zoals pagina headers en footers die meer consistent worden weergegeven. Wellicht de beste toevoeging voor mobiel ontwikkelen is dat er nu standaard support is voor touch based dynamic actions. Je kan nu dus dynamic actions maken voor acties zoals dubbel tikken, vegen en zoomen.

Toegankelijkheid
De manier waarop een applicatie toegankelijk gemaakt kan worden voor minder validen is veranderd. De link onderaan de pagina om om te schakelen naar de toegankelijk modus is verdwenen. Het is de bedoeling dat de applicatie meer wordt ontworpen en gebouwd volgens de regels die opgezet zijn door de W3C organisatie. Om de ontwikkelaar te helpen om dit op een juiste manier te doen, is de APEX advisor uitgebreid zodat deze ook kan testen of je applicatie wel voldoende toegankelijk is voor minder validen.

Font APEX
Font apex is een collectie van meer dan 1000 iconen die je kan gebruiken binnen je applicatie. Deze set is voor APEX 18.1 onder handen genomen o.a. door van alle iconen een 32×32 pixel versie toe te voegen.

Authenticatie
In APEX 18.1 is er een nieuwe authenticatie schema bij gekomen, het zogenaamde social sign-in schema. Hiermee is het voor ontwikkelaars mogelijk om authenticatie op te zetten voor o.a. Oracle Identity Cloud Service, Google, Facebook en generiek OAuth2. Dit alles zonder extra code!

Interactive Grid
De interactive grid is ook onder handen genomen en begint meer en meer excel achtige functies te krijgen. Dit is voor de gebruikers natuurlijk super handig maar ook aan de ontwikkelaars is gedacht. De API van de interactive grid geeft je de mogelijkheid om deze naar eigen believen uit te breiden. Extra menu’s, buttons  of processen het kan allemaal. Om hier goed mee om te kunnen gaan loont het wel om je eerst, in ieder geval een beetje, te verdiepen in de architectuur van de interactive grid.

API
Nu de term API is gevallen kan ik daar nog aan toevoegen dat de JavaScript API’s  aangepast en uitgebreid zijn. Dus nog meer info om je applicaties te kunnen tweaken!

Er valt natuurlijk nog  veel meer te vertellen over deze nieuwe versie maar ik denk dat ik nu wel genoeg redenen heb gegeven om APEX 18.1 snel uit te proberen. Mocht je dit nog niet gedaan hebben maak dan een account aan op apex.oracle.com om met deze versie wat ervaring op te doen.

Of download en installeer het in je eigen omgeving want dat kan natuurlijk ook!

 

 

Hier komt de sidebar

Volg ons op

© Orcado B.V. | 1999 - 2023