/* 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();
}
}
}