Blog

Det går framåt

Det blev visst en ordvist här. ”Det går framåt”. Jättekul! För att JavaScript ofta handlar om frontend. Men titta här:

Sedan jag startade min JavaScript-resa i måndags med freeCodeCamp så har jag nu gått igenom grundstegen. Jag gillar upplägget med ett interaktivt fönster som man kan koda i och jag tog mig snabbt genom de grundläggande delarna (Basic JavaScript). Jag har fortsatt till ES6. ES6 står för EcmaScript 6 och är synonymt med den senaste standarden av JavaScript. Det ES6 erbjuder är bland annat konkurrerande variabeldeklarationer till var; dessa är let och const. Med let så kan man få varning om man försöker deklarera en till variabel med samma namn. Det innebär också att den variabel som deklareras också kommer hålla sig inom det block där det deklarerades. I en for-loop så kommer let i att vara förbehållet den loopen. Men med var så kommer i att finnas tillgänglig utanför loopen. Med const så kan man skapa konstanter. Om jag gör en konstant const PI = 3.14; så kommer jag inte kunna ändra värdet på PI senare i koden.

Fler roliga saker är arrow functions. Dessa påminner om de lambda-funktioner som kom med Java 8. Det dessa gör är att det blir enklare att göra anonyma funktioner. Kombinerat med att man kan skicka godtyckligt många argument så får man väldigt mycket flexibilitet.

Än så länge har ES6 erbjudit JavaScript sådant som jag känner igen från min tid med Java. Något som jag däremot bara skrapat på ytan än så länge är callback functions och destructuring assignment. Jag behöver mer träning här.

Jag fortsätter med kurserna på freeCodeCamp och återkopplar vad jag lär mig. Under tiden rekommenderar jag att ni håller ögonen på #100daysOfCode på Twitter. Det är fantastiskt vad folk motiverar varandra där och det är något som gör mig glad. Vi ses på fredag!


Från baksida till framsida – dags att lära mig JavaScript

Förra veckan la jag till en nyhetsblogg till Bokarenan som dessutom kom med logisk perma-länk till respektive inlägg. Det finns fortfarande fler funktioner och justeringar som kan göras till hemsidan, men för närvarande riktar jag min blick till JavaScript. Jag vet att det finns de som löser både frontend och backend med JavaScript, men för min del har jag än så länge undvikit det hela på alla sidor. Undantaget är när användare ska manuellt lägga till bokinformation och behöver fler fält om en bok har flera författare. Faktum är att jag vet näst intill ingenting om JavaScript. Nu är det dags att ändra på det!

Denna vecka kommer jag därför att börja lära mig JavaScript. Jag tittar därför på www.freecodecamp.org och ser om deras sätt att lära ut är något för mig. Detta blir det tredje programmeringsspråket jag lär mig. Tidigare har jag lärt mig Java och PHP. Med Java var det inledningsvis böcker som jag använde mig av, för att sedan använda TeamTreehouse. Med PHP började jag också med en bok och försökte sedan med TeamTreehouse igen. Men att lära mig PHP genom Treehouse var inget för mig då. Jag tror att jag började på en för enkel nivå då och blev lite uttråkad. Jag kunde bygga funktionella saker efter den första boken, så att använda officiella guider verkade vara lösningen för mig. Nu går jag alltså in för JavaScript utan att ha läst någon bok innan. Jag är dock väl inläst på de grundläggande detaljerna som är gemensamt för många programmeringsspråk, jag måste dock lära mig dialekten och de finesser som följer med språket.

Upplägget på freeCodeCamp är textbaserad förmedling av information kombinerat med interaktiva test. Det innebär att det finns ett kodar-fönster i samband med informationen där man får försöka klara av olika test. Så här kan det se ut:

Exempel på en sida ur JavaScript-tutorial på freeCodeCamp.org

Som del av att lära mig JavaScript så har jag gått med i gemenskapen #100DaysOfCode. Det innebär ett åtagande gentemot gemenskapen att programmera en timme om dagen i etthundra dagar. För att hålla mig på banan nu när jag ger mig in i ett nytt språk är det bra att få det extra lilla stödet man kan få av varandras pepp.

Vi ses på onsdag, då blir det lite initiala reaktioner på JavaScript. Men nu kör vi!


Uppdaterade nyheter

Hej kära vänner och läsare! Det är fredag och helg. Många av oss sätter oss i soffan ikväll med chips och tittar på något underhållande. De senaste veckorna har jag och min sambo kunnat njuta av den dumma (men roliga!) tv-serien Medical Police på Netflix. Tyvärr var det bara 10 avsnitt så nu får vi ägna oss åt något annat. Men eftersom det är fredag så skriver jag veckans sista inlägg så här på eftermiddagen. Den här veckan har fokus varit på programmering och att lägga till en blogg-funktion till Bokarenan. I onsdags skrev jag om hur Symfony och Doctrine har underlättat skapandet av en ny entitet (BlogPost) och uppdateringen av databasen. Denna gång ska jag skriva om den avslutande delen: hur allt ska kunna presenteras till användaren.

Det finns två komponenter att beakta när det kommer till hur nyheterna presenteras till användarna: template och Controller. Jag tänkte börja med Controller.

Min tanke är att den som är administratör ska kunna skriva ett blogginlägg (nyhet). Jag löste detta genom att använda AdminController och lägga till två funktioner till denna Controller som jag alltså har haft sedan tidigare. Den första funktionen innebär att administratören kan lägga till ett nytt inlägg. Något som jag vill lyfta fram som några detaljer är att administratören kan välja publiceringsdatum. Det innebär att inläggen inte dyker upp under Nyheter om inte publiceringsdatumet har nåtts. Den andra detaljen jag vill lyfta fram är ”slugs”. Det innebär att varje inlägg har en unik länk i stil med 2020-01-31-Det_här_är_en_nyhet. Detta kommer till användning när man vill titta på endast en nyhet, eller för sökmotorers möjligheter att länka direkt till ett inlägg.

Den andra Controllern som behövde uppdateras var NewsController. Denna kontroller har tilluppgift att presentera nyheter till användare. I kontrollern så skapade jag en ny funktion som hämtar de senaste inläggen och skickar dem till template-engine. Det tillkommer lite fler detaljer som innebär att jag kan paginera allt ihop och bara hämta de inlägg som ska vara på den aktuella sidan som användaren är på. Oftast är detta första sidan, men länkar till övriga sidor dyker upp längst ned.

Vad är då template-engine? Det är i princip en funktion som renderar html (eller php-filer med html-element) med dynamiskt innehåll. Som template-engine använder jag Twig. Från NewsController skickar jag de aktuella inläggen till Twig som löser det hela med att placera innehåll på rätt ställen och presenterar det med html-element och innehåll till användaren.

I NewsController så kan det se ut så här:

    /**
     * @Route("/{page}", name="nyheter_index", methods={"GET"})
     */
    public function index(BlogPostRepository $blogRepository, $page=1): Response
    {
        if (!\is_numeric($page)) {
            $page=1;
        }

        
        $count = $blogRepository->getCount();
        $limit = 1;
        $pages = $count/$limit;
        $pages = \ceil($pages);
        if ($page > $pages) {
            $page = $pages;
        }
        $posts = $blogRepository->getLatest($page, $limit);
        return $this->render("nyheter/index.html.twig", [
            "count" => $count,
            "page" => $page,
            "pages" => $pages,
            "posts" => $posts
        ]);
    }

Man kan se att det finns en template fil under filmappen nyheter som heter index.html.twig. Den filen ser ut så här:

{% extends "content.html.twig" %}
{% block navNyheter %}active{% endblock %}
{% block content %}
    {% for post in posts %}
        <article>
            <div class="article-header">
                <h1><a href="{{ path("nyheter_view", {'slug': post.slug}) }}">{{ post.title }}</a></h1>
            </div>
            <div class="article-content">
                <p class="time">{{ post.publish|date("d/m/Y") }} av {{ post.user }}</p>
                <p>{{ post.text|striptags('<em><strong><i><mark><cite><dfn>')|raw|nl2br }}</p>
                {% if app.user == post.user %}
                    <p><a href=""></a></p>
                {% endif %}
                
            </div>
        </article>
    {% endfor %}
    <div class="flex-center">
        {% for i in 1.. pages %}
            {% if i == page %}
                <a class="page-number active" href="/nyheter/{{i}}">{{ i }}</a>
            {% else %}
                <a class="page-number" href="/nyheter/{{i}}">{{ i }}</a>
            {% endif %}
        {% endfor %}
    </div>
{% endblock %}

Som man kan se i ovanstående kod så kan jag komma åt variabeln $posts genom instruktionen {{ post }}. Och när jag använder det på rätt sätt så kan jag få ett resultat som liknar det nedan.

Så det var allt för denna gången. Jag har skrivit ett blogginlägg om att göra en bloggfunktion för att göra blogginlägg. Blogg. Nu har jag skrivit det så mycket att jag börjar läsa det hela som grogg. Och apropå det: spel! Jag har visserligen en viss varm känsla för Secret of Monkey Island, men något som jag ser fram emot nu är att börja spela Skyrim igen. Senast jag gjorde det var 2013. Nu har jag den uppdaterade versionen på PS4. Jag får se om det fortfarande kan hålla mig underhållen. Men det är lugnt. Jag har några partyspel som nog funkar gott ändå!

Trevlig helg, allihopa!


Att göra en nyhetsblogg

Denna onsdag skriver jag om Bokarenan och möjligheten att bygga på den med fler funktioner. Det som står på dagordningen denna gång är en nyhetsblogg. För att få till detta så är det tre saker som ska komma på plats:

  • Ny entitet
  • Uppdaterad databas
  • Uppdaterad presentation/view

Det enklaste är att skapa en ny entitet med hjälp av MakerBundle i Symfony. Det innebär att jag via ett CLI (kommandotolken) kan instruera Symfony att göra den nya entiteten åt mig. På vägen får jag hjälp av Symfony för vad jag ska göra härnäst. För att starta det hela så utgår jag från projektets root-mapp och kör följande kommando:
php .\bin\console make:entity

Detta ger följande interaktion:

Jag döper min nya entitet till BlogPost, och ger den följande fält:
– title [string]
– text [text]
– entered [datetime]
– modified [datetime]
– publish [datetime]
– user [ManyToOne]

Exempel på hur fältet user i BlogPost relaterar till en annan entitet. User är det objekt som alltså refereras av BlogPost. ManyToOne innebär att respektive BlogPost bara kan referera till en användare, men en användare kan skapa flera BlogPost.

Genom hela denna process så har Symfony skapat och uppdaterat klassen BlogPost. Om vi tar en översikt över kursen så har den följande metoder och fält:

Då var steg ett avklarat. Nästa steg är att uppdatera databasen. Återigen är Symfony behjälplig… eller rättare sagt så är det faktiskt Doctrine. I CLI:t så kör jag följande kommandon:
php .\bin\console make:migration
Detta är en instruktion från Symfony till Doctrine hur databasen ska uppdateras efter att en till entitet har lagts till. Då återstår att låta Doctrine uppdatera databasen:
php .\bin\console doctrine:migrations:migrate
Databasen är nu uppdaterad och har rätta relationerna mellan BloggPost-tabellen och User-tabellen.

Då var två av tre steg avklarade. Det som återstår nu är att uppdatera presentationen för denna nya entitet. Detta steg består faktiskt av flera detaljer. Det innebär att en kontroller (eller två) ska uppdateras, en template för att skapa bloggposter ska skapas, en template för att presentera bloggposter ska uppdateras. Detta steg återkommer jag till på fredag. Vi ses då!


Statistik ”avklarad” och frågan om Oauth2

Det var onsdag den 30 oktober 2019 när jag började skriva något om statistik på den här bloggen. Det har blivit 20 inlägg i den kategorin och nu är jag klar med den kurs jag gått under senhösten/vintern. Jag har behandlat ämnen så som sannolikhet, standardavvikelser, standardiserade värden, normalfördelning, hypoteser, centrala gränsvärdessatsen, konfidensintervall, proportioner, chi2 och linjär regression. Jag har gått från deskriptiv statistik till prediktiv analys med en förklaringsvariabel. Emellanåt har det varit utmanande att finna tid till att skriva om statistiken och plugga, samtidigt som jag tagit hand om bebisar, tränat och programmerat. Men jag tycker att jag lärt mig mycket om statistik och jag har nu några idéer om hur jag skulle kunna tillämpa några av de kunskaper jag fått. Så här är några idéer:

  • Undersök korrelation mellan löptid och förlorad vätska. Min hypotes är att det finns ett positivt förhållande mellan hur länge jag springer och hur mycket vätska jag blir av med.
  • Undersök om jag har preferens för en särskild kategori böcker jämfört med andra. Jag behöver dock ett större läsunderlag klart innan jag kan påbörja detta. Jag tror att chi2-analys kan vara på sin plats då.
  • Sammanställ en beskrivning hur länge det tar att lägga upp en ny recension på Bokarenan innan en användare lägger upp en ny. Hur ser sambandet mellan detta och längden på den bok som recenseras.

Så även om jag är klar med statistikkursen så är jag inte klar med statistiken. Vi får se var det smyger sig in framöver. Men nu kommer jag flytta fokus tillbaka till programmering ett tag.

Förra måndagen skrev jag att jag skulle kolla på möjligheten att logga in med oauth (eller rättare sagt oauth2) till Bokarenan. Då skrev jag att jag eventuellt skulle titta på inloggning med Google-konto. Nu har jag kollat möjligheter och provat implementeringar och kan rapportera tillbaka.

Jag kom att prova med Facebook istället för Google och provade följande behjälpliga paket: knpuniversity/oauth2-client-bundle tillsammans med league/oauth2-facebook. Det jag fick göra var att skapa en controller för Facebook-inloggning och registrering samt en autentiserare för det också. Jag upplevde instruktionerna från knpuniversity/oauth2-client-bundle var enkla att följa och redigera för egna behov. Det krävdes att jag fick lägga till ytterligare autentiserare i min konfigurering (security.yaml) och att jag skrev vilken av dem som i första hand skulle användas:

        guard:
            authenticators:
                - App\Security\FacebookAuthenticator
                - App\Security\LoginFormAuthenticator
            entry_point: App\Security\LoginFormAuthenticator

Jag fick en till konfigureringsfil (knpu_oauth2_client.yaml) med instruktioner för autentisering:

knpu_oauth2_client:
    clients:
       
        facebook_main:

            type: facebook
            client_id: '%env(OAUTH_FACEBOOK_ID)%'
            client_secret: '%env(OAUTH_FACEBOOK_SECRET)%'

            redirect_route: connect_facebook_check
            redirect_params: {}
            graph_api_version: v2.12

Det denna konfigureringsfil innehåller är alltså vilken ”användare” och vilket ”lösenord” som ska användas gentemot Facebook för att få en ingång till oauth2 (så användare kan logga in med sina Facebook-användare). Informationen för det sparas i .env-filen. Sedan finns information om vilken funktion i controllern som kommer fånga upp inloggningen.

Det som jag tyckte var det svåraste var om en Facebook-användare behövde registreras som ny användare. Det jag gjorde då var att logga in användaren och sedan dirigera denna till avregistrering om denne inte vill gå med på användarvillkoren. Jag fick ta och registrera i sessionen (via autentiseraren) att användaren var ny och sedan kontrollera detta:

if ($this->session->get('fb-new')) {
    $targetUrl = $this->router->generate('connect_facebook_register');
    return new RedirectResponse($targetUrl);
}

Jag gillade slutresultatet. Det var jätteenkelt att logga in! Men jag har beslutat att för närvarande inte inkludera funktionen i produktion. Anledningen: jag är inte ett företag. Med det vill jag säga att det finns juridiska åtaganden att ta hänsyn till när det kommer till oauth2 och jag vill inte ta ansvar för Facebooks data om användare på min hobby-sida. Det kan vara så att jag överreagerar vad gäller detta och om så vore fallet så återinför jag funktionen.

Det som jag ska göra härnäst på Bokarenan är att införa en nyhetsblogg. Vi får se hur det går. Vi ses på onsdag!


Samband mellan slajm och maskrosor

Så är det äntligen fredag igen. Och som vi har längtat till att få läsa lite om linjär regression. Just det, det är statistik igen (som utlovat)! Denna gång kommer vi återvända till farmaren Frans och hans slajmfarm. Han vill veta om det finns något samband mellan maskrosor och hur mycket slajm som slajmklumparna producerar.

Frans ringer sifferkunniga Samantha igen. Nu börjar det bli ganska många gånger som han har ringt så Sam börjar fundera på att ta ut en avgift. Men hon kommer inte långt i dem tankarna. När hon föra höra regression komma på tal släpper hon allt. Pannkakor kan hon göra sen!

De ägnar nu en dag åt att noggrant mäta den mängd maskrosor som respektive slajmklump äter under dagen, samt väga den slajm de producerar. Det är ganska mycket jobb men de väljer slumpvis 50 slajmklumpar från populationen som ska få delta i denna studie. Allt skrivs ned i ett protokoll.

Efter en lång dag på ranchen tillsammans med Frans så kan Sam äntligen pusta ut. Vid Frans köksbord tar Sam fram sin dator och startar sitt statistikprogram. Hon matar in alla siffror från protokollet i två kolumner; en för mängden maskrosor och en för mängden slajm.

Med alla siffrorna på plats tar hon och ritar upp dem på en graf. I x-led har hon mängden maskrosor och i y-led har hon mängden slajm. Då får hon en graf som ser ut så här:

Det verkar finnas ett förhållande som innebär att ju mer maskrosor som slajmklumparna konsumerat desto mer slajm har de producerat. Hur bra funkar maskrosätande som förklaringsfaktor?

Till sin hjälp har Sam något som kallas korrelationskoefficienten (r). Den visar om det finns något linjärt samband mellan två variabler och riktningen på sambandet. Den kan anta ett värde mellan -1 och 1. Om r är 0 så finns inget linjärt samband, men desto närmare 1 desto bättre stigande linjärt samband. Vice versa för -1 men då fallande samband. Om r hade varit -1 i grafen ovan så hade alla prickarna placerat sig på en linje som lutade nedåt. Genom lite läckra beräkningar där hon i princip summerar faktorer av standardiserade skillnader för varje punkt från respektive medelvärden och dividerar med antalet punkter (minus ett)… det där lät mer komplicerat än att visa formeln:

Det är lite jobbigt att göra beräkningen för hand. Sam skulle behöva beräkna produkten för varje punkt i grafen och det är 50 stycken. Hon tar hjälp av sin dator istället och får fram att korrelationskoefficienten är 0,93. Det verkar finnas ett positivt samband mellan maskrosätande och slajm producerat och det har en ganska stark koppling. Men Sam är inte riktigt klar än. Hon vill veta hur mycket slajm man kan förvänta sig om en slajmklump äter 100g maskrosor. Så hon fortsätter med regressionsanalysen.

Sam vill få fram en modell som kan beskriva hur förhållandet egentligen ser ut. Det Sam tänker sig är att ta fram en funktion som beskriver en linje som passerar genom punkterna. Ungefär så här ska funktionen se ut: y(x)=m+kx. Och den linje som Sam ska ta fram ska ha lika stor mängd som är ovanför som under linjen. Det vill säga att avstånden från linjen för alla punkter ovanför ska vara lika stor som för de punkter som är under. Åter till Sams dator, där får hon fram följande linje:

Linjen kan beskrivas med formeln: y(x)=25,8 + 1,05x +/- 0,13. Om en slajmklump äter 100 g maskrosor kan Frans förvänta sig få ungefär 131 ml slajm från den. Finns det då några andra faktorer som påverkar? Ja, det är möjligt, men maskrosätande har en förklaringsfaktor på 86%. Det är JÄTTEMYCKET.


Maskrosätande

Idag är det onsdag, och som utlovat ska vi idag utreda om gröna slajmar har ett annat förhållande till maskrosor än röda slajmar. Det stämmer, idag är det statistik på agendan!

Vi har tidigare i bloggen kollat på hur stor andel av farmaren Frans kunder som är nöjda med den slajm som han levererar (84% av alla kunder är nöjda med Slajm). Men denna gång vill vi kolla på andelar på ett annat sätt. Farmaren Frans har upptäckt några av hans slajmklumpar inte verkar tycka om de maskrosor som serveras. Han misstänker att de röda slajmarna inte har tillnärmelsevis lika stor aptit för de frekventa blommorna som de gröna slajmarna.

Frans har gott minne över hur den sifferkunnige Samantha hjälpte honom tidigare (Ska jag bry mig om 1 ml hit eller dit?). Sam kunde såklart hjälpa honom även denna gång, så tillsammans utformade de ett enkelt protokoll och iakttog de slajmklumpar som idag fanns i maskroshagen. Protokollet blev en enkel tabell som såg ut så här:

Slajmklumpar som tog för sig av blommorna räknades till de som ”gärna” äter maskrosor. De slajmklumpar som kom fram och sniffade på blommorna utan att äta räknades till de som ”kanske” äter maskrosor. De slajmklumpar som inte åt, och inte sniffade blommorna räknades till de som ”inte alls” äter maskrosor. Som tur gick det ganska enkelt att räkna och hålla reda på alla slajmar eftersom Frans känner sina slajmklumpar så bra. Så efter en dag i maskroshagen hade Frans och Sam fått fram följande resultat:

”Varför har du skrivit dit en massa extra siffror?” frågade Frans.
”Jo du ser att gröna slajmar är 36 stycken, och det finns 24 röda. Det är det som jag skrivit upp till höger”, svarade Sam.
”Okej, men varför har du skrivit summor för varje kolumn? Vad ska det vara bra för?”
”Åh, jag är inte helt klar. Vänta!”

Sam började frenetiskt skriva upp siffror. Först skrev hon 60 i mörkblått i nedre högra hörnet av tabellen.
”Det är summan av alla slajmklumpar som varit i hagen idag.”
Därefter började hon räkna på vad hon kallade var ”de förväntade antalet slajmklumpar för varje cell”. Det hon menade var att man kan förvänta sig att visst många slajmklumpar kommer fördela sig i kategorierna ”gärna”, ”kanske” och ”inte alls” på ett visst sätt om det inte finns någon skillnad mellan röda och gröna slajmare. Det hon vill undersöka är om det stämmer det som Frans påstår: att det finns en skillnad.

Efter att ha räknat ett tag har Sam skrivit upp hur många slajmklumpar det kommer finnas i varje cell om det inte är någon skillnad mellan röda och gröna slajmklumpar. Enligt hennes beräkning kan man förvänta sig att 17 gröna slajmklumpar ”gärna” äter maskrosor. Men resultatet de fick var att 18 stycken gröna slajmare gärna äter blommorna. Har Sam fått ett signifikant resultat? Det verkar som att övriga förväntade resultat ligger nära det uppmäta resultatet! Sam får fortsätta räkna.

Hon börjar med att beräkna hur stor den genomsnittliga avvikelsen är och hur långt det ifrån det förväntade värdet de uppmätta värdena är. Hon använder sig av chi2:

Detta innebär att för varje cell så gör hon en beräkning enligt ovanstående formel och summerar dem.

Sam hade nu fått fram chi2 = 0,66. Med hjälp av en chi2-fördelningskurva så hade nu Sam ett mått på hur stor sannolikheten är att de skillnader mot förväntade antal skulle uppstå av slumpen. Om hon har liten sannolikhet så kan hon utesluta att det inte skulle finnas någon skillnad mellan röda och gröna slajmar. Vad är då sannolikheten?

Till sin hjälp har Sam chi2-fördelningskurva och uträkning av grader av frihet. Grader av frihet räknar hon fram genom att ta antalet rader minus ett gånger antalet kolumner minus ett: (3-1)(2-1)=2. Hon får fram följande graf där det färgade området är sannolikheten att få så stor avvikelse eller större av slumpen. Svaret? 72%!

Sam kunde inte ge stöd åt Frans hypotes. Det verkar som att det för närvarande inte är någon skillnad om röda eller gröna slajmar kommer äta maskrosor. Med Sams hjälp har Frans nu kommit fram till att alla slajmklumpar gott kan få fortsätta dela på maskroshagen.


Uppehåll över, nytt år är igång

Det har nu gått en hel månad sedan jag senast skrev ett inlägg. Då var datumet 20:e december 2019. Det är nu den 20:e januari 2020. I stort sett har jag under hösten skrivit tre inlägg i veckan och jag planerar att fortsätta så den närmaste tiden. Det uppehåll som jag hade var välbehövt. När det kommer till familj så är det något som kommer först. Över nyår och de första veckorna därefter så ägnade jag mycket tid till att hälsa på familj och släkt tillsammans med bebisar som fortsätter att utveckla sig. Till detta har kommit att slutföra den kurs jag har ägnat övrig tid åt: grundläggande statistik. Men ni läsare som har följt mina inlägg ett tag nu vet att jag antagligen lyckats hitta tid över till programmering trots allt detta. Ni har rätt!

Den gångna månaden har jag ägnat strötiden åt att göra en lättare data scaper. Den har till uppdrag att hitta bokinformation så att användare inte ska behöva fylla i femtioelva fält på egen hand. Istället ska användare kunna ägna sig åt att skriva om sin senaste läsning. Jag laddade upp denna funktion vid lunch idag. Så om du vill se om det funkar så kan du bli medlem idag på bokarenan.se/registrera.

Nästa steg i Bokarenan är några mindre justeringar i layouten och jag ska kolla på möjligheten att införa OAuth; eller möjligheten att logga in med ditt Google-konto. Uppdateringar om det kommer längre fram.

Denna vecka på Femte Arenan så kommer jag fortsätta i statistikens tecken. På onsdag kommer jag beskriva hur man kan analysera om det finns statistiskt signifikanta skillnader mellan röda slajmar och gröna slajmar vad avser deras preferens för att äta maskrosor. På fredag kommer jag försöka förutse hur mycket slajm en slajmklump kan producera baserat på hur mycket maskrosor den har ätit under dagen. Vi kommer alltså beröra chi2-analys och linjär regressionsanalys denna vecka. Det är ju toppen, och superintressant för en slajmproducent! Vi ses på onsdag!


En tillbakablick på Bokarenan och Symfony

När jag började mitt projekt Bokarenan nu under hösten så hade jag ett mål att göra min kod mer hanterbar. Jag hade kommit till en punkt då jag inte kände att jag hade någon bra överblick över hur min kod hängde samman. Bokarenan var byggd med PHP men utan att använda någon objektorienterad struktur. Varje sida i applikationen var en egen PHP-fil. Min ”om” sida fanns till exempel på bokarenan.se/om.php, och min sökfunktion fanns på bokarenan.se/search.php. Eftersom man kunde logga in så behövde varje sida inkludera mina variables.php- och functions.php-filer. De användes för att dels hitta rätt filer (sökvägarna sparades i variables.php, bland annat sökvägen för functions.php) och dels för att kontrollera om användaren var inloggad och om användaren varit inaktiv för länge. Det var även viktigt att variables.php inkluderades före functions.php för att functions använde variabler i variables.php. Ju fler funktioner jag ville lägga till i applikationen, desto svårare blev det att överblicka att allting kom i rätt ordning. Jag kände att jag behövde göra min kod mer logiskt sammanhängande för att få rätsida på allt ihop. Svaret var Objekt Orienterad Programmering (OOP).

Jag är hyfsat bekant med OOP sedan allt jag gjort i Java har varit att jonglera objekt. Jag har till och med ägnat mig åt designprincipen MVC (Model – View – Controller) när jag prövat att göra en webapplikation i Spring Boot. Detta är ett framework för Java som jag gillade att använda. Men applikationen gjorde jag aldrig färdig för publicering. Kan hända att det projektet dyker upp här. Jag kallade den för Shipstorm och den var till för att dokumentera båtar som jag tyckte såg fina ut.

När jag nu ville göra en uppdaterad version av Bokarenan så ville jag göra OOP och gärna använda ett MVC-framework. Jag visste ju att det skulle hjälpa mig så mycket att få rätt struktur på allt ihop. Jag visste bara inte vart jag skulle hitta ett framework som skulle passa mig och som skulle kunna funka på mitt webbhotell.

Jag läste en del böcker om PHP samt en kurs på Packt Publishing som guidade mig helt okej igenom olika steg för att göra ett eget microframwork, för att sedan ta steget till att börja använda ett färdigt framework. Det blev Symfony till slut. Symfony upplevde jag som väldigt flexibelt. Det var enkelt att välja vilka komponenter av Symfony jag ville ha. Mina favoriter är Twig, Security och Doctrine. Twig gör det enkelt att generera sidor för dynamiskt innehåll. Security hjälper till med inloggning och autentisering. Och Doctrine gör det väldigt enkelt att hämta objekt från en databas.

Medan jag upplevt det som mycket enkelt att utveckla applikationen på min dator; den medföljande virtuella servern gjorde det hur smidigt som helst, så kvarstod utmaningen att få allt att funka på mitt webbhotell. Jag vill inte exponera känslig information så som databasuppgifter, men vill ju att besökare ska kunna nå min hemsida. Via mitt webbhotell så kan man logga in och använda deras filhanteringssystem. Nackdelen är att detta bara erbjuder den allmänna/publika sidan av hemsidan.

Lösningen hette FileZilla, ett FTP-program, som gjorde det möjligt för mig att även komma åt den yta som inte är publik. Jag kunde därmed dela upp min applikation i dess publika och dess privata delar. På den publika arean så la jag ingångsvägen för applikationen – index.php, samt CSS-, JS-, och bildfiler. På den privata arean la jag applikationslogiken; med Controllers, Entities och template-filer. Men bara detta gjorde inte applikationen redo för användning helt. Jag kunde nu ladda första sidan till Bokarenan på bokarenan.se. Men inga länkar funkade, även om applikationen nu kunde kommunicera med databasen. Det visade ju sig att bokarenan.se egentligen laddade bokarenan.se/index.php. Alla länkar gick genom denna fil. Så för att ladda till exempel bokarenan.se/om behövde jag ange bokarenan.se/index.php/om. Detta var inte riktigt snyggt i mitt tycke, så något behövde jag göra. Och in kommer RewriteEngine som jag kan komma åt med hjälp av .htaccess. Det är en fil jag lägger på min area och som instruerar servern till att översätta allting igenom index.php-filen utan att det ska synas i adressfältet.

Det har visserligen tagit mig hela hösten att uppdatera Bokarenan med Symfony och ersätta den spagettikod som utgjorde förra versionen, men jag har haft en rimlig anledning att dra ut på det: bebisar. Nu är allt uppe och funkar. Jag kan definitivt tänka mig att använda Symfony för fler projekt och det utgör en bra grund för att underhålla den nya versionen av Bokarenan.


84% av alla kunder är nöjda med Slajm

Idag skriver jag åter om statistik. Denna gång fokuserar jag på proportioner med fokus på en parameter. Ibland vill man göra en undersökning som fokuserar på hur stor andel av en population som ger lyckosamma utfall. Det kan handla om hur många produkter från en tillverkningsprocess som ej är defekta, eller det kan handla om hur många väljare som kan tänka sig rösta för ett särskilt alternativ. Denna gång återvänder jag till Slajm-farmaren för att undersöka hur stor andel av hans kunder som är nöjda med den slajm som han säljer.

Vi tar ett urval med storlek n=250. Antalet nöjda kunder är X=210. För att räkna ut andel nöjda kunder i vårat urval så har vi :

Vi vill gärna kunna säga något om alla kunder, inte bara kunderna i vårat stickprov. Vi väljer att svara med ett konfidensintervall på en konfidensnivå 95%. För att räkna ut intervallet så har vi vår andel (0,84) plus/minus en marginal:

Marginalen räknas ut med hjälp av det kritiska värdet z* som tas fram för den angivna konfidensnivån 95%. Det ger oss z*=1,96. Det kritiska värdet här är givet vid en särskild konfidensnivå när vi har en t-fördelning. Det liknar antalet standardavvikelser från medelvärdet i en normalfördelning. Det kritiska värdet multipliceras med standardfelet för urvalet. Det ger oss följande uträkning:

Vi har alltså att 84% av kunderna är nöjda med Slajm, med en felmarginal på 5% på en 95%-konfidensnivå. Slajm-farmaren Frans är inte helt nöjd med detta, för det finns en risk att han inte har uppnått en kundnöjdhet över 80%. Frans har lite att tänka över nu. Varför finns det så många kunder som inte är nöjda? Det är ett mysterium som Frans får utreda framöver. Tills dess är vi klara för den här gången.

Nästa gång, på fredag, tänker jag återvända till programmering och skriva ett par rader om det. Hur enkelt var det egentligen att jobba med Symfony och gick det bra att ladda upp applikationen på ett webbhotell? Vi ses då!