#Adapted from Jer Thorp's examples
#Press any key to see the grid visualization

from Processing import *


numbers = createNumbers(0, 100)
#printNumbers()
freqs = count(numbers, 100)

size(1000, 700)
background(0)
smooth()

int xinc = width/100
int yscale = height/70
color c = color(255, 0, 0)

background(0)
dots(xinc, height/8)
barGraph(xinc, height/4, yscale)
plot(xinc, height/8*3, yscale, true, c)
plot(xinc, height/2, yscale, false, c)
curveplot(xinc, height/8*5, yscale, false, c)
curveplot(xinc, height/4*3, yscale, true, c)

void curveplot(int xinc, int y, int yscale, boolean filled, color c) {
  colorMode(RGB)
  strokeWeight(2)
  stroke(c)
  if (filled) {
    fill(c)
  }
  else {
    noFill()
  }
  beginShape()
  curveVertex(0, y)
  curveVertex(0, y)
  for (int i=0 i < freqs.length i++) {
    curveVertex(i*xinc, y-freqs[i]*yscale)
  }
  curveVertex((freqs.length)*xinc, y)
  curveVertex((freqs.length)*xinc, y)
  endShape()
}

void plot(int xinc, int y, int yscale, boolean drawDot, color c) {
  colorMode(RGB)
  fill(c)
  stroke(c)
  for (int i=0 i < freqs.length-1 i++) {
    pushMatrix()
    translate(i*xinc, y)
    if (drawDot) {
      ellipse(0, -freqs[i]*yscale, 5, 5)
    }
    else {
      line(0, -freqs[i]*yscale, xinc, -freqs[i+1]*yscale)
    }
    popMatrix()
  }
  if (drawDot) { # last one
    pushMatrix()
    translate((freqs.length-1)*xinc, y)
    ellipse(0, -freqs[freqs.length-1]*yscale, 5, 5)
    popMatrix()
  }
}

void barGraph(int xinc, int y, int yscale) {
  for (int i = 0 i < freqs.length i++) {
    #fill(255, freqs[i] * 30, 0)
    colorMode(HSB)
    fill(freqs[i] * 30, 255, 255)
    pushMatrix()
    translate(xinc*i, y)
    rect(0, 0, xinc, -freqs[i]*yscale) 
    popMatrix()
  }
}

void colorGrid(int x, int y, int s) {
  stroke(0)
  strokeWeight(1)
  pushMatrix()
  translate(x, y)
  for (int i = 0 i < freqs.length i++) {
    int left = (i%10)*s
    int top = floor(i/10)*s
    int right = left+s
    int bottom = top+s

    colorMode(HSB)
    if (mouseX-x > left && mouseX-x < right && mouseY-y < bottom && mouseY-y > top) {
      fill(255, 0, 255)
      textAlign(CENTER)
      textSize(s/3)
      text(i+": "+freqs[i], left+s/2, top+s/2)
    }
    else {
      fill(freqs[i] * 30, 255, 255, freqs[i] * 30)
      rect(left, top, s, s)
    }
  }
  popMatrix()
}

void dots(int xinc, int y) {
  fill(255, 40)  #low alpha for blending
  noStroke()
  for (int i = 0 i < numbers.length i++) {
    pushMatrix()
    translate(numbers[i]*xinc, y)
    scale(xinc)
    ellipse(0, 0, 1, 1)
    popMatrix()
  }
}

int[] createNumbers(int min, int max) {
  int n = 225
  int[] returnArray = new int[n]

  for (int i = 0 i<n i++)
    returnArray[i]=int(random(min, max))

  return(returnArray)
}

void printNumbers() {
  for (int i=0 i<numbers.length i++) {
    print(numbers[i]+ " ")
  }
}

int[] count(int[] nums, int size) {
  int[] counts = new int[size]
  #Tally the counts
  for (int i = 0 i < nums.length i++) {
    counts[nums[i]]++
  }
  return counts
}

