//written for Processing 0133 by Greg Niemeyer UC Berkeley

import krister.Ess.*;
AudioChannel myChannel0;
AudioChannel myChannel1;
AudioChannel myChannel2;
AudioChannel myChannel3;
AudioChannel myChannel4;

PGraphics backgr;
PGraphics foregr;

int segments = 10;
float r = 0.0;
float [][] angle = new float [segments][4];
float lastAng = 0;
int seriesLength = 0;
int linefeed = 0;
boolean pause = false;

//serial stuff
PrintWriter output;
PFont font;
PFont fat_font;

boolean new_data = true;

float alpha_setting = 225;

float [][] side = new float [4][3];
float [][] data = new float [4][3];
float [][] sorted_data = new float [4][3];
float [][][] gon = new float [4][4][2];

int myEcho = 0;
int minimum = 0;
float comp = 6000.0;
int sampleSize = 159044;

float [][][] transmit = new float [sampleSize][4][3]; //0-3 are data
float [][][] stroke_col = new float [5][3][4];
float vref = 4.9;
float lref = 9.76;
float co2ref = 9.76;
int gamestate = 0;

String [][] txt = new String [5][5];

// Declare and construct an array of objects c[0]
Course [][] c = new Course [5][3];//0-3 are inputs, 4 is a sum.

void setup(){
println (sampleSize);
//load the background

backgr = createGraphics(width, height, P3D);
backgr.beginDraw();
backgr.background(0xFFFFFFFF);
int b = 0;
while ( b<width )
{
if (b<width/2){
backgr.stroke(b*0.4);
}
else{
backgr.stroke((width-b)*0.4);
}
noFill();
backgr.line(b,0,b,height);
b++;
}
backgr.endDraw();

//load the foreground
foregr = createGraphics(width, height, P3D);

//load the sound
// start up Ess
Ess.start(this);

// load "cell.aif" into a new AudioChannel
myChannel0=new AudioChannel("cell_0.aiff");
myChannel1=new AudioChannel("cell_1.aiff");
myChannel1.pan(-1.0);
myChannel2=new AudioChannel("cell_2.aiff");
myChannel3=new AudioChannel("cell_3.aiff");
myChannel3.pan(1.0);
myChannel4=new AudioChannel("cell_4.aiff");

//load the data

String lines [] = loadStrings("../data/nestrick.txt");
seriesLength = lines.length;
println("from_setup"+seriesLength);
//float [][][] transmit = new float [(seriesLength/4)+1][4][3];
int s = 0;
for (int i = 0; i < seriesLength; i++){
float list[] = float (split(lines[i], ", "));
for (int j = 0; j < 3; j++){
if(list[j] < 5000.0 && list[j] > 0.0){//add a data error limiter
transmit[floor(i/4)][i%4][j] = list[j];
}
else {
transmit[floor(i/4)][i%4][j] = 2500.0;
println (transmit[i/4][i%4][j]);
}
//println ("at i "+floor(i/4)+"and x "+i%4+"and j "+j);
//println (transmit[i/4][i%4][j]);
}
}

size (720,480);//size (1024, 768);
frameRate (30);
float col = 1;
for (int i=0; i<segments; i++){
col = -1*col;
angle[i][0]=TWO_PI/segments*i;
angle[i][1]=(col*255);
angle[i][2]=(col*255);
angle[i][3]=col*255;
}

for (int o = 0; o < 5; o++){
for(int k = 0; k < 3; k++){
if (o != 4){
c[o][k] = new Course ( (width/2)+width/5*sin((TWO_PI/4.0*o)+PI), (height/2)+width/5*cos((TWO_PI/4.0*o)+PI), 175, 0, 0, 0, 0);
}
else {
c[o][k] = new Course (width/2, height/2, height/5*2 + (175/2), 0, 0, 0, 0); //central wheel
}

}
}
font = loadFont("HelveticaNeue-Light-48.vlw");
fat_font = loadFont("HelveticaNeue-Bold-18.vlw");
//deal with the serial

//set the colors here
//trans 0 is white (light)
stroke_col[0][0][0] = 255;
stroke_col[0][0][1] = 255;
stroke_col[0][0][2] = 255;
stroke_col[0][0][3] = alpha_setting;
//trans 1 is red (temp)
stroke_col[0][1][0] = 255;
stroke_col[0][1][1] = 128;
stroke_col[0][1][2] = 128;
stroke_col[0][1][3] = alpha_setting;
//trans 2 is green (co2)
stroke_col[0][2][0] = 164;
stroke_col[0][2][1] = 255;
stroke_col[0][2][2] = 128;
stroke_col[0][2][3] = alpha_setting;

//trans 0 is white (light)
stroke_col[1][0][0] = 192;
stroke_col[1][0][1] = 192;
stroke_col[1][0][2] = 192;
stroke_col[1][0][3] = alpha_setting;
//trans 1 is red (temp)
stroke_col[1][1][0] = 255;
stroke_col[1][1][1] = 64;
stroke_col[1][1][2] = 64;
stroke_col[1][1][3] = alpha_setting;
//trans 2 is green (co2)
stroke_col[1][2][0] = 64;
stroke_col[1][2][1] = 255;
stroke_col[1][2][2] = 64;
stroke_col[1][2][3] = alpha_setting;

//trans 0 is white (light)
stroke_col[2][0][0] = 64;
stroke_col[2][0][1] = 64;
stroke_col[2][0][2] = 64;
stroke_col[2][0][3] = alpha_setting;
//trans 1 is red (temp)
stroke_col[2][1][0] = 192;
stroke_col[2][1][1] = 16;
stroke_col[2][1][2] = 16;
stroke_col[2][1][3] = alpha_setting;
//trans 2 is green (co2)
stroke_col[2][2][0] = 0;
stroke_col[2][2][1] = 128;
stroke_col[2][2][2] = 0;
stroke_col[2][2][3] = alpha_setting;

//trans 0 is white (light)
stroke_col[3][0][0] = 0;
stroke_col[3][0][1] = 0;
stroke_col[3][0][2] = 0;
stroke_col[3][0][3] = alpha_setting;
//trans 1 is red (temp)
stroke_col[3][1][0] = 128;
stroke_col[3][1][1] = 0;
stroke_col[3][1][2] = 0;
stroke_col[3][1][3] = alpha_setting;
//trans 2 is green (co2)
stroke_col[3][2][0] = 0;
stroke_col[3][2][1] = 96;
stroke_col[3][2][2] = 0;
stroke_col[3][2][3] = alpha_setting;

//trans 0 is black (light)
stroke_col[4][0][0] = 0;
stroke_col[4][0][1] = 0;
stroke_col[4][0][2] = 0;
stroke_col[4][0][3] = 255;
//trans 1 is red (temp)
stroke_col[4][1][0] = 128;
stroke_col[4][1][1] = 0;
stroke_col[4][1][2] = 0;
stroke_col[4][1][3] = alpha_setting;
//trans 2 is green (co2)
stroke_col[4][2][0] = 24;
stroke_col[4][2][1] = 24;
stroke_col[4][2][2] = 24;
stroke_col[4][2][3] = 255;

//deal with label:
txt[0][0]="North Light ";
txt[0][1]="North Temp ";
txt[0][2]="North CO2 ";
txt[1][0]="West Light ";
txt[1][1]="West Temp ";
txt[1][2]="West CO2 ";
txt[2][0]="South Light ";
txt[2][1]="South Temp ";
txt[2][2]="South CO2 ";
txt[3][0]="East Light ";
txt[3][1]="East Temp ";
txt[3][2]="East CO2 ";
txt[4][0]="N";
txt[4][1]="W";
txt[4][2]="S";
txt[4][3]="E";
txt[4][4]="A";

//need to add more..
}

void draw(){

if (linefeed < seriesLength/4 && pause == false){
linefeed+=8; //linefeed++; this is the slowdown times 30
image(backgr, 0, 0);
showTrt();
r = ratio(linefeed, seriesLength);

c[4][2].spin_avg(linefeed, 4, 2);

for (int o = 0; o < 4; o++){
for (int k = 0; k < 3; k++){
c[o][k].spin(linefeed, o, k);
}
}
image(foregr, 0, 0);
saveFrame("parasite-#####.tga");
}
else {
println("end of show");
linefeed = 0;
pause = true;
}
}

void showTrt(){
int seconds = linefeed/30/8;
int minutes = int(seconds/60);
seconds = seconds - minutes*60;

int measuredSeconds = linefeed;
int measuredMinutes = int(measuredSeconds/60);
int measuredHours = measuredMinutes/60;
measuredSeconds = measuredSeconds - measuredMinutes*60;
measuredMinutes = measuredMinutes - measuredHours*60;
measuredHours = measuredHours+5;//add conference start time 7 am and end time 4 pm
textFont(fat_font, 18);
textAlign(RIGHT);
fill(255, 255);
if (minutes < 10 && seconds < 10){
text("Real 0"+minutes+":0"+seconds, width/5, height/5*4);
}
else if (minutes < 10 && seconds >= 10){
text("Real 0"+minutes+":"+seconds, width/5, height/5*4);
}
else if (minutes >= 10 && seconds >= 10){
text("Real "+minutes+":"+seconds, width/5, height/5*4);
}
else if (minutes >= 10 && seconds < 10){
text("Real "+minutes+":0"+seconds, width/5, height/5*4);
}

textAlign(LEFT);

if (measuredMinutes < 10 && measuredSeconds < 10){
text("Actual "+measuredHours+":0"+measuredMinutes+":0"+measuredSeconds, width/5*4, height/5*4);
}
else if (measuredMinutes < 10 && measuredSeconds >= 10){
text("Actual "+measuredHours+":0"+measuredMinutes+":"+measuredSeconds, width/5*4, height/5*4);
}
else if (measuredMinutes >= 10 && measuredSeconds >= 10){
text("Actual "+measuredHours+":"+measuredMinutes+":"+measuredSeconds, width/5*4, height/5*4);
}
else if (measuredMinutes >= 10 && measuredSeconds < 10){
text("Actual "+measuredHours+":"+measuredMinutes+":0"+measuredSeconds, width/5*4, height/5*4);
}
}
class Course {
float x_pos, y_pos, radius, speed, motion, temp_speed, temp_angle;
Course (float x, float y, float r, float s, float m, float ts, float ta) {
x_pos = x;
y_pos = y;
radius = r;
speed = s;
motion = m;
temp_speed = ts;
temp_angle = ta;
}

void spin_avg(int currentLine, int sensor, int channel){
speed = (pow(transmit[currentLine][0][2], 2) + pow(transmit[currentLine][1][2], 2)+ pow(transmit[currentLine][2][2], 2) +pow(transmit[currentLine][3][2], 2))/50000000.0/4.0;

motion += speed;

float prev_motion = motion;
motion = (motion+speed)%TWO_PI;
if (prev_motion > motion){
myChannel4.volume(r);
myChannel4.play();
}

smooth();
//BACKGRND:
ellipseMode(CENTER);
noStroke();
for (int h = 0; h<4; h++){
fill (int(transmit[currentLine][h][1]/19), 100);
ellipse(c[h][0].x_pos, c[h][0].y_pos, width/5*4, width/5*4);
}

fill (stroke_col[4][0][0], stroke_col[4][0][1], stroke_col[4][0][2],stroke_col[4][0][3]);
noStroke();
ellipse(x_pos, y_pos, radius, radius);

for (int i=0; i<segments; i+=2){
fill (stroke_col[sensor][channel][0], stroke_col[sensor][channel][1],stroke_col[sensor][channel][2],stroke_col[sensor][channel][3]);
noStroke();
if (i!=segments-1){
arc(x_pos, y_pos, radius, radius, angle[i][0]+motion, angle[i+1][0]+motion);
}
else {
arc(x_pos, y_pos, radius, radius, angle[segments-1][0]+motion, angle[0][0]+motion);
}
}
stroke (0);
strokeWeight (radius*0.15);
point(x_pos, y_pos);

textFont(fat_font, 18);
textAlign(CENTER);
fill(200, 200, 200, 200);
text(txt[4][4], x_pos, y_pos+8);
}

void spin(int currLine, int sensor, int channel){
smooth();
switch(channel){
case 0://draw the light and the text
stroke (25);
strokeWeight (radius*1);
point(x_pos, y_pos);

stroke (25);
//if (sensor == 0){println("at line"+linefeed+" for sensor "+sensor+" temp is "+transmit[currLine][sensor][channel]/19.7); }
strokeWeight (radius*0.75);
point(x_pos, y_pos);
break;
case 1://draw the temperature
float temp_radius = transmit[currLine][sensor][channel]/35.0;
fill (stroke_col[sensor][channel][0], stroke_col[sensor][channel][1],stroke_col[sensor][channel][2],stroke_col[sensor][channel][3]);
noStroke();
ellipse(x_pos, y_pos, temp_radius, temp_radius);
break;
case 2://draw the gas and the progress bars

//the progress bar
float progress = ratio(linefeed, seriesLength)*width;

strokeWeight(1);
for (int s = 0; s < 5; s++){
stroke(255/(s+1));
line(progress+s, 0, progress+s, height);
line(width-progress-s, 0, width-progress-s, height);
}

//end the progress bar
speed = transmit[currLine][sensor][channel]*transmit[currLine][sensor][channel]/50000000.0;
float prev_motion = motion;
motion = (motion+speed)%TWO_PI;
if (prev_motion > motion){
float placeFactor = 0;
float sizeFactor = 0;
switch(sensor){
// start the sound playing once and draw a dot
case 0:
myChannel0.play();
foregr.beginDraw();
foregr.noStroke();
foregr.fill(stroke_col[sensor][channel][0],stroke_col[sensor][channel][1],stroke_col[sensor][channel][2], 128);
placeFactor = height*r*r;
sizeFactor = transmit[currLine][sensor][channel]/50;
foregr.ellipse(random(width), placeFactor, sizeFactor, sizeFactor );
foregr.endDraw();
break;
case 1:
myChannel1.play();
foregr.beginDraw();
foregr.noStroke();
foregr.fill(stroke_col[sensor][channel][0],stroke_col[sensor][channel][1],stroke_col[sensor][channel][2], 128);
placeFactor = width*r*r;
sizeFactor = transmit[currLine][sensor][channel]/50;
foregr.ellipse(placeFactor, random(height), sizeFactor, sizeFactor );
foregr.endDraw();
break;
case 2:
myChannel2.play();
foregr.beginDraw();
foregr.noStroke();
foregr.fill(stroke_col[sensor][channel][0],stroke_col[sensor][channel][1],stroke_col[sensor][channel][2], 128);
placeFactor = height-(height*r*r);//was *0.5
sizeFactor = transmit[currLine][sensor][channel]/50;
foregr.ellipse(random(width), placeFactor, sizeFactor, sizeFactor );
foregr.endDraw();
break;
case 3:
myChannel3.play();
foregr.beginDraw();
foregr.noStroke();
foregr.fill(stroke_col[sensor][channel][0],stroke_col[sensor][channel][1],stroke_col[sensor][channel][2], 128);
placeFactor = width-(width*r*r);
sizeFactor = transmit[currLine][sensor][channel]/50;
foregr.ellipse(placeFactor, random(height), sizeFactor, sizeFactor);
foregr.endDraw();
break;
}
}

 

for (int i=0; i<segments; i+=2){//to draw every other segment only!
fill (stroke_col[sensor][channel][0], stroke_col[sensor][channel][1],stroke_col[sensor][channel][2],stroke_col[sensor][channel][3]);
noStroke();
smooth();
float my_rotation = angle[i][0]+motion;
float my_next_rotation = angle[i+1][0]+motion;

if (i!=segments-1){
arc(x_pos, y_pos, radius, radius, my_rotation, my_next_rotation);
}
else {
arc(x_pos, y_pos, radius, radius, ((angle[segments-1][0]+motion)%TWO_PI), my_rotation);
}
}

stroke (stroke_col[sensor][2][0], stroke_col[sensor][2][1],stroke_col[sensor][2][2],255);
strokeWeight (radius*0.15);
point(x_pos, y_pos);

textFont(fat_font, 18);
textAlign(CENTER);
fill(0, 0, 0, 200);
text(txt[4][sensor], x_pos, y_pos+8);
break;
}
}
}
void keyPressed(){
if (keyCode == DOWN)
pause =! pause; //toggle?
}
float ratio (int feed, int series){
float a = float(feed);
float b = float(series/4);
float my_ratio = pow(a/b, 2);
return my_ratio;
}