> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.ZSY74KMo3yz/rev.1151
 * 
 * authors: 
 *   
 *   
 *   
 *   mar
 *   

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



/*
-------------------------------------------------------------------------------------
Gender-o-meter: A visualization from evolution between olympic records of women and man
Jaume Nualart(http://nualart.cat) & Mar Canet(http://mcanet.info)
10th August 2012 
-------------------------------------------------------------------------------------
*/

int totalTimelines = 2;
int widthViz  = 600;
int heightViz = 200;
int heightMarginViz = 60;
int fontSize = 15;
genderMeter[] myGenderMeter = new genderMeter[1];

void setup() {  // this is run once. 
    // set the background color
    background(255);
    
    // canvas size (Variable aren't evaluated. Integers only, please.)
    size(800, 650); 
      
    // smooth edges
    smooth();
    
    // limit the number of frames per second
    frameRate(30);
    
    // set the width of the line. 
    strokeWeight(1);
    for(int i=0;i<totalTimelines;i++){
        myGenderMeter[i] = new genderMeter();
    }
    
    font = loadFont("arial"); 
    
} 

void draw() 
{
    background(255);
    for(int i=0;i<totalTimelines;i++){
        myGenderMeter[i].setOffsetPosition(50, (heightViz+heightMarginViz)*i+heightMarginViz);
        myGenderMeter[i].setMouseEvent();
        myGenderMeter[i].draw();
    }
}


//==========================================

class genderMeter{
    
Object datosJson = [{ 
"sport":"Athletics",
"discipline":"100m",
"start-date-man":"01/01/1912" , 
"start-date-woman":"01/01/1952",
"records-man":[{"01/01/1912",10.84},{"01/01/1920",10.40},{"01/01/1925",10.30},{"01/01/1930",10.14},{"01/01/1955",10.10},{"01/01/1985",9.89},{"01/01/2012",9.58}] , 
"records-woman":[{"01/01/1924",11.84},{"01/01/1970",10.54},{"01/01/1980",10.20},{"01/01/1985",10.11},{"01/01/2012",9.89}]  
}];

int offsetXWomansRecords;
int offsetX;
int offsetY;
int one_day = 1000*60*60*24;

float maximumValue; 
float minimValue;
int totalDaysViz;
int startDateInSeconds;
boolean mouseInsideViz=false;

genderMeter(){
    totalDaysViz = calculateTotalDaysViz();
    findMinAndMaxValue();
    offsetXWomansRecords = displacementWomanRecords();
    println(offsetXWomansRecords);
}

void setOffsetPosition(int x, int y){
    offsetX = x;
    offsetY = y;
}

void setMouseEvent(){
    if(mouseX>=offsetX && mouseX<=offsetX+widthViz && mouseY>=offsetY && mouseY<=offsetY+heightViz){
        mouseInsideViz = true;
    }else{
        mouseInsideViz = false;
    }
}

void loadJson(String data){
    datosJson = JSON.parse(data);
}

// Calculate total days between dates
int daysBetweenDays( int year1, int month1, int day1, int year2, int month2, int day2){    
    //Set the two dates
    var date1 = new Date(year1, month1-1, day1);//Month is 0-11 in JavaScript 
    var date2 = new Date(year2, month2-1, day2);//Month is 0-11 in JavaScript
    //Get 1 day in milliseconds
    
    //Calculate difference btw the two dates, and convert to days 
    int date1TotalSeconds = date1.getTime();
    int date2TotalSeconds = date2.getTime();
    
    return abs(ceil((date1TotalSeconds-date2TotalSeconds)/one_day));
}

// Calculate total days Visualized
int calculateTotalDaysViz(){
    // Get older start date
    int smallerStartDate;
    var startDateMansStrAr = datosJson[0]["records-man"][0][0].split("/");
    var startDateMansInt = new Date(parseInt(startDateMansStrAr[2]), parseInt(startDateMansStrAr[1])-1, parseInt(startDateMansStrAr[0])).getTime();
    
    var startDateWomansStrAr = datosJson[0]["records-woman"][0][0].split("/");
    var startDateWomansInt = new Date(parseInt(startDateWomansStrAr[2]), parseInt(startDateWomansStrAr[1])-1, parseInt(startDateWomansStrAr[0])).getTime();
  
    if(startDateMansInt <startDateWomansInt){
        smallerStartDate = startDateMansInt;
    }else{
        smallerStartDate = startDateWomansInt;
    }
    // Add to gloval variables
    startDateInSeconds = smallerStartDate;
     
    // Get man last date
    var lastRecordIFromArray  = datosJson[0]["records-man"].length-1;

    var endDateMansStrAr = datosJson[0]["records-man"][lastRecordIFromArray][0].split("/");
    var endtDateMansInt = new Date(parseInt(endDateMansStrAr[2]), parseInt(endDateMansStrAr[1])-1, parseInt(endDateMansStrAr[0])).getTime();

    return abs(ceil((endtDateMansInt-smallerStartDate)/one_day));
}

// Calculate total days Visualized
int calculateManTotalDaysViz(){
    // Get older start date
    int smallerStartDate;
    var startDateMansStrAr = datosJson[0]["records-man"][0][0].split("/");
    var startDateMansInt = new Date(parseInt(startDateMansStrAr[2]), parseInt(startDateMansStrAr[1])-1, parseInt(startDateMansStrAr[0])).getTime();

    // Get man last date
    var lastRecordIFromArray  = datosJson[0]["records-man"].length-1;

    var endDateMansStrAr = datosJson[0]["records-man"][lastRecordIFromArray][0].split("/");
    var endtDateMansInt = new Date(parseInt(endDateMansStrAr[2]), parseInt(endDateMansStrAr[1])-1, parseInt(endDateMansStrAr[0])).getTime();

    return abs(ceil((endtDateMansInt-startDateMansInt)/one_day));
}


int getXPosition(int year, int month, int day)
{
    var dateSeconds =  new Date(year, month-1, day).getTime();
    return  abs(ceil(((startDateInSeconds-dateSeconds)/one_day)*(widthViz/totalDaysViz) ));
}

int getYPosition(float value){
    return ceil( ((maximumValue-minimValue)-(value-minimValue))*(float(heightViz)/(maximumValue-minimValue)) );
}

void findMinAndMaxValue(){
    var lastRecordIFromArray  = datosJson[0]["records-man"].length-1;
    minimValue = datosJson[0]["records-man"][lastRecordIFromArray][1];    
    maximumValue = datosJson[0]["records-woman"][0][1];
    if(maximumValue < datosJson[0]["records-man"][0][1] ){
        maximumValue = datosJson[0]["records-man"][0][1];
    }
}

String getManValueInX(){
    float posX = (mouseX-offsetX)/widthViz;
    //getTotalDaysManViz()
    return String(posX);    
}

String getWomanValueInX(){
    int totalWomanRecords = datosJson[0]["records-woman"].length;
    for(int i=1; i<totalWomanRecords;i++){
        var dateThisWomanRecordAr = datosJson[0]["records-woman"][i][0].split("/");
       if(datosJson[0]["records-woman"][i][1]){
        }
    }
    return String(0.02);    
}

int displacementWomanRecords(){
    float displacementX = 0;
    int lastRecordIFromArray  = datosJson[0]["records-woman"].length-1;
    float bestTimeWomans = parseFloat(datosJson[0]["records-woman"][lastRecordIFromArray][1]); 
    int yW = parseInt(datosJson[0]["records-woman"][lastRecordIFromArray][0].split("/")[2]);
    int mW = parseInt(datosJson[0]["records-woman"][lastRecordIFromArray][0].split("/")[1]);
    int dW = parseInt(datosJson[0]["records-woman"][lastRecordIFromArray][0].split("/")[0]);
    
    int totalRecordsMan = datosJson[0]["records-man"].length;
    for(int i=(totalRecordsMan-1);i>0;i--){
        
        if( bestTimeWomans >= parseFloat(datosJson[0]["records-man"][i][1])){
            int y = parseInt(datosJson[0]["records-man"][i][0].split("/")[2]);
            int m = parseInt(datosJson[0]["records-man"][i][0].split("/")[1]);
            int d = parseInt(datosJson[0]["records-man"][i][0].split("/")[0]);
            displacementX = getXPosition(yW,mW,dW)-getXPosition(y,m,d);
        }
    }
    return displacementX;
}

void draw(){
    fill(255,255,255);
    rect(offsetX,offsetY,widthViz+1,heightViz+1);
    
    // Text
    int marginPX = 4;
    int posXBreak = offsetX+widthViz-offsetXWomansRecords;
    
    textFont(font);
    textSize(fontSize)
    fill(0, 174, 239);
    text("man", posXBreak+marginPX, 30+offsetY); 
    int womanOffsetXPos = textWidth("woman");
    fill(127, 63, 152);
    text("woman", posXBreak-womanOffsetXPos-marginPX, 30+offsetY); 
    
    // Line
    stroke(0,0,0);
    line(posXBreak,30+offsetY,posXBreak,heightViz+offsetY-1);
    
    // draw Woman graph
    noStroke();
    fill(127, 63, 152, 100);
    int totalWomanRecords = datosJson[0]["records-woman"].length;
    
    stroke(127, 63, 152,100);
    float lastWomanValuePosY = getYPosition(datosJson[0]["records-woman"][totalWomanRecords-1][1]);
    line(offsetX,offsetY+lastWomanValuePosY,offsetX+widthViz+15,offsetY+lastWomanValuePosY);
    
    stroke(0, 174, 239, 100);
    line(offsetX,offsetY+heightViz,offsetX+widthViz+15,offsetY+heightViz);
    
    noStroke();
    
    int startXWoman = 0;
    beginShape();
    for(int i=1; i<totalWomanRecords;i++){
        // point 1 for line
        var dateThisWomanRecordAr = datosJson[0]["records-woman"][i-1][0].split("/");
        int posX1 = getXPosition(dateThisWomanRecordAr[2],dateThisWomanRecordAr[1],dateThisWomanRecordAr[0]);
        int posY1 = getYPosition(datosJson[0]["records-woman"][i-1][1]);
        // point 2 for line
        var dateThisWomanRecordAr2 = datosJson[0]["records-woman"][i][0].split("/");
        int posX2 = getXPosition(dateThisWomanRecordAr2[2],dateThisWomanRecordAr2[1],dateThisWomanRecordAr2[0]);
        int posY2 = getYPosition(datosJson[0]["records-woman"][i][1]);
        if(i==1){
            vertex(posX1+offsetX, heightViz+offsetY);
            vertex(posX1+offsetX, posY1+offsetY); 
            startXWoman = posX1;
        }
        vertex(posX1+offsetX, posY1+offsetY);
        vertex(posX2+offsetX, posY2+offsetY);
    }
    vertex(posX2+offsetX, posY2+offsetY); 
    vertex(posX2+offsetX,heightViz+offsetY);
    vertex(startXWoman-offsetX, heightViz+offsetY);
    vertex(posX2+offsetX, heightViz+offsetY);
    endShape();
    
    // draw Man graph
    noStroke();
    fill(0, 174, 239, 100);
    int totalMaleRecords = datosJson[0]["records-man"].length;
    int startXMan = 0;
    beginShape();
    for(int i=1; i<totalMaleRecords;i++){
        // point 1 for line
        var dateThisManRecordAr = datosJson[0]["records-man"][i-1][0].split("/");
        int posX1 = getXPosition(dateThisManRecordAr[2],dateThisManRecordAr[1],dateThisManRecordAr[0]);
        int posY1 = getYPosition(datosJson[0]["records-man"][i-1][1]);
        // point 2 for line
        var dateThisManRecordAr2 = datosJson[0]["records-man"][i][0].split("/");
        int posX2 = getXPosition(dateThisManRecordAr2[2],dateThisManRecordAr2[1],dateThisManRecordAr2[0]);
        int posY2 = getYPosition(datosJson[0]["records-man"][i][1]);
        if(i==1){
            vertex(posX1+offsetX, heightViz+offsetY);
            vertex(posX1+offsetX, posY1+offsetY); 
            startXMan = posX1;
        }
        vertex(posX1+offsetX, posY1+offsetY);
        vertex(posX2+offsetX, posY2+offsetY);
    }
    vertex(posX2+offsetX, posY2+offsetY);
    vertex(posX2+offsetX, heightViz+offsetY); 
    vertex(startXMan+offsetX, heightViz+offsetY);
    vertex(posX2+offsetX, heightViz+offsetY);
    endShape();
    
    // distance between woman and man
    fill(0);
    rect(offsetX+widthViz-offsetXWomansRecords,heightViz+offsetY,offsetXWomansRecords,20);
    fill(255);
    String yearsWoman = "2"+"years";
    int textTotalXPos = textWidth(yearsWoman);
    text(yearsWoman,offsetX+widthViz-offsetXWomansRecords+(offsetXWomansRecords/2)-(textTotalXPos/2),heightViz+offsetY+fontSize);
    
    fill(150);
    rect(offsetX,heightViz+offsetY,widthViz-offsetXWomansRecords,20);
    fill(255);
    String yearsMan = "2"+"years";
    int textTotalXPos = textWidth(yearsMan);
    text(yearsMan,offsetX+(widthViz-offsetXWomansRecords)/2,heightViz+offsetY+fontSize);
    
    fill(0);
    var dateThisWomanFirstRecordAr = datosJson[0]["records-woman"][0][0].split("/");
    int posXWomanFirstRecord = getXPosition(dateThisWomanFirstRecordAr[2],dateThisWomanFirstRecordAr[1],dateThisWomanFirstRecordAr[0]);
    rect(offsetX,heightViz+offsetY+20,posXWomanFirstRecord,20);
    
    fill(100);
    rect(offsetX+posXWomanFirstRecord,heightViz+offsetY+20,widthViz-posXWomanFirstRecord,20);
    
    if(mouseInsideViz){
        stroke(0,0,0);
        line(mouseX,offsetY,mouseX,heightViz+offsetY-1);
        fill(0, 174, 239);
        text(getManValueInX(), mouseX+marginPX, offsetY); 
        int womanOffsetXPos = textWidth("woman");
        fill(127, 63, 152);
        text(getWomanValueInX(), mouseX-womanOffsetXPos-marginPX, offsetY); 
        noStroke();
    }
    
    
    
    
}

}