xxxxxxxxxx
476
/*
stuff to add:
- ADD GRID TO SELECTED BOX
- grid aesthetics
- SHOULD GRID IMMEDIATELY CLOCK OR ADD TO QUEUE?? (just how it is now)
- undo pop-ups / history?
bug fixes:
- make it zoom correctly on phone
- make separate version for android with double tap disabled
*/
// colors, fontsizes
const orange=[232,94,2], navy=[35,53,65], presscol=[55,73,85], gridpress=[95,108,117], butcol = [50,68,80], lgrey = 180, dgrey=140, grey3 = 229;
const numpadnumsize = 26, gridnumsize = 24, buttontextsize = 14, timernumsize = 12, timesnumsize = 24;
// declare for preload
let regular, medium, bold, recordsvg;
// orange[0],orange[1],orange[2] // navy[0],navy[1],navy[2] // presscol[0],presscol[1],presscol[2] // gridpress[0],gridpress[1],gridpress[2] // butcol[0],butcol[1],butcol[2] //
// define mode, true = chatmode, false = gridmode
let mode = true;
let times = [];
let grid = [];
const cwidth = 375, cheight = 727;
const chatmarg = 8,chatheight=45,chatY=cheight-365, chatbufferwidth=55;
const buttonmarg = 8;
const swapY = chatY + chatheight + chatmarg + buttonmarg, swapheight = 50;
const plusY = swapY + swapheight + buttonmarg, plusheight = 50;
const recordY = plusY + plusheight + buttonmarg, recordwidth = 110;
const topheight = 69, gridbutwidth = 87;
const gridbotx = 15, gridboty = cheight - 80;
const dashY = chatY-chatmarg, numpadY = dashY + chatmarg*2 + chatheight;
const butwidth = (cwidth-recordwidth-buttonmarg*3)/3, butheight = (cheight-numpadY-buttonmarg*2)/4;
const butx1 = buttonmarg,butx2=butx1+butwidth,butx3=butx2+butwidth,buty1=numpadY+buttonmarg, buty2=buty1+butheight,buty3=buty2+butheight,buty4=buty3+butheight;
const numbers = [[butx2,buty4],[butx1,buty1],[butx2,buty1],[butx3,buty1],[butx1,buty2],[butx2,buty2],[butx3,buty2],[butx1,buty3],[butx2,buty3],[butx3,buty3]];
const timeswidth = 130, timesheight = 34, timesmarg = timesheight+10, timesX = cwidth - timeswidth - buttonmarg, timesY = chatY, bufferheight = 0.75*timesheight;
let press = -1;
let selection = -1;
let typing = "";
let queue = [];
let swapping = false;
function preload() {
regular = loadFont('Roboto-Regular.ttf');
medium = loadFont('Roboto-Medium.ttf');
bold = loadFont('Roboto-Bold.ttf');
recordsvg = loadImage('img/stopwatch2.svg');
}
function setup() {
createCanvas(cwidth, cheight);
// createButton("switch mode").mousePressed(switchMode);
createButton("export time").mousePressed(exportTimes);
for(i=101;i<130;i++){
grid.push([i,true])
}
}
function draw() {
background(255);
noStroke();
// fill(220);
// rect(0,dashY,width,height-dashY);
fill(navy[0],navy[1],navy[2]);
if(mode){
rect(0,numpadY,width,height-numpadY);
}
else{
rect(width-recordwidth-buttonmarg*2,numpadY,recordwidth + buttonmarg*2,height-numpadY);
}
// draw buttons
textFont(bold);
if(mode){ textSize(numpadnumsize);
noStroke();
for(i=0;i<numbers.length;i++){
fill(presscol[0],presscol[1],presscol[2]);
if(press==i){
rect(numbers[i][0],numbers[i][1],butwidth,butheight);
}
fill(255);
text(i,numbers[i][0]+butwidth/2-8,numbers[i][1]+butheight/2+8)
}
}
else{
textSize(gridnumsize)
for(i=0;i<grid.length;i++){
if(grid[i][1]){fill(butcol[0], butcol[1], butcol[2]);}
else{fill(gridpress[0],gridpress[1],gridpress[2])}
rect(gridbotx + (i%3) * butwidth - buttonmarg/2, gridboty - Math.trunc(i/3) * butheight +buttonmarg/2,butwidth - buttonmarg, butheight - buttonmarg,15);
fill(255);
text(grid[i][0], gridbotx + (i%3) * butwidth + 14, gridboty - Math.trunc(i/3) * butheight + 44)
}
}
// draw other buttons
textFont(medium); textSize(buttontextsize);
if(mode){
fill(butcol[0],butcol[1],butcol[2]);
if(press=="<-"){fill(presscol[0],presscol[1],presscol[2]);}
rect(butx3+buttonmarg/2,buty4+buttonmarg/2,butwidth-buttonmarg,butheight-buttonmarg,15);
fill(butcol[0],butcol[1],butcol[2]);
if(press=="clear"){fill(presscol[0],presscol[1],presscol[2]);}
rect(butx1+buttonmarg/2,buty4+buttonmarg/2,butwidth-buttonmarg,butheight-buttonmarg,15);
}
fill(butcol[0],butcol[1],butcol[2]);
if(press=="swap"){fill(presscol[0],presscol[1],presscol[2]);}
rect(width-buttonmarg-recordwidth,swapY,recordwidth,swapheight,15);
fill(butcol[0],butcol[1],butcol[2]);
if(press=="+"){fill(presscol[0],presscol[1],presscol[2]);}
rect(width-buttonmarg-recordwidth,plusY,recordwidth,plusheight,15);
fill(orange[0],orange[1],orange[2]);
if(press=="record"){fill(orange[0]+20,orange[1]+20,orange[2]+20);}
rect(width-buttonmarg-recordwidth,recordY,recordwidth,height-recordY-buttonmarg,15);
fill(255);
if(mode){
text("<-",butx3+butwidth/2-5,buty4+butheight/2);
text("clear",butx1+butwidth/2-14,buty4+butheight/2+3);
}
text("swap racer", width-buttonmarg-recordwidth+20,swapY+30);
text("+ racer", width-buttonmarg-recordwidth+20,plusY+30);
image(recordsvg, width-buttonmarg-recordwidth+34,recordY+60,42,48);
// text("record", width-buttonmarg-recordwidth+35,recordY+80);
// draw chatbox
if(selection == -1){
strokeWeight(4);
stroke(orange[0],orange[1],orange[2]);
}
else{
strokeWeight(2);
stroke(180);
}
fill(255);
if(mode){
rect(chatmarg,chatY,width-2*chatmarg,chatheight,5);}
else{rect(width-buttonmarg-recordwidth, chatY, recordwidth, chatheight,5);}
noStroke()
fill(100);textFont(regular); textSize(timernumsize);
text(hour()+":"+minute()+":"+second()+"."+Math.round(millis()/100)%10,width-chatmarg-70,chatY+30);
fill(0);textFont(medium);textSize(timesnumsize);
let chatbuffer = 0;
for(i=0;i<queue.length;i++){
stroke(180);
strokeWeight(2);
line(chatmarg*2+(chatbuffer+1)*chatbufferwidth+1, chatY+10, chatmarg*2+(chatbuffer+1)*chatbufferwidth+1, chatY+chatheight-10);
noStroke();
text(queue[i],chatmarg*3 + chatbuffer*chatbufferwidth, chatY+30);
chatbuffer++
}
text(typing,chatmarg*3 + chatbuffer*chatbufferwidth,chatY+30);
// draw times
let buffer = 0;
for(i=times.length-1;i>-1;i--){
fill(0);textFont(medium);textSize(timesnumsize);
let curry = timesY - timesmarg * (times.length-i) - buffer*bufferheight;
let curheight = timesheight;
for(j=2;j<times[i].length;j++){
buffer++;
curheight += bufferheight;
curry -= bufferheight;
}
// console.log(buffer);
fill(255);
let currx = timesX;
if(selection == i){
strokeWeight(4);
stroke(orange[0],orange[1],orange[2]);
if(swapping){
currx -= 50;
}
}
else{
strokeWeight(1);
stroke(180);
}
rect(currx, curry, timeswidth, curheight,5);
noStroke();
for(j=2;j<times[i].length;j++){
fill(180);
text(times[i][j], currx + 10, curry + timesnumsize);
stroke(180);
strokeWeight(2);
line(currx+10, curry + timesnumsize - 2, currx + 52, curry + 10)
noStroke();
curry += bufferheight;
}
if(selection==i && times[i][0].length==3){
fill(180);
}
else{
fill(0);
}
text(times[i][0], currx + 10, curry + timesnumsize);
fill(100);textFont(regular); textSize(timernumsize);
text(times[i][1], currx + timeswidth - textWidth(times[i][1])-10, curry + 22);
}
// draw top bar
fill(orange[0],orange[1],orange[2]);
rect(0,0,width,topheight);
stroke(255); fill(255);
strokeWeight(4);
const arrowmarg= 20, caplength = 13;
line(arrowmarg,topheight/2,45,topheight/2); line(arrowmarg,topheight/2,arrowmarg+caplength,topheight/2 - caplength); line(arrowmarg,topheight/2,arrowmarg+caplength,topheight/2 + caplength);
strokeWeight(2);
const lineX=78, lineY=28, linelength=178;
line(lineX,lineY,lineX+linelength,lineY);
line(lineX+linelength/2,lineY,lineX+linelength/2,lineY-15);
circle(lineX,lineY,8); circle(lineX+linelength/2,lineY,8); circle(lineX+linelength,lineY,8);
triangle(lineX+linelength/2,lineY-15,lineX+linelength/2,lineY-11,lineX+linelength/2+4,lineY-13)
noStroke();
const textY = 48;
textFont(regular); textSize(12);
text("incoming",lineX-5, textY); text("passed",lineX+linelength-textWidth("passed")+5,textY);
textFont(bold); textSize(18);
text(grid.length-times.length + " / " + times.length,lineX+linelength/2-textWidth(grid.length-times.length + " /"),textY);
if(press=="grid"){fill(lgrey);} else{fill(grey3);}
rect(width-gridbutwidth,0,gridbutwidth,topheight);
fill(navy[0],navy[1],navy[2]);
let textheight=16;
textFont(regular); textSize(14);
text("Change to",width-gridbutwidth+13,5+textheight);
textFont(bold);
if(mode && press!="grid" || mode==false&&press=="grid"){text("Grid",width-gridbutwidth+30,8+textheight*2);} else{text("Chat",width-gridbutwidth+29,8+textheight*2);}
text("Mode",width-gridbutwidth+26,8+textheight*3);
}
function mousePressed(){
// enable only for chrome on android:
if (event.type == 'touchstart'){
// GRID FUNCTION
if(mode == false){
for(i=0;i<grid.length;i++){
let xx = gridbotx + (i%3) * butwidth - buttonmarg/2, yy = gridboty - Math.trunc(i/3) * butheight+buttonmarg/2
if(mouseX>xx && mouseX<xx + butwidth && mouseY>yy && mouseY<yy + butheight && grid[i][1]){
press = i;
times.push([grid[i][0],hour()+":"+minute()+":"+second()+"."+Math.round(millis()/100)%10])
grid[i][1] = false;
}
}
}
// NUMPAD FUNCTION
if(mode){
for(i=0;i<numbers.length;i++){
if(mouseX>numbers[i][0] && mouseX<numbers[i][0] + butwidth && mouseY>numbers[i][1] && mouseY<numbers[i][1] + butheight && typing.length < 3){
press = i;
if(selection==-1){
typing = typing.concat(i);
}
else if(times[selection][0].length < 3){
times[selection][0] = times[selection][0].concat(i);
if(times[selection][0].length>2){
selection = -1;
}
}
else{
times[selection].push(times[selection][0]);
times[selection][0] = "".concat(i);
}
}
}
}
// BACKSPACE
if(mouseX > butx3 && mouseX < butx3 + butwidth && mouseY > buty4 && mouseY < buty4 + butheight){
press = "<-";
if(selection==-1){
if(typing.length > 0){
typing = typing.substring(0, typing.length - 1);
}
else if(queue.length > 0){
typing = queue.pop();
}
}
else{
times[selection][0] = times[selection][0].substring(0,times[selection][0].length - 1);
}
}
// CLEAR
if(mouseX > butx1 && mouseX < butx2 && mouseY > buty4 && mouseY < buty4 + butheight){
press = "clear";
if(selection==-1){
typing = "";
queue = [];
}
else{
times[selection].push(times[selection][0]);
times[selection][0] = "";
selection = -1;
}
}
// SWITCH MODE
if(mouseX > width-gridbutwidth && mouseX < width && mouseY > 0 && mouseY < topheight){
press = "grid";
if(mode){mode = false;}
else{mode=true;}
}
if(mouseX > width-buttonmarg-recordwidth && mouseX < width-buttonmarg){
// RECORD BUTTON
if(mouseY > recordY && mouseY < height-buttonmarg){
press = "record";
if(queue.length > 0){
times.push([queue[0], hour()+":"+minute()+":"+second()+"."+Math.round(millis()/100)%10]);
queue.shift();
}
else{
times.push([typing, hour()+":"+minute()+":"+second()+"."+Math.round(millis()/100)%10]);
typing = "";
}
}
// PLUS BUTTON
if(mouseY > plusY && mouseY < plusY + plusheight){
press = "+";
if(selection == -1){
queue.push(typing);
typing = "";
}
else{
times.splice(selection+1, 0, ["",times[selection][1]]);
selection++;
}
}
// SWAP BUTTON
if(mouseY > swapY && mouseY < swapY + swapheight){
press = "swap";
if(selection>-1){
if(swapping){
swapping = false;
}
else{
swapping = true;
}
}
}
}
// SELECT TIME
if(mouseX > timesX && mouseX < timesX + timeswidth){
let buffer = 0;
for(i=times.length-1;i>-1;i--){
let curry = timesY - timesmarg * (times.length-i) - buffer*bufferheight;
for(j=2;j<times[i].length;j++){
buffer++;
}
if(mouseY>curry - (times[i].length - 2) * timesheight*0.5 && mouseY<curry + timesheight){
if(swapping){
times[selection].push(times[selection][0]);
times[i].push(times[i][0]);
let bibswap = times[selection][0];
times[selection][0] = times[i][0];
times[i][0] = bibswap;
selection = -1;
swapping = false;
}
else{
selection = i;
}
}
}
}
// DESELECT TIME
if(mouseX > chatmarg && mouseX < chatmarg+width-2*chatmarg && mouseY > chatY && mouseY < chatY+chatheight){
typing = "";
selection = -1;
}
if(mouseX < timesX && mouseY < chatY){
typing = "";
selection = -1;
}
}
}
function mouseReleased(){
press = -1;
}
function switchMode(){
if(mode){mode = false;}
else{mode=true;}
}
function exportTimes(){
timetable = new p5.Table();
timetable.addColumn('bib');
timetable.addColumn('time');
for(i=0;i<times.length;i++){
let newRow = timetable.addRow();
newRow.setString('bib', times[i][0]);
newRow.setString('time', times[i][1]);
}
saveTable(timetable, 'results.csv');
}
// document.addEventListener('gesturestart', function (e) {
// e.preventDefault();
// });