Resultater fra norsk eliteserie i fotball
Tippeligaen
Poengfangst runde for runde
Velg en sesong: selector from setupSeasonSelector() goes here
Det er tre involverte processing-filer:
_nff1.pde
/* Receiving data from javascript and draw animated development of a season in Tippeligaen. Data is year and a string with one line pr team containing teamname and commaseparated accumulated points round by round. Two values pr round: accumulated homepoints and accumulated awaypoints. sample string (far too short): "VIF#0,0,1,0,1,3\nViking#0,0,3,0,1,3" See function setupSeason below. */ // current season Season curSeason=null; // current round int curRound=0; // drawing limits int W=500; int H=500; // size of a marker float circleR=18.0; // texting PFont veryBigFont; PFont bigFont; PFont smallFont; void setup(){ size(W,H); background(255, 255, 255); frameRate(5); veryBigFont=createFont("Arial Bold",70); bigFont=createFont("Arial Bold",30); smallFont=createFont("Arial Bold",12); //setupSeason(2014, "VIF#0,0,1,0,1,3\nViking#0,0,3,0,1,3"); } void draw(){ background(255, 255, 255); // will not show anything unless we have ordred a season if(curSeason!=null) curSeason.drawMe(curRound++); else{ pushStyle(); stroke(0); fill(0); textFont(bigFont); textAlign(CENTER); text("Last opp en sesong",W/2,100); popStyle(); } } //------------------------------- // called from javascript // receive data for a season and set it up void setupSeason(int year, String T){ curSeason=new Season(year,T); curSeason.sortTeams(); curRound=0; }
og
_Season.pde
/* A season hold all teams for the season and which year it is about */ class Season{ int year; Team[] teams; // max points reached in this season of best team float maxPoints;// needed for scaled draw Season(int year,String data){ this.year=year; // data is a multiline text with one line for each team String[] T=data.trim().split("\n"); //one team for each line teams=new Team[T.length]; for (int ix=0;ix < T.length;ix++) teams[ix]=new Team(T[ix].trim()); // find maxpoints, ie best score in all teamss maxPoints=0; for (int ix=0;ix < teams.length;ix++) maxPoints=Math.max(maxPoints,teams[ix].getMax()); } // do a simple bublesort, decreasing ponts void sortTeams(){ boolean done=false; while(!done){ done=true; for(int ix=1;ix <teams.length;ix++) if(teams[ix-1].getMax() < teams[ix].getMax()){ Team tmp=teams[ix-1]; teams[ix-1]=teams[ix];teams[ix]=tmp; done=false; } } } // draw up to and including round void drawMe(int round){ // find leader in this round int leaderIx=0; for(int ix=1;ix < teams.length;ix++){ if(teams[ix].getRoundValue(round) > teams[leaderIx].getRoundValue(round)) leaderIx=ix; } // axis and center text stroke(0); line(0,H-1,W,H-1); line(0,0,0,H-1); pushStyle(); textFont(veryBigFont); fill(120); textAlign(CENTER); text(year,W/2,H/4); popStyle(); // draw each team for(int ix=0;ix < teams.length;ix++){ //horizontal offset float xpos=circleR+1+ ix*((W-30)/(teams.length+1)); teams[ix].drawAtPos(round,xpos,maxPoints,ix==leaderIx); } } }
og
_Team.pde
/* a team ha a name and a history the histoy is accumulated points for each round */ class Team{ String name; float[] history; Team(String S){ // vif#hp,ap,hp,ap,hp,ap // get the name String T[]=S.split("#"); name=T[0].trim(); // the rest is history, two values pr round // add this two values to get sum of homepoints and away points String[]V=T[1].split(","); history=new float[int(V.length/2)]; int hix=0; for(int vix=0; vix < V.length; vix+=2){ history[hix]=float(V[vix].trim())+float(V[vix+1].trim()); hix++; } } // max value for this team //(since history is accumulated) float getMax(){ return history[history.length-1]; } // value at this round, or last round recorded float getRoundValue(int round){ return history[Math.min(round,history.length-1)]; } // draw a team, text at bottom and baloon with line void drawAtPos(int round,float xpos,float maxPoints,boolean markedAsBest){ // round is allways within limits // xpos is position along hor axis // maxpoints are best teams final result, used for scaling float points=getRoundValue(round); textFont(smallFont); textAlign(LEFT); fill(0); float H=height-80; // this is used to perform a temporary translate and rotation pushMatrix(); // show teamname rotated translate(xpos,H); pushMatrix(); translate(0,10); rotate(PI/4); text(name,0,0); popMatrix(); // display a line up to a "baloon" with points stroke(255,0,0); float top=map(points,0,maxPoints,-10,-H+30); fill(255); line(0,0,0,top); ellipse(0,top,30,30); // show point within the baloon fill(0); textAlign(CENTER); text(points,0,top); if(markedAsBest){ stroke(200); line(-xpos,top-16,width,top-16); } popMatrix(); } }
Javascriptkoden er slik:
_produce.js
// all seasons as loaded var seasons; // when we have loaded the page function initAll(){ loadSeasons(); setupSeasonSelector(); var selector=document.getElementById("year"); selector.value="2015" selector.onchange=function(){markYear()}; setTimeout(markYear,100); } // load all data, all seasons function loadSeasons(){ // local data with var assignment alldata=<JSON>: seasons=alldata.seasons; // otherwise, do syncron ajax } // look for a season, by year function getSeason(year){ for(var six=0;six<seasons.length;six++) if(seasons[six].year==year){ return seasons[six]; } return null; } // locate a team in the seasonStatus we // are building in produceProString function findTeam(teamName,resultlist){ for(var ix=0;ix < resultlist.length;ix++) if (resultlist[ix].name==teamName) return resultlist[ix]; return null; } // produce the string we are to send to processing // together with the year function produceProString(year){ //"Viking,5,5,3,4,1,2 #Rosenborg,0,3,5,6,7,8" // name,hp,ap,hp,ap#name,hp,ap,hp,ap // two values (accumulated homepoints,accumulated awaypoints) for each round // assume seasons are loaded var season= getSeason(year); if(!season){ console.log("ERROR, NO SEASON",year); return; } var matches=season.matches; // we build in this array, with an element pr round // only one match pr team pr round var seasonStatus=[]; // set up initial team-object list for(var ix=0;ix < matches.length;ix++){ var theTeam=findTeam(matches[ix].hteam,seasonStatus); if(theTeam==null){ var newTeam=[{ "name":matches[ix].hteam, "homepoints":0, "awaypoints":0, "proString":"" }]; seasonStatus=seasonStatus.concat(newTeam); } } // walk throug matches and update prostring in seasonStatus for(var mix=0; mix < matches.length; mix++){ var match=matches[mix]; var hteam=findTeam(match.hteam,seasonStatus); var ateam=findTeam(match.ateam,seasonStatus); if(match.hscore == match.ascore){ hteam.homepoints+=1; ateam.awaypoints+=1 }else if(match.hscore > match.ascore) hteam.homepoints+=3; else ateam.awaypoints+=3; // and update string hteam.proString+=hteam.homepoints+","+hteam.awaypoints+","; ateam.proString+=ateam.homepoints+","+ateam.awaypoints+","; } // format it and return, make round 0 so all starts at origo var result=""; for(var ix=0;ix < seasonStatus.length;ix++){ var ps=seasonStatus[ix].proString; ps=ps.substring(0,ps.length-1); // loose a , result=result+seasonStatus[ix].name+"# 0,0,+"+ps+"\n"; } return result; } // new year, update teamselectors and sen data to processing function markYear(){ var year=parseInt(document.getElementById("year").value); // send year data setYear(year); } // --------- talk to the sketch ---------- // all data for a year function setYear(year){ // identify processing var pjs=Processing.getInstanceById("draw1"); var T=produceProString(year); pjs.setupSeason(year,T); }
og litt kode for å konfigurere websiden med selectorer:
_makehtml.js
// prepareing selector elements according to // selected data function setupSeasonSelector(){ var T='<select style="font-size:14px;" name="year" id="year" >'; for(var six=0;six<seasons.length;six++){ year=seasons[six].year; T+='<option value="'+year+'">'+year+'</option>'; } T+='</select>'; document.getElementById("seasonselector").innerHTML=T; }