Framstilling av en fotballsesong
Datagrunnlaget er en rekke filer som innholder en liste av alle lag og alle kamper. Du kan se et eksempel her Eliteserien2016.json.
Løsningen ser slik ut
test.html.
Det er flere komponenter involvert. Selve sketchen som setter opp løsningen:
_sketch.js
/* Setter opp en skisse som er motoren i tegningen */ var resultater; // datakilde var overskrift; var sesongObj=null; // aktuell sesong var sesongen; var runde; // aktuell runde var visBobler; // kurveform var dataLoaded=false; // data på plass // Dette gjøres før noe annet skjer function preload() { // starter med an lokal fil // selectorer er synket sesongObj = loadJSON("data/Eliteserien2016.json",preparerData); } function loadNewSeason(){ dataLoaded=false; var land_liga=document.getElementById("landvalg").value; var aar=document.getElementById("aar").value; resultater="https://borres.hiof.no/fotballdata/json/"+land_liga+aar+".json"; // med callback, preparerData, når dataer hentet sesongObj = loadJSON(resultater,preparerData); } function preparerData(){ dataLoaded=true; // ordne data sesongen=new sesong(sesongObj); //oppdater lagstatus etter alle rundene sesongen.oppDater(sesongen.getAntallRunder()); // sett maxpoeng (hjelper oss å tegne) sesongen.setMaxPoeng(); overskrift=sesongen.getLiga()+" "+sesongen.getAar(); // max på skider document.getElementById("runden").max= sesongen.getAntallRunder(); runde=0; document.getElementById("runden").value=runde; } function setup(){ var canvas = createCanvas(800,500); canvas.parent('canvasHere'); runde=0; document.getElementById("runden").value=runde; visBobler=true; }; function draw(){ background(255,255,255); if(dataLoaded){ push(); fill(0); textAlign(CENTER,TOP); textSize(20); text(overskrift+" - runde: "+runde,width/2,2); pop(); runde=document.getElementById("runden").value; if(runde > sesongen.getAntallRunder()){ runde=sesongen.getAntallRunder(); } sesongen.oppDater(runde); if(visBobler) tegnSesongBobler(sesongen,runde); else tegnSesongHistogram(sesongen,runde); } else{ text("Data er ikke lastet",width/2,height/2); } } function bobler(on){visBobler=on}
Merk at vi bruker preload med callback for å ta vare på asynkron lasting.
Et klubb-objekt er beskrevet slik:
_klubb.js
// ett lag med navn og akkumulerte poeng function klubb(klubbObj){ this.navn=klubbObj.name; this.poeng=0; this.getNavn=function(){return this.navn} //----------- funksjoner --------- // shekker en kamp og ser om dette laget er med this.oppdaterPoeng=function(kamp){ if(kamp.hteam == this.navn){ if(kamp.hscore > kamp.ascore) this.poeng+=3; else if (kamp.hscore == kamp.ascore) this.poeng+=1; } else if(kamp.ateam == this.navn){ if(kamp.hscore < kamp.ascore) this.poeng+=3; else if (kamp.hscore == kamp.ascore) this.poeng+=1; } } // antall poen nå this.getPoeng=function(){ return this.poeng; } // tilbake til start this.resetPoeng=function(){ this.poeng=0; } // hva heter laget this.getNavn=function(){ return this.navn; } }
En sesong er beskrevet slik:
_sesong.js
/* en sesong for en liga basert på resultater (matches) inklusive enliste av lagnavn (teams) */ function sesong(JsonRes){ this.aar=JsonRes.year; this.serie=JsonRes.liga; this.kampListe=JsonRes.matches; this.maksPoeng=0; // legger til lag i denne sesongen this.klubbListe=new Array(); for(var ix=0;ix <JsonRes.teams.length;ix++){ this.klubbListe[ix]=new klubb( JsonRes.teams[ix]); } //----------- funksjoner-------- // regner ut maks poeng this.setMaxPoeng=function(){ for(var i=0;i < this.klubbListe.length;i++){ this.maksPoeng=Math.max(this.maksPoeng,this.klubbListe[i].getPoeng()); } //og sorterer lagene this.klubbListe.sort( // compare: function(a,b){ return b.getPoeng()-a.getPoeng(); } ) } // opdaterer status til en bestemt runde this.oppDater=function(runde){ var r=Math.min(runde,this.getAntallRunder()); // nullstill for(var i=0;i < this.klubbListe.length;i++){ this.klubbListe[i].resetPoeng(); } // fordel poeng t.o.m. denne runden for(var j=0; j < this.kampListe.length; j++){ var kamp=this.kampListe[j]; if( kamp.round <=r ){ for(var i=0;i < this.klubbListe.length;i++){ this.klubbListe[i].oppdaterPoeng(kamp); } } } } // hvor mange runder er det i denne sesongen this.getAntallRunder=function(){ return int(this.kampListe[this.kampListe.length-1].round); } // årstallet this.getAar=function(){ var y1=this.kampListe[0].date.split(".")[0]; var y2=this.kampListe[this.kampListe.length-1].date.split(".")[0]; if(y1==y2) return y1; else return y1+"/"+y2; } // liganavnet this.getLiga=function(){ return this.serie; } // antall klubber this.getAntallKlubber=function(){ return this.klubbListe.length; } // finn et lag this.getLag=function(i){ return this.klubbListe[i]; } // hva er maks poeng noe lag har fått denne sesongen this.getMaksPoeng=function(){ return this.maksPoeng; } }
Vi har to alternative tegne funksjoner:
Histogram
_tegningH.js
/* tegn et histogram for en bestemt runde i en sesong */ function tegnSesongHistogram(sesongen,runde){ // marginer for å lette tegningen var marginB=60; var marginL=10; var marginR=70; var marginT=20; // x-aksen line(0,height-marginB,width,height-marginB); var step=(width-marginL-marginR)/sesongen.getAntallKlubber(); push(); // flytt origo ned til venstre i det fargede feltet translate(marginL,height-marginB); for(var i=0; i< sesongen.getAntallKlubber();i++){ push(); translate(i*step+step/2,0); // hvor høyt skal vi var v=map(sesongen.getLag(i).getPoeng(), 0,sesongen.getMaksPoeng(), 0,height-marginB-marginT-step) // en søyle push(); fill(200,255,255); rect(0,0,step,-v); pop(); // marker laget med navn textAlign(CENTER,BOTTOM); text(sesongen.getLag(i).getPoeng(),step/2,-v); textAlign(LEFT,TOP); rotate(PI/8); text(sesongen.getLag(i).getNavn(),step/2,0); pop(); } pop(); }
og boblediagram
_tegningB.js
/* Tegn en et boblediagram for en runde i en sesong */ function tegnSesongBobler(sesongen,runde){ // marginer for å lette tegningen var marginB=60; var marginL=10; var marginR=70; var marginT=30; // x-aksen line(0,height-marginB,width,height-marginB); // feltet der boblene skal være push(); fill(200,255,255); noStroke(); rect(0,marginT,width,height-marginB-marginT); pop(); // avstand mellom lagene ( diameter i boblene) var step=(width-marginL-marginR)/sesongen.getAntallKlubber(); push(); // flytt origo ned til venstre i det fargede feltet translate(marginL,height-marginB); // så tegner vi klubber bortover for(var i=0; i< sesongen.getAntallKlubber();i++){ push(); // vandrer mot venstre translate(i*step+step/2,0); // hvor høyt skal vi var v=map(sesongen.getLag(i).getPoeng(), 0,sesongen.getMaksPoeng(), 0,height-marginB-marginT-step); // så vi går klare av x-aksen v+=step/2; // ballong med sn"snor2 line(0,0,0,-v); fill(255); ellipse(0,-v,step,step); // marker laget med navn textAlign(CENTER,CENTER); fill(0); text(sesongen.getLag(i).getPoeng(),0,-v); textAlign(LEFT,TOP); rotate(PI/8); text(sesongen.getLag(i).getNavn(),0,5); pop(); } pop(); }