import processing.pdf.*; int HOME = 0; int AWAY = 1; float FULL_POINT_SIZE = 16; float POINT_SIZE = 5; //int TOP_BOUNDARY = 40; //int BOTTOM_BOUNDARY = height - 230; int TICK_INTERVAL = 30; float TICK_RADIUS = 9; float TIMEOUT_RADIUS = 165; color HOME_COLOR = color(192,0,0,200); color AWAY_COLOR = color(13, 18, 108,200); color POSITIVE_COLOR2 = color(204,199,199); color NEGATIVE_COLOR2 = color(97,92,92); color POSITIVE_COLOR = color(255); color NEGATIVE_COLOR = color(255); float LEFT_LABELS = 135; float ASSIST_ALIGN = 110; float REBOUND_ALIGN = 110; float STEAL_ALIGN = 110; float ASSIST_LABEL_ALIGN = ASSIST_ALIGN+10; float REBOUND_LABEL_ALIGN = REBOUND_ALIGN-10; float STEAL_LABEL_ALIGN = 110; float FOUL_ALIGN = 145; float TURNOVER_ALIGN = 145; float FOUL_LABEL_ALIGN = FOUL_ALIGN+5; float TURNOVER_LABEL_ALIGN = TURNOVER_ALIGN-5; float POINT_ALIGN = 58; float TEAM_ALIGN = 25; int[][] basketPoints = new int[2][2400]; int[][] foulPoints = new int[2][2400]; int[][] runningScore = new int[2][2400]; int[][] steals = new int[2][2400]; int[][] assists = new int[2][2400]; int[][] rebounds = new int[2][2400]; int[][] fouls = new int[2][2400]; int[][] turnovers = new int[2][2400]; int[][] timeouts = new int [2][2400]; //int[][] halftime = new int [2][2400]; String[][] personScore = new String[2][2400]; int currentSecond = 0; int FULL_SPAN = 60*2; void setup() { size(900, 600); //size(1100, 400, PDF, "output.pdf"); //plotX1 = 50; //plotX2 = width - plotX1; String[] lines = loadStrings("cleaned.txt"); int timeOffset = 1199; for (int i = 0; i < 2400; i++) { personScore[HOME][i] = ""; } for (int i = 0; i < 2400; i++) { personScore[AWAY][i] = ""; } for (int i = 0; i < lines.length; i++) { if (lines[i].equals("*")) { timeOffset = 2399; } else { String timestamp = lines[i].substring(48, 53).trim(); String[] minutesSecondsString = split(timestamp, ':'); int[] minutesSeconds = int(minutesSecondsString); int ms = timeOffset - (minutesSeconds[0]*60 + minutesSeconds[1]); String score = ""; int[] currentScore = null; if (lines[i].length() > 53) { score = lines[i].substring(53, 62).trim(); if (score.length() > 0) { String[] currentScoreString = split(score, '-'); currentScore = int(currentScoreString); } } String home = lines[i].substring(0, 48).trim(); if (home.startsWith("GOOD! FT SHOT")) { foulPoints[HOME][ms]++; runningScore[HOME][ms] = currentScore[HOME]; personScore[HOME][ms] += home + "\n"; } else if (home.startsWith("GOOD! 3 PTR")) { basketPoints[HOME][ms] = 3; runningScore[HOME][ms] = currentScore[HOME]; personScore[HOME][ms] += home + "\n"; } else if (home.startsWith("GOOD! JUMPER")) { basketPoints[HOME][ms] = 2; runningScore[HOME][ms] = currentScore[HOME]; personScore[HOME][ms] += home + "\n"; } else if (home.startsWith("GOOD! LAYUP")) { basketPoints[HOME][ms] = 2; runningScore[HOME][ms] = currentScore[HOME]; personScore[HOME][ms] += home + "\n"; } else if (home.startsWith("STEAL")) { steals[HOME][ms] = 1; } else if (home.startsWith("ASSIST")) { assists[HOME][ms] = 1; } else if (home.startsWith("REBOUND")) { rebounds[HOME][ms] = 1; } else if (home.startsWith("FOUL")) { fouls[HOME][ms] = 1; } else if (home.startsWith("TURNOVR")) { turnovers[HOME][ms] = 1; } else if (home.startsWith("TIMEOUT")) { timeouts[HOME][ms] = 1; } //else if (home.startsWith("*")) { // float halftime = 1; // } if (lines[i].length() > 67) { String away = lines[i].substring(67).trim(); if (away.startsWith("GOOD! FT SHOT")) { foulPoints[AWAY][ms]++; runningScore[AWAY][ms] = currentScore[AWAY]; personScore[AWAY][ms] += away + "\n"; } else if (away.startsWith("GOOD! 3 PTR")) { basketPoints[AWAY][ms] = 3; runningScore[AWAY][ms] = currentScore[AWAY]; personScore[AWAY][ms] += away + "\n"; } else if (away.startsWith("GOOD! JUMPER")) { basketPoints[AWAY][ms] = 2; runningScore[AWAY][ms] = currentScore[AWAY]; personScore[AWAY][ms] += away + "\n"; } else if (away.startsWith("GOOD! LAYUP")) { basketPoints[AWAY][ms] = 2; runningScore[AWAY][ms] = currentScore[AWAY]; personScore[AWAY][ms] += away + "\n"; } else if (away.startsWith("STEAL")) { steals[AWAY][ms] = 1; } else if (away.startsWith("ASSIST")) { assists[AWAY][ms] = 1; } else if (away.startsWith("REBOUND")) { rebounds[AWAY][ms] = 1; } else if (away.startsWith("FOUL")) { fouls[AWAY][ms] = 1; } else if (away.startsWith("TURNOVR")) { turnovers[AWAY][ms] = 1; } else if (away.startsWith("TIMEOUT")) { timeouts[AWAY][ms] = 1; } } } } } void draw() { background(255); smooth(); PFont font; font = loadFont("FrutigerLTStd-Roman-9.vlw"); textFont(font,9); //----------------------------------------------------- drawFull(currentSecond-15, currentSecond+FULL_SPAN+20, 150, width-150, 200); drawMini(0, 2400, 50, width-50, 500); } void drawFull(float leftSecond, float rightSecond, float plotX1, float plotX2, float middle) { PFont font2; font2 = loadFont("FrutigerLTStd-Bold-9.vlw"); PFont font3; font3 = loadFont("FrutigerLTStd-Bold-11.vlw"); textFont(font3,11); rectMode(CORNERS); //draw axis line stroke(128); strokeWeight(0.5); line(plotX1, middle, plotX2, middle); //draw home dividing line 1 float y = middle; int dashOn = 4; int dashOff = 8; int dashWidth = dashOn + dashOff; for (int sec = 0; sec < 2400; sec++) { float x = map(sec, leftSecond, rightSecond, plotX1, plotX2); // draw tick marks and time stroke(0); fill(0); int remainder=sec% TICK_INTERVAL; if (remainder==0){ textAlign(LEFT); line (x, middle+TICK_RADIUS, x, middle-TICK_RADIUS); String s = formatTime(sec); textFont(font2,9); fill(NEGATIVE_COLOR2); text (s, x+2, middle+2+textAscent()); } textFont(font3,11); textAlign(CENTER); noStroke(); //plotting home timeouts if (timeouts[HOME][sec] != 0) { stroke(HOME_COLOR); int dashHeight = dashOn + dashOff; for (int h = 40; h < height-230; h += dashHeight) { line(x, h-dashOn, x, h); } } ellipseMode(CORNER); // figure out how many total points there are this second int pointsThisSecond = basketPoints[HOME][sec] + foulPoints[HOME][sec]; // figure out the score before this second occurred int score = runningScore[HOME][sec] - pointsThisSecond; // home roll-overs float vertHome = -POINT_ALIGN + middle - pointsThisSecond * FULL_POINT_SIZE / 2; // calculate the bottom of all the ellipses float vertHomeBottom = vertHome + pointsThisSecond*FULL_POINT_SIZE; // check if the mouseY is between the top and bottom of the ellipses if (mouseY > vertHome && mouseY < vertHomeBottom) { textFont(font2,9); // check whether the mouseX coordinate is inside a point if (abs(mouseX - x) < FULL_POINT_SIZE*2) { // draw the text (this is unchanged) fill(0); text(personScore[HOME][sec], x, vertHome-14); } } textFont(font3,11); //plotting home points if (basketPoints[HOME][sec] != 0) { // update the score to be shown score += basketPoints[HOME][sec]; float diameter = abs(basketPoints[HOME][sec]) * FULL_POINT_SIZE; fill(HOME_COLOR); ellipse(x-diameter/2, vertHome, diameter, diameter); fill(255); float centerY = vertHome + diameter/2; // draw 'score' to the screen instead of runningScore[][] vtext(score,x,centerY); vertHome += diameter; } //plotting home foul shots for (int f = 0; f < foulPoints[HOME][sec]; f++) { float diameter = abs(basketPoints[HOME][sec]) * FULL_POINT_SIZE; fill(HOME_COLOR); ellipse(x-FULL_POINT_SIZE/2, vertHome, FULL_POINT_SIZE+3, FULL_POINT_SIZE+3); fill(255); float centerY = vertHome + FULL_POINT_SIZE/2; // add one to the score for this foul shot score++; // and draw 'score' to the screen instead of runningScore vtext(score,x+2,centerY+1.5); vertHome += FULL_POINT_SIZE; } fill(HOME_COLOR); ellipseMode(CENTER); fill(HOME_COLOR); //plotting home steals if (steals[HOME][sec] != 0) { text("S", x, middle-STEAL_ALIGN); fill(POSITIVE_COLOR2); ellipse(x, middle-STEAL_ALIGN+5,5,5); } fill(HOME_COLOR); //plotting home rebounds if (rebounds[HOME][sec] != 0) { text("R", x, middle-REBOUND_ALIGN); fill(POSITIVE_COLOR2); ellipse(x, middle-REBOUND_ALIGN+5,5,5); } fill(HOME_COLOR); //plotting home assists if (assists[HOME][sec] != 0) { text("A", x, middle-ASSIST_ALIGN); fill(POSITIVE_COLOR2); ellipse(x, middle-ASSIST_ALIGN+5,5,5); } fill(HOME_COLOR); //plotting home fouls if (fouls[HOME][sec] != 0) { text("F", x, middle-FOUL_ALIGN); fill(NEGATIVE_COLOR2); ellipse(x, middle-FOUL_ALIGN+5,5,5); } fill(HOME_COLOR); //plotting home turnovers if (turnovers[HOME][sec] != 0) { text("T", x, middle-TURNOVER_ALIGN); fill(NEGATIVE_COLOR2); ellipse(x, middle-TURNOVER_ALIGN+5,5,5); } //plotting halftime //if (halftime[HOME][sec] != 0) { // strokeWeight(2); //stroke(255); //line(x, middle-145, x, middle+145); // } noStroke(); //plotting away timeouts if (timeouts[AWAY][sec] != 0) { stroke(AWAY_COLOR); int dashHeight = dashOn + dashOff; for (int h = 40; h < height-230; h += dashHeight) { line(x, h-dashOn, x, h); } } //plotting away points ellipseMode(CORNER); // figure out how many total points there are this second int pointsThisSecondAway = basketPoints[AWAY][sec] + foulPoints[AWAY][sec]; // figure out the score before this second occurred int scoreAway = runningScore[AWAY][sec] - pointsThisSecondAway; //roll-overs float vertAway = POINT_ALIGN + middle - pointsThisSecondAway * FULL_POINT_SIZE / 2; // calculate the bottom of all the ellipses float vertAwayBottom = vertAway + pointsThisSecondAway*FULL_POINT_SIZE; // check if the mouseY is between the top and bottom of the ellipses if (mouseY > vertAway && mouseY < vertAwayBottom) { textFont(font2,9); // check whether the mouseX coordinate is inside a point if (abs(mouseX - x) < FULL_POINT_SIZE*2) { // draw the text (this is unchanged) fill(0); text(personScore[AWAY][sec], x, vertAway-14); } } textFont(font3,11); //plotting away points if (basketPoints[AWAY][sec] != 0) { // update the score to be shown scoreAway += basketPoints[AWAY][sec]; float diameter = abs(basketPoints[AWAY][sec]) * FULL_POINT_SIZE; fill(AWAY_COLOR); ellipse(x-diameter/2, vertAway, diameter, diameter); fill(255); float centerY = vertAway + diameter/2; // draw 'score' to the screen instead of runningScore[][] vtext(scoreAway,x,centerY); vertAway += diameter; } //plotting away foul shots for (int f = 0; f < foulPoints[AWAY][sec]; f++) { float diameter = abs(basketPoints[AWAY][sec]) * FULL_POINT_SIZE; fill(AWAY_COLOR); ellipse(x-FULL_POINT_SIZE/2, vertAway, FULL_POINT_SIZE+3, FULL_POINT_SIZE+3); fill(255); float centerY = vertAway + FULL_POINT_SIZE/2; // add one to the score for this foul shot score++; // and draw 'score' to the screen instead of runningScore vtext(scoreAway,x+2,centerY+1.5); vertAway += FULL_POINT_SIZE; } ellipseMode(CENTER); fill(AWAY_COLOR); //plotting away steals if (steals[AWAY][sec] != 0) { text("S", x, middle + STEAL_ALIGN + textAscent()); fill(POSITIVE_COLOR2); ellipse(x, middle+STEAL_ALIGN+15,5,5); } fill(AWAY_COLOR); //plotting away rebounds if (rebounds[AWAY][sec] != 0) { text("R", x, middle + REBOUND_ALIGN + textAscent()); fill(POSITIVE_COLOR2); ellipse(x, middle+REBOUND_ALIGN+15,5,5); } fill(AWAY_COLOR); //plotting away assists if (assists[AWAY][sec] != 0) { text("A", x, middle + ASSIST_ALIGN+ textAscent()); fill(POSITIVE_COLOR2); ellipse(x, middle+ASSIST_ALIGN+15,5,5); } fill(AWAY_COLOR); //plotting away fouls if (fouls[AWAY][sec] != 0) { //float x = map(sec, 0, 2400, plotX1, plotX2); //float vert = height/2; text("F", x, middle + FOUL_ALIGN + textAscent()); fill(NEGATIVE_COLOR2); ellipse(x, middle+FOUL_ALIGN+15,5,5); } fill(AWAY_COLOR); //plotting away turnovers if (turnovers[AWAY][sec] != 0) { //float x = map(sec, 0, 2400, plotX1, plotX2); //float vert = height/2; text("T", x, middle + TURNOVER_ALIGN + textAscent()); fill(NEGATIVE_COLOR2); ellipse(x, middle+FOUL_ALIGN+15,5,5); } fill(AWAY_COLOR); } //exit(); //draw left erasing rectangle fill(255); noStroke(); rect(0, middle - 185, plotX1, middle + 185); //draw right erasing rectangle fill(255); noStroke(); rect(width, middle - 185, plotX2, middle + 185); //draw oultining rectangle strokeWeight(4); stroke(POSITIVE_COLOR2); noFill(); float boxX1 = plotX1-3*POINT_SIZE/2; float boxX2 = plotX2+3*POINT_SIZE/2; rect(plotX1, middle-175, plotX2, middle+175); //label statistics fill(0); textAlign(RIGHT); textFont(font2,9); text ("Assists", LEFT_LABELS, middle - ASSIST_LABEL_ALIGN); text ("Rebounds", LEFT_LABELS, middle - REBOUND_LABEL_ALIGN); text ("Steals", LEFT_LABELS, middle - STEAL_LABEL_ALIGN); text ("Fouls", LEFT_LABELS, middle - FOUL_LABEL_ALIGN); text ("Turnovers", LEFT_LABELS, middle - TURNOVER_LABEL_ALIGN); text ("Points", LEFT_LABELS, middle - POINT_ALIGN); text ("Assists", LEFT_LABELS, middle + ASSIST_LABEL_ALIGN + textAscent()); text ("Rebounds", LEFT_LABELS, middle + REBOUND_LABEL_ALIGN + textAscent()); text ("Steals", LEFT_LABELS, middle + STEAL_ALIGN + textAscent()); text ("Fouls", LEFT_LABELS, middle + FOUL_LABEL_ALIGN + textAscent()); text ("Turnovers", LEFT_LABELS, middle + TURNOVER_LABEL_ALIGN + textAscent()); text ("Points", LEFT_LABELS, middle + POINT_ALIGN + textAscent()); textFont(font3,11); fill(HOME_COLOR); text ("WITTENBERG", LEFT_LABELS, middle - TEAM_ALIGN); fill(AWAY_COLOR); text ("ALLEGHENY", LEFT_LABELS, middle + TEAM_ALIGN + textAscent()); fill(0); } //----------------------------------------------------------------------------------------------------------------- void drawMini(float leftSecond, float rightSecond, float plotX1, float plotX2, float middle) { //draw halftime; stroke (195); strokeWeight(1.5); line ((plotX2-plotX1)/2+50, middle-25, (plotX2-plotX1)/2+50, middle+25); if (mousePressed) { if (mouseY > middle-40 && mouseY < middle+40) { float c = map (mouseX, plotX1, plotX2, 0, 2400); currentSecond=int(c) - FULL_SPAN/2; if (currentSecond < 0){ currentSecond = 0; } if (currentSecond > 2400 - FULL_SPAN){ currentSecond = 2400 - FULL_SPAN; } } } PFont font; font = loadFont("FrutigerLTStd-Roman-9.vlw"); //font = createFont("SansSerif", 9); textFont(font,9); rectMode(CORNERS); //draw axis line stroke(128); strokeWeight(0.5); line(plotX1, middle, plotX2, middle); //draw hash marks and time stroke(128); strokeWeight(0.5); int interval = 60; for (int sec = 0; sec < 2400; sec++) { if (sec % interval == 0) { float x = map(sec, 0, 2400, plotX1, plotX2); line(x, middle+3, x, middle-3); } } for (int sec = 0; sec < 2400; sec++) { float x = map(sec, 0, 2400, plotX1, plotX2); noStroke(); fill(192,0,0,200); //plotting home timeouts if (timeouts[HOME][sec] != 0) { stroke(200); line(x, middle-25, x,middle+25 ); } //plotting away timeouts if (timeouts[AWAY][sec] != 0) { stroke(200); line(x, middle-25, x,middle+25 ); } //plotting home points ellipseMode(CORNER); float vertHome = -13+ middle - (basketPoints[HOME][sec] + foulPoints[HOME][sec]) * POINT_SIZE / 2; if (basketPoints[HOME][sec] != 0) { float diameter = (abs(basketPoints[HOME][sec]) * POINT_SIZE)/1.5; ellipse(x-diameter/2, vertHome, diameter, diameter); vertHome += diameter; } for (int f = 0; f < foulPoints[HOME][sec]; f++) { ellipse(x-POINT_SIZE/2, vertHome-2, POINT_SIZE, POINT_SIZE); vertHome += POINT_SIZE; } ellipseMode(CENTER); //plotting home steals fill(150); if (steals[HOME][sec] != 0) { ellipse(x, middle-28, 2,2); } //plotting home rebounds if (rebounds[HOME][sec] != 0) { ellipse(x, middle-28, 2,2); } //plotting home assists if (assists[HOME][sec] != 0) { ellipse(x, middle-28, 2,2); } //plotting home fouls fill(0); if (fouls[HOME][sec] != 0) { ellipse(x, middle-36, 2,2); } //plotting home turnovers if (turnovers[HOME][sec] != 0) { ellipse(x, middle-36, 2,2); } noStroke(); fill(13, 18, 108,200); //for (int sec = 0; sec < 2400; sec++) { // float x = map(sec, 0, 2400, plotX1, plotX2); //plotting away points ellipseMode(CORNER); //float vert = height/2; float vertAway = 13 +middle - (basketPoints[AWAY][sec] + foulPoints[AWAY][sec]) * POINT_SIZE / 2; if (basketPoints[AWAY][sec] != 0) { float diameter = (abs(basketPoints[AWAY][sec]) * POINT_SIZE)/1.5; ellipse(x-diameter/2, vertAway, diameter, diameter); vertAway += diameter; } for (int f = 0; f < foulPoints[AWAY][sec]; f++) { ellipse(x-POINT_SIZE/2, vertAway-2, POINT_SIZE, POINT_SIZE); vertAway += POINT_SIZE; } ellipseMode(CENTER); //plotting away steals fill(150); if (steals[AWAY][sec] != 0) { ellipse(x, middle+28, 2,2); } //plotting away rebounds if (rebounds[AWAY][sec] != 0) { ellipse(x, middle+28, 2,2); } //plotting away assists if (assists[AWAY][sec] != 0) { ellipse(x, middle+28, 2,2); } //plotting away fouls fill(0); if (fouls[AWAY][sec] != 0) { ellipse(x, middle+36, 2,2); } //plotting home turnovers if (turnovers[AWAY][sec] != 0) { ellipse(x, middle+36, 2,2); } } //draw rectangle slider float left = map(currentSecond, leftSecond, rightSecond, plotX1, plotX2); float right = map(currentSecond+FULL_SPAN, leftSecond, rightSecond, plotX1, plotX2); strokeWeight(3); stroke(POSITIVE_COLOR2); noFill(); rect(left, middle-50, right, middle+50); //exit(); } void vtext(String s, float x, float y){ text(s, x, y+textAscent()/2); } void vtext(int s, float x, float y){ text(s, x, y+textAscent()/2); } String formatTime(int sec) { if(sec > 1200){ sec=sec-1200; } int opposite = 1200 - sec; int m = opposite/60; int s = opposite%60; return m + ":" + nf(s,2); }