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 >= $badge['value'] * $multi) {
                $persoonBadges = $pers->getBadges();
                $persoonBadges->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->getBadges();
    $last_json_string = $this->getLast();
    
    $badges = json_decode($badges_json_string);
    $last = json_decode($last_json_string);
    
    if(sizeof($badges) != 0 && in_array($badge, $badges)) {
        return;
    }   
    
    $badges[] = $badge;
    
    if($setlast) {
        if(sizeof($last) == 0 || (sizeof($last) != 0 && !in_array($badge, $last))) {
            $last[] = $badge;
        }   
    }   
    
    $badges_json_string = json_encode($badges);
    $this->setBadges($badges_json_string);
    
    if(sizeof($last) != 0) {
        $last_json_string = json_encode($last);
        $this->setLast($last_json_string);
    }   
    
    $this->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!

Geef een reactie