/*------------------------------------------------------------
 Copyright (c) 2013, Friends of Ed (An Apress Company)
 All rights reserved. 
The code provided here accompanies the book:
Processing: Creative Coding and Generative Art in Processing 2
   By Ira Greenberg, Dianna Xu, and Deepak Kumar
   Friends of Ed (An APress Company), 2013
   ISBN-13 978-1430244646
   Please refer to the associated README for a full disclaimer.
   ------------------------------------------------------------*/
// Sketch 7-11: Word Cloud Visualization
   // Sketch 7-11: The Word frequency table class
class WordFreq {
   // A Frequency table class for Words
   ArrayList<WordTile> wordFrequency;
   String [] stopWords = loadStrings("stopwords.txt");
   
   WordFreq(String[] tokens) { // Constructor
 wordFrequency = new ArrayList();
 // Compute the wordFrequency table using tokens
   for (String t : tokens) {
   if (!_isStopWord(t, stopWords)) {
   // See if token t is already a known word
   int index = _search(t, wordFrequency);
   if (index >= 0) {
   ( wordFrequency.get(index)).incr();
   }
   else {
   wordFrequency.add(new WordTile(t));
   }
   }
   } // for
   // Sort the table in reverse order of frequencies
   _sort(wordFrequency);
   //Collections.sort(wordFrequency, Collections.reverseOrder());
   } // WordFreq()
 void tabulate(int n) { // console printout
   //int n = wordFrequency.size();
   println("There are "+N()+" entries.");
   for (int i=0; i < n; i++) {
   println(wordFrequency.get(i));
   }
   } // tabulate
 void arrange(int N) { // arrange or map the first N tiles in sketch
   WordTile tile;
   for (int i=0; i < N; i++) {
   tile = wordFrequency.get(i);
   tile.setFontSize();
 // Exploring the spiral layout
   float cx = width/2-50, cy = height/2, px, py;
   float R = 0.0, dR = 0.2, theta = 0.0, dTheta = 0.5;
   do { // find the next x, y for tile, i in spiral
   float x = cx + R*cos(theta);
   float y = cy + R*sin(theta); 
   tile.setXY(x, y);
   px = x;
   py = y;
   theta+=dTheta;
   R += dR;
   } // until the tile is clear of all other tiles
   while (!clear (i));
   }
   } // arrange()
 boolean clear(int n) { // Is tile, i clear of tiles 0..i-1?
   WordTile tile1 = wordFrequency.get(n);
   for (int i=0; i < n; i++) {
   WordTile tile2 = wordFrequency.get(i);
   if (tile1.intersect(tile2)) {
   return false;
   }
   } // for
   return true;
   } // clear()
 void display(int N) {
   for (int i=0; i < N; i++) {
   WordTile tile = wordFrequency.get(i);
   tile.display();
   }
   } // display()
 void interact(float mx, float my) {
   // Find out which tile was clicked
   WordTile tile = _searchTile(wordFrequency, mx, my);
 
   // Do something on it
   if (tile != null) {
   println("Tile Clicked: "+tile);
   tile.setColor(color(255, 0, 0));
   tile.display();
   }
   } // interact()
 int N() { // Number of table entries
   return wordFrequency.size();
   } // N()
 String[] samples() { // Returns all the words
   String [] k = new String[N()];
   int i=0;
   for (Word w : wordFrequency) {
   k[i++] = w.getWord();
   }
   return k;
   } // keys()
 int[] counts() { // Returns all the frequencies
   int [] v = new int[N()];
   int i=0;
   for (Word w : wordFrequency) {
   v[i++] = w.getFreq();
   }
   return v;
   } // values()
 int maxFreq() { // The max frequency
   return max(counts());
   } // maxFreq()
 int _search(String w, ArrayList<WordTile> L) {
   // Search for word, w in L
   for (int i=0; i < L.size(); i++) {
   if (L.get(i).getWord().equals(w))
   return i;
   }
   return -1;
   } // search()
 WordTile _searchTile(ArrayList<WordTile> L, float mx, float my) {
 for (int i=0; i < L.size(); i++) {
   WordTile tile = L.get(i);
   if (ptInTile(tile, mx, my)) {
   return(tile);
   }
   }
   return null;
   } // _searchTile()
 boolean ptInTile(WordTile t, float x, float y) {
   float x1 = t.location.x;
   float y1 = t.location.y - t.tileH;
   float x2 = x1+t.tileW;
   float y2 = t.location.y;
 return ((x >= x1 && x <= x2) && (y >= y1 && y <= y2));
   } // ptInTile()
   
   boolean _isStopWord(String word, String[] stopWords) {
   for (String stopWord : stopWords) {
   if (word.equals(stopWord)) {
   return true;
   }
   }
   return false;
   } // isStopWord()
 void _sort(ArrayList<WordTile> A) { // sort the array A in ascending order
   // for i=1 through N-1:
   for (int i=0; i < A.size(); i++) {
   // insert A[i] in A[0] .. A[i] such that A[0] <= A[1] <= … <= A[i]
   WordTile a = A.get(i); // Save A[i] in p
   int pos = i;
   //while ( (pos > 0) && (A.get(pos-1).getFreq() < a.getFreq())) {
   while ( (pos > 0) && (a.compareTo(A.get(pos-1))>0)) {
   // Move A[pos-1] back by 1
   A.set(pos, A.get(pos-1));
   pos--;
   } // while
   // A[pos] is where a gets inserted
   A.set(pos, a);
   }// for
   } // _sort
 String toString() { // Print representation
   return "Word Frequency Table with"+N()+" entries.";
   } // toString()
   } // class WordFreq