# Making Calculators Early Thoughts

I spent about one class considering what to make for my final project. I wasn’t sure what I wanted to create, but I knew I wanted a challenge. I wasn’t looking to make something boring and simply get credit for doing so. I wanted to push myself, even if I couldn’t fully complete my project. That being said, making a game ran through my mind numerous times, but I felt too comfortable with this idea to pursue it. Consequently, I considered making something that sounds much simpler than it really is; a calculator.

First Prototype

My first attempt was wildly unsuccessful. My code was completely unorganized, and overall not very useful. I attempted to make a graphing calculator, but I couldn’t even get far enough in my program to graph my function. When I would try to incorporate a variable, my program would crash, and leave me with an error that I couldn’t completely understand. That being said, this calculator can successfully add, subtract, divide, and multiply integers. Regardless, even after spending only a couple hours on this prototype, I knew this could never be my final draft. There were just too many complications, and not enough simplicity.

```import java.util.Arrays;
import java.util.List;
String textBox = "";
Character[] characters = new Character[]{'x', '+', '/', '*', '(', ')', '-', '^'};
List characterList = Arrays.asList(characters);
Character[] numbers = new Character[]{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
List numberList = Arrays.asList(numbers);

void setup() {
size(800, 800);
background(255);
fill(100);
noStroke();
rect(200, 200, 400, 400);
}

void draw() {
}

int evaluateFunction(String value) {
/*
This function goes through each operator in the order of PEMDAS to
evaluate textBox and resolve it into a single number which can be turned back into an integer.
*/

int finalValue = 0;
for (int len = 0; len &lt; value.length(); len++) {
char part = value.charAt(len);
if (characterList.contains(part)) {
if (part == '(') {
finalValue = parenthesis(value, len+1);
}
}
}
for (int len = 0; len &lt; value.length(); len++) {
char part = value.charAt(len);
if (characterList.contains(part)) {
if (part == '^') {
finalValue = exponent(value, len+1);
}
}
}
for (int len = 0; len &lt; value.length(); len++) {
char part = value.charAt(len);
if (characterList.contains(part)) {
if (part == '*') {
finalValue = multiply(value, len+1);
}
}
}
for (int len = 0; len &lt; value.length(); len++) {
char part = value.charAt(len);
if (characterList.contains(part)) {
if (part == '/') {
finalValue = divide(value, len+1);
}
}
}
for (int len = 0; len &lt; value.length(); len++) {
char part = value.charAt(len);
if (characterList.contains(part)) {
if (part == '+') {
finalValue = summation(value, len+1);
}
}
}
for (int len = 0; len  0) {
part = s.charAt(i);
i--;
}
int backEnd = depth-i;
i = depth;
while (!characterList.contains(part) &amp;&amp; i <s> 0) {
part = s.charAt(i);
i--;
}
int backEnd = depth-i;
i = depth;
while (!characterList.contains(part) &amp;&amp; i <s> 0) {
part = s.charAt(i);
i--;
}
int backEnd = depth-i;
i = depth;
while (!characterList.contains(part) &amp;&amp; i <s> 0) {
part = s.charAt(i);
i--;
}
int backEnd = depth-i;
i = depth;
while (!characterList.contains(part) &amp;&amp; i &lt; s.length()) {
part = s.charAt(i);
i++;
}
int frontEnd = i;
String first =  s.substring(depth-backEnd, depth-1);
String second = s.substring(depth, frontEnd);
int value = int(first)-int(second);
return value;
}

int exponent(String s, int depth) {
// never got around to implementing the exponent operator.
return 0;
}

int parenthesis(String s, int depth) {
/*
finds the parenthesis in the string, and attempts to evaluate all the information within the parenthesis
before doing anything else in the string.
*/
char character = s.charAt(depth);
String value = "";
while (character != ')'){
value += character;
depth++;
}
println(value);
//element of recursion that wasn't very functional.
int evaluated = evaluateFunction(value);
return evaluated;

}

void graphFunction() {
ArrayList powerList = new ArrayList();
for (int len = 0; len &lt; textBox.length()-1; len++) {
char letter = textBox.charAt(len);
char nextLetter = textBox.charAt(len+1);
if (numberList.contains(letter)) {
if (nextLetter == 'x') {
//if an 'x' is next to numbers without any operator, it will place an asterics in between the two.
textBox = textBox.substring(0, len+1) + '*' + textBox.substring(len+1, textBox.length());
}
}
redrawText(' ');
}

/*
for (int len = 0; len &lt; textBox.length(); len++) {
char carrot = textBox.charAt(len);
if (carrot == '^') {
// needs advanced work
powerList.add(textBox.substring(len-1, len+2));
}
}
for (int listLength = 0; listLength &lt; powerList.size(); listLength++) {
String power = powerList.get(listLength);
// needs advanced work
char back = power.charAt(0);
char front = power.charAt(power.length()-1);
//textBox = textBox.replace(power, "Math.pow(" + back + ',' + front + ')');
//redrawText(' ');
}
*/

//I never got around to working in depth with the exponents.
//The commented out code is the exponent input and response.
for (float x = -1; x  0) {
//checks to make sure the textBox contains at least one key, then removes the most recent key
String newTextBox = textBox.substring(0, textBox.length()-1);
textBox = newTextBox;
redrawText(' ');
}
} else if (key == ENTER) {
graphFunction();
}
}

</s></s></s>```

Second Prototype

I learned a lot from my first attempt at making a graphing calculator. With my second trial, I understood that I needed to make changes to my format, and how I went about coding the program in general. It turned out okay. Just like my first prototype, this program could add, subtract, multiply, and divide integers. It was also worth noting that it presented the information in a more user-friendly fashion. I added a “knob” that you could turn on and off. This was used if you wanted to use the program as a simple calculator, or for graphing. When the knob was off, it wouldn’t graph anything, and if you typed in a simple expression, the answer would appear at the bottom for you. If the knob was on, however, you could use variables to experiment with the graphing feature. This is where more problems ensued. The functions that could be graphed were very limited. This was a result of the multitude of errors that occurred if the program had difficulty evaluating the function, which I will further discuss in this blog post. Nevertheless, the second prototype was certainly better than the first, but nowhere near where I wanted it to be.

```import java.util.Arrays;
import java.util.List;
import java.lang.Math;
boolean graph = true;
String textBox = "";
Character[] characters = new Character[]{'x', '+', '/', '*', '(', ')', '-', '^'};
List characterList = Arrays.asList(characters);
Character[] numbers = new Character[]{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
List numberList = Arrays.asList(numbers);
void setup() {
size(800, 800);
createGraph();
}

void createGraph() {
// creates the basic graph background, nothing too complicated
background(255);
fill(100);
noStroke();
rect(200, 200, 400, 400);
stroke(0);
line(400, 200, 400, 599);
line(200, 400, 599, 400);
// the location of the knob changes based on if the boolean graph is true or false.
if (graph) {
rect(700, 150, 50, 50);
fill(0, 255, 0);
rect(700, 100, 50, 50);
} else {
rect(700, 100, 50, 50);
fill(255, 0, 0);
rect(700, 150, 50, 50);
}
}

void draw() {
}

int checkParethesis(String s) {
//finds parenthesis inside the textBox, and evaluates everything inside the string
int finalValue = int(s);
for (int len = 0; len &lt; s.length(); len++) {
char letter = s.charAt(len);
if (letter == '(') {
finalValue = parenthesis(s, len+1);
return finalValue;
}
}
return 2147483647;
}

int evaluateFunction(String s) {
/*
This function goes through addition, subtraction, multiplication, and division of the textBox.
It is very complicated, but basically it consists of alot of string manipulation.
As I said in my blogpost, Strings are very difficult for me (and in general).
This was my attempt to push myself and learn more about how to use strings.
*/

int stringValue = int(s);
int finalValue =  checkParethesis(s);
if (finalValue == 2147483647) {
error();
} else {
return finalValue;
}

for (int len = 0; len <s>= 0 &amp;&amp; numberList.contains(number); countBack--) {
number = s.charAt(countBack);
}
for (countFor = len+1; countFor &lt; s.length() &amp;&amp; numberList.contains(number); countFor++) {
number = s.charAt(countFor);
}
char lastChar = s.charAt(countFor-1);
if (characterList.contains(lastChar)) {
//countFor--;
}
println(countFor);
int backNumber = int(s.substring(countBack+1, len));
int forNumber = int(s.substring(len+1, countFor));
finalValue = backNumber + forNumber;
return finalValue;
}
}

for (int len = 0; len <s> 0) {
if (characterList.contains(s.charAt(len-1))) {
// evaluate string in front of negative affected by the negative
char character = '0';
int countForward = 0;
for (countForward = len+1; !characterList.contains(character) &amp;&amp; countForward <s>= 0 &amp;&amp; !characterList.contains(character); countBackward--) {
character = s.charAt(countBackward);
}
s = s.substring(0, countBackward+1) + String.valueOf(-1*evaluateFunction(s.substring(countBackward+1, len) + s.substring(len+1, countForward))) + s.substring(countForward, s.length());
println(s);
char number = '0';
int increment;
for (increment = 1; increment <s>= 0 &amp;&amp; numberList.contains(number); countBack--) {
number = s.charAt(countBack);
}
for (countFor = len+1; countFor &lt; s.length() &amp;&amp; numberList.contains(number); countFor++) {
number = s.charAt(countFor);
}
char lastChar = s.charAt(countFor-1);
if (characterList.contains(lastChar)) {
countFor--;
}
int backNumber = int(s.substring(countBack+1, len));
int forNumber = int(s.substring(len+1, countFor));
finalValue = backNumber - forNumber;
return finalValue;
}
}

for (int len = 0; len <s>= 0 &amp;&amp; numberList.contains(number); countBack--) {
number = s.charAt(countBack);
}
for (countFor = len+1; countFor &lt; s.length() &amp;&amp; numberList.contains(number); countFor++) {
number = s.charAt(countFor);
}
char lastChar = s.charAt(countFor-1);
if (characterList.contains(lastChar)) {
countFor--;
}
int backNumber = int(s.substring(countBack+1, len));
int forNumber = int(s.substring(len+1, countFor));
finalValue = backNumber * forNumber;
return finalValue;
}
}

for (int len = 0; len <s>= 0 &amp;&amp; numberList.contains(number); countBack--) {
number = s.charAt(countBack);
}
for (countFor = len+1; countFor &lt; s.length() &amp;&amp; numberList.contains(number); countFor++) {
number = s.charAt(countFor);
}
char lastChar = s.charAt(countFor-1);
if (characterList.contains(lastChar)) {
countFor--;
}
int backNumber = int(s.substring(countBack+1, len));
int forNumber = int(s.substring(len+1, countFor));
if (forNumber != 0) {
finalValue = backNumber / forNumber;
} else return 0;

return finalValue;
}
}

return stringValue;
}

int checkCharacter(int first, int second, char n) {
if (n == '*') {
return first*second;
}
if (n == '/') {
return first/second;
}
if (n == '+') {
return first+second;
}
if (n == '-') {
return first-second;
}
if (n == '^') {
return int(pow(first, second));
}
return 0;
}

int parenthesis(String s, int depth) {
int finalValue = 0;
int parenthesisCount = 1;
char letter;
// for loop checks to see what is enclosed in the initial parenthesis
for (int increment = depth; increment &lt; s.length() &amp;&amp; parenthesisCount != 0; increment++) {
letter = s.charAt(increment);
//the parenthesisCount accounts for if there are other parenthesis inside the parenthesis
if (letter == ')') {
parenthesisCount--;
} else if (letter == '(') {
parenthesisCount++;
}
if (parenthesisCount == 0) {
String inside = s.substring(depth, increment);
char numb = '0';
int counter;
//for loop finds the full number that is performing a function(add, subtract, etc.) with the value inside the parenthesis
for (counter = increment+1; counter &lt; s.length()-1 &amp;&amp; numberList.contains(numb); counter++) {
numb = s.charAt(counter+1);
}
//if loop in case the function ends with a parenthesis
if (increment+1 &lt; s.length()) {
String outside = s.substring(increment+2, counter+1);
int number = evaluateFunction(inside);
int secondNumber = evaluateFunction(outside);
char character = s.charAt(increment+1);
finalValue = checkCharacter(number, secondNumber, character);
return finalValue;
}
return evaluateFunction(inside);
}
}
return 2147483647;
}

void error() {
/* never got around to checking if the string wasnt executable,
but I had an idea in mind.
*/
}

void graphFunction() {
ArrayList powerList = new ArrayList();
for (int len = 0; len &lt; textBox.length()-1; len++) {
char letter = textBox.charAt(len);
char nextLetter = textBox.charAt(len+1);
if (numberList.contains(letter)) {
if (nextLetter == 'x') {
textBox = textBox.substring(0, len+1) + '*' + textBox.substring(len+1, textBox.length());
}
}
redrawText(' ');
}

/*
for (int len = 0; len &lt; textBox.length(); len++) {
char carrot = textBox.charAt(len);
if (carrot == '^') {
// needs advanced work
powerList.add(textBox.substring(len-1, len+2));
}
}
for (int listLength = 0; listLength &lt; powerList.size(); listLength++) {
String power = powerList.get(listLength);
// needs advanced work
char back = power.charAt(0);
char front = power.charAt(power.length()-1);
}
*/

/*
as stated in my previous prototype, I never got around to implementing
an exponential operator, although I had an idea of what I could try.
*/

if (!textBox.contains("x")) {
int functionValue = evaluateFunction(textBox);
text(functionValue, 400, 700);
}
for (int x = -100; x  200 &amp;&amp; yVal  0) {
String newTextBox = textBox.substring(0, textBox.length()-1);
textBox = newTextBox;
redrawText(' ');
}
} else if (key == ENTER) {
graphFunction();
}
}

</s></s></s></s></s></s>```

Strings

I wouldn’t call them the bane of my existence, but Strings were a big issue throughout my final project. That was the point. When I was trying to think of a project to create, I was aware of my comfort zone. Throughout various games I created, along with a multitude of Project Euler problems, I felt very confident with Integers, Objects, and ArrayLists (relative to Strings). Aside from the text() function in Processing, I had never really gone in depth with Strings in any of my programs. This is why I was looking to explore the idea of using Strings in an advanced form. Unsurprisingly, this is where I ran into nearly all of my issues of my graphing calculators. Utilizing Strings was very difficult (and a little frustrating) to me. In my opinion, it is completely non-intuitive, and I think that was part of the problem. In the end, I had learned a lot about Strings, even if I wasn’t able to fully take advantage of them in my first two prototypes.

Third Prototype

My third attempt was quite a bit different from my first two. The issue I kept running into was that Java could not evaluate an expression in the String form. Consequently, when the user inputted an expression that was in the form of a String, I had to painstakingly pick apart the String and accurately resolve each instance of the expression (with variables) into a single number. This became more and more difficult as the expressions become more complex. That being said, there was a solution to this issue using another programming platform. JavaScript has this incredibly useful tool called eval(), which will evaluate an arithmetic expression from a String. This one function could replace my 300 lines of code to evaluate the expression into just a few. Unfortunately, I never got that far in the program. I ran into this odd issue with JavaScript, or at least the software represented using Processing. The key values for various non-integer keys weren’t represented as themselves in the program. Keys such as ‘=’ , ‘-’ , ‘(‘, ‘^’ and many others were all represented as random symbols in the program. This made it much more difficult to progress in the project, made moreso by the fact that I was not well adept in JavaScript. I never made it past this step. Given some time and thought, I may have been able to progress past this obstacle, but that didn’t mean there wouldn’t have been more ahead. Like I said previously, I had never really used JavaScript, and may not have understood how to solve each issue that would’ve come afterwards. Ultimately, I gave JavaScript a quick attempt, but soon realized I should stick with a platform I was more comfortable with.

```/* This program is merely the JavaScript version of my first and second prototype. There isn't really any new information
in this program (aside from Syntax) so I didn't bother to comment throughout it.
*/

var graph = true;
var textBox = "";
var characters = new Array('x', '+', '/', '*', '(', ')', '-', '^');
var numbers = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
function setup() {
createCanvas(800, 800);
createGraph();
}

function draw() {
}

function createGraph() {
background(225);
fill(100);
noStroke();
rect(200, 200, 400, 400);
stroke(0);
line(400, 200, 400, 599);
line(200, 400, 599, 400);
if (graph) {
rect(700, 150, 50, 50);
fill(0, 255, 0);
rect(700, 100, 50, 50);
} else {
rect(700, 100, 50, 50);
fill(255, 0, 0);
rect(700, 150, 50, 50);
}
}

function graphFunction() {
var powerList;
if (!textBox.contains("x")) {
var functionValue = evaluateFunction(textBox);
text(functionValue, 400, 700);
} else {
for (var x = -100; x &lt; 100; x++) {
var value = textBox.replace("x", String.valueOf(x));
var functionValue = eval(value) + "
";
}
}
}

function redrawText(n) {
createGraph();
if (n != ' ') {
textBox = textBox + "" + n;
}
stroke(0);
fill(0);
textSize(24);
text(textBox, 200, 100);
}

function acceptedCharacter(n) {
for (var len = 0; len &lt; characters.length; len++) {
if (n == characters[len]) {
return true;
}
}
for (var len = 0; len  0) {
var newTextBox = textBox.substring(0, (textBox.length)-1);
textBox = newTextBox;
redrawText(' ');
}
} else if (keyCode == ENTER) {
graphFunction();
}
}

```

Simple Calculator

After my first three attempts at making a graphing calculator, I decided to take a step back. I dove right into making a graphing calculator, but I wanted to make sure I could create a basic calculator in the first place. Thankfully, I was successful. It was the quickest project, and only took approximately 75 lines of code. Instead of adding a key to a String every time the user typed an acceptable character, the user’s number input was concatenated to the back of a preexisting Integer. This made it much tremendously easier to evaluate the given expression. Ultimately, the simplicity of this project led me to create my final prototype.

```import java.util.Arrays;
import java.util.List;
Character[] characters = new Character[]{'+', '/', '*', '-'};
List characterList = Arrays.asList(characters);
Character[] numbers = new Character[]{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
List numberList = Arrays.asList(numbers);
int number_1 = 0;
int number_2 = 0;
char sign;
boolean signPressed = false;
boolean pastEquation = false;

void setup() {
size(200, 200);
background(255);
fill(0);
stroke(0);
}

void draw() {
}

void keyPressed() {
if (characterList.contains(key)) {
//checks to make sure the key pressed is an operator.
//then checks to make sure an operator hasn't already been assigned.
if (!signPressed) {
sign = key;
signPressed = true;
}
}
if (numberList.contains(key)) {
//checks to make sure the key pressed is a number.
//concates the number with the new input (in case the numbers used are more than one digit (ie. 12, 143 etc.) )
String value = String.valueOf(key);
if (!signPressed){
if (pastEquation){
number_1 = 0;
}
}
concate(int(value));
}
if (key == 'c') {
// 'c' is the reset button for this program
number_1 = 0;
number_2 = 0;
signPressed = false;
pastEquation = false;
}
if (key == ENTER) {

/*
evaluates the expression given by the user.
The numbers and operation given by the user was saved
and was used only now
*/
String first = String.valueOf(number_1);
String second = String.valueOf(number_2);
number_1 = (evaluate(number_1, number_2, sign));
number_2 = 0;
signPressed = false;
pastEquation = true;
//Prints out the full equation.
println(first + " " + sign + " " + second + " " + "=" + " " + String.valueOf(number_1));
}
}

void concate(int n) {
//this is the function that actually concates the numbers with a new number.
if (!signPressed) {
number_1 = number_1*10 + n;
} else {
number_2 = number_2 *10 + n ;
}
}

int evaluate(int n, int m, char s) {
//this is the program that evaluates the expression given by the user (int n is the 1st number, int m is the 2nd, and
//char s is the operator given)
if (s == '+') {
return n + m;
} else if (s == '-') {
return n-m;
} else if (s == '*') {
return n*m;
} else if (s == '/') {
return n/m;
}
return 0;
}

```

Final Prototype

After some thought, and helpful advice, I decided to throw out the use of Strings in my expression. As a matter of fact, in order to focus more on the function subject of my project, I changed how the equation is inputted. Any given expression is now placed in the code itself, rather than inputting it while the program as running. Does this make the program less flashy? Of course. However, given all the time I spent trying to make the perfect graphing calculator, I think it was justified. With this headache out of the way, I was able to spend some more time on the evaluation of an equation. Thanks to this, I was able to make an implicit graphing calculator. Basically, this code takes an input for an equation, with the use of various ‘x’ and ‘y’ variables, which are not dedicated to a specific side of the equation. (i.e. x3  + y2 – y3x   > 1) In order to present a function such as this in graphing form, I had to utilize each and every pixel used in my program. By taking the ‘x’ and ‘y’ value of each individual pixel, and putting those values in the equation, it became easy to visualize the function in the program. For additional elements, I incorporated window size measure, that could be changed while the program is running. While it did end up utilizing Strings, the use of them wasn’t overwhelming, and turned out successful in the end. After that, I felt like there was something more to do. As a result, I added a third dimension; time. By having three variable in the equation, these new functions could be represented in three dimensions. With the help of Mr. Anderson, I was able to 3D print a model of a function I created in the program. Using a 400 pixel by 400 pixel window, I took approximately 500 screenshots of the function as the time progressed. From there, a separate program is able to compile the photos and create a 3D representation of the collected photos, which can be printed out. Surprisingly enough, the final prototype only required two times the lines of code as the simple calculator to complete.

```import java.lang.Math;
import java.util.Arrays;
import java.util.List;

float t = -10;
int lowerX = -10;
int upperX = 10;
int lowerY = -10;
int upperY = 10;
String xLower = String.valueOf(lowerX);
String xUpper = String.valueOf(upperX);
String yLower = String.valueOf(lowerY);
String yUpper = String.valueOf(upperY);
boolean typeUpperx = false;
boolean typeLowerx = false;
boolean typeUppery = false;
boolean typeLowery = false;
Character[] numbers = new Character[]{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
List numberList = Arrays.asList(numbers);

void setup() {
size(800, 800);
background(0);
evaluateFunction();
}

void draw() {
//text that displays the t value, and the bounds for the x and y values
text("t = " + t, 50, 50);
text(xLower + " " + "&lt;= " + "x " + "&lt;= " + xUpper, 650, 50);
text(yLower + " " + "&lt;= " + "y" + "&lt;= " + yUpper, 650, 100);
/*
this code that is commented was used to take 500 pictures of the function through time, and
put them all together to create a 3D obect that was eventually printed.
*/

//t = map(frameCount, 1, 501, -10, 10);
//evaluateFunction();
//saveFrame();
//if (t  0) {
//   t++;
//  }
//} else exit();
}

void evaluateFunction() {
background(0);
color c = color(255, 0,0);
float jump;
/*
these first four if statements set bounds on the actual x and y bounds in the program
in order to prevent any lag.
*/

if (lowerX  500) {
upperX = 500;
}
if (lowerY  500){
upperY = 500;
}

//this if statement used to find the right ratio for the jumps used in the for-loop.
if (upperX-lowerX &lt; upperY-lowerY){
jump = .02*(upperX-lowerX)/20;
} else {
jump = .02*(upperY-lowerY)/20;
}
for (float x = lowerX; x &lt;= upperX; x+= jump) {
for (float y = lowerY; y &lt;= upperY; y+= jump) {
// float value is the left side of the equation
float value = x*x*x -y*y*x*t;
int xVal;
int yVal;
// this is the equation that is checked, where value is defined above.
if (value  700) {
if (mouseY  25) {
typeUpperx = true;
typeLowerx = false;
typeUppery = false;
typeLowery = false;
} else if (mouseY  85) {
typeUppery = true;
typeLowery = false;
typeUpperx = false;
typeLowerx = false;
}
} else if (mouseX &gt; 625 &amp;&amp; mouseX &lt; 685) {
if (mouseY  25) {
typeLowerx = true;
typeUpperx = false;
typeUppery = false;
typeLowery = false;
} else if (mouseY  85) {
typeLowery = true;
typeUppery = false;
typeLowerx = false;
typeUpperx = false;
}
}
}

```

What I have learned

This project has not only taught me a lot about programming, but myself as a programmer. I have started to grow into myself, and focus on what I really enjoy creating. I also came across a number of obstacles, and tried to find my own workarounds for them. After growing frustrated with my own programs, I have realized how to prevent these headaches. First, I need to make sure I always organize my programs. Consistently making functions to keep my code clean is key, and I will undoubtedly continue this routine in the future. It is also important to comment on lines of code that are especially complicated. It is amazing how fast I can forget what my code does a day after I wrote it. This tip isn’t only for my benefit, though. If I can’t understand my own program, there is no way any other programmer reading my code could have any clue either. Overall, this project has been an incredible way for me to learn about myself and how to think critically with regards to programming. https://www.openprocessing.org/sketch/430439