[UPDATED for 11-10-27 homework: I intend to expand upon this sketch for my final project. I've added functionality for offspring taking an average of the parents' traits, but of course this is only one small aspect of where we believe we get our genes/traits/habits from. While we may be born to smart parents, we may end up dumb. So maybe weighing genetics vs. luck vs. environment vs. whatever will need to be the preferred future model. Which is great, because it will dovetail nicely into my plans to create Galapag.us's "evolutions", or formulae hypothesizing what characters people are made up of. So someone's numbers may be range-bound via genetics but may leap way out of bounds with other factors playing a part. What is the role of which country one's parents are identified with in how one turns out? I also need to add aging, and tracking of offspring from parents, perhaps seeing how the code determines procreation likelihood.
I would also like to patch the Processing sketch into my already-existing user database for Galapag.us in MySQL. I suspect Processing might have some nice data visualization libraries I can use to feltronize the data I have already.]
For our homework this week, we were supposed to write some Processing code that creates multiple instances of an object. I took my genetic crossing homework from last week and expanded it.
Most notably, all the “persons” were turned into an array of Person objects. I hashed out the sex() function more, but didn’t do a blend of all the characteristics, leaving it a randomized process for the time being. But offspring of offspring could now reproduce via the flirt(), chemistry(), and sex() functions that calculate whether two random male-female pairs (sorry, I didn’t make adopt() or insemination() functions yet) find an attraction and mate.
I also added a new class for nations, creating the US, China, and EU. I thought about checking each person object to see if it would be more attracted to a certain nation and thus gravitate towards it, but I was having problems either with how to move the persons accurately (weighting between preferences for the three nations) and also how to keep them from bunching up together so much that they are unreadable. Everything is there though except for the requisite movement functions. The nations draw squares based on the rating (1-10 scale) of their security, innovation, jobOpportunity, and immigrationPolicy. Obviously this doesn’t include all variables but some to just test to see if it works. I wanted the person-nation attraction to be based on intelligence vs. innovation (which I realize is not a very strong relationship always).
Pressing the space bar stops the looping so you can get a look at the non-moving sketch. Mousing over the different person nodes pops up a box with that node’s precise data.
Demo and code below the jump:
Demo:
The code:
// Ben Turner // NYU-ITP, Intro to Computational Media // Exercise with objects, classes, constructors // need these functions for all the vars and walking thru them import java.util.Enumeration; import java.util.Hashtable; Person person[]; // init Person object array Nation nation[]; // init Nation object array boolean toggleNoLoop = false; // toggles space bar for stopping/starting loop int numCharacteristics = 19; // total characteristics per person (see Person class) int numPeople = 4; // initialize starting # of ppl int maxPeople = 30; // so it won't go nuts; don't forget to limit and/or raise this when needed int flirter1, flirter2; // picks random flirters int personNodeSize = 20; // size of black circle representing each person int ageDivider = 5; // divides age for drawing circle int weightDivider = 40; // divides weight for drawing circle int heightDivider = 10; // divides height for drawing circle int numNations = 4; // starting # of nations int maxNations = 10; // so won't go out of bounds int nationNodeSize=200; // size of nation blocs int[][] colorArray = new int[numCharacteristics][3]; // need colors for all characteristics int[] characteristicsArray = new int[numCharacteristics]; void setup() { size(600, 700); smooth(); frameRate(5); person = new Person[maxPeople]; nation = new Nation[maxNations]; // init all person objects & nations for (int i=0;i<maxPeople;i++) { person[i] = new Person(i, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", -1, -1); } for (int i=0;i<maxNations;i++) { nation[i] = new Nation(i, "", 0, 0, 0, 0, 0, 0); } // create some Adams and Eves and Sumerians person[0] = new Person(0, 6, 10, 10, 7, 6, 8, 6, 180, 67, 10, 80, 10, 10, 9, 8, 5, 2, 1, 7, "Albert Einstein", "male", -1, -1); person[1] = new Person(1, 2, 2, 1, 8, 5, 2, 2, 130, 70, 4, 30, 2, 6, 7, 5, 2, 2, 10, 9, "Gisele Bundchen", "female", -1, -1); person[2] = new Person(2, (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 300), (int)random(1, 100), (int)random(1, 10), (int)random(1, 120), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1,10), "person3", "male", -1, -1); person[3] = new Person(2, (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 300), (int)random(1, 100), (int)random(1, 10), (int)random(1, 120), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1,10), "person4", "female", -1, -1); nation[0] = new Nation(0, "USA", 200, 100, (int)random(1, 100), (int)random(1, 100), (int)random(1, 100), (int)random(1, 100)); nation[1] = new Nation(0, "European Union", 200, 400, (int)random(1, 100), (int)random(1, 100), (int)random(1, 100), (int)random(1, 100)); nation[2] = new Nation(0, "China", 200, 600, (int)random(1, 100), (int)random(1, 100), (int)random(1, 100), (int)random(1, 100)); // generates random color standard for all the characteristics stroke(0); for (int i=0;i<numCharacteristics;i++) { for (int j=0;j<3;j++) { colorArray[i][j] = int(random(255)); } } } void draw() { background(255); fill(0); text("blue = parent -> child, green = 2 parents", 15, 15); drawNations(); drawLegend(); drawPeople(); drawPopUpBox(); flirt(); // as people do // is there an attraction that may create offspring? if (numPeople < maxPeople-1) { // or else person[] will go out of bounds when creating new person if (chemistry(flirter1, flirter2)) { numPeople++; person[numPeople] = sex(person[flirter1], person[flirter2]); } } // unluckyNightOut(); } /* void unluckyNightOut() { int[] xPos = new int[numPeople]; int[] yPos = new int[numPeople]; for (int i=0;i<numPeople;i++) { xPos[i] = person[i].xPos; yPos[i] = person[i].yPos; } } */ // gets two unique male-female pairs to test compatibility void flirt() { boolean twoUniques = false; int randPpl = numPeople - 1; flirter1 = (int)random(randPpl); while (twoUniques == false) { flirter2 = (int)random(randPpl); if (flirter1 != flirter2) { twoUniques = true; } } } // takes two results from flirt() and sees if they pass certain reproduction tests // e.g. male-female pair? similar appearance level? same level of money? // then returns boolean saying whether sex() will occur boolean chemistry(int _flirter1, int _flirter2) { boolean procreate = false; int randomTest = (int)random(10); if (randomTest < 4) { if ((person[_flirter1].gender == "male" && person[_flirter2].gender == "female") || (person[_flirter2].gender == "male" && person[_flirter1].gender == "female")) { if (abs((int)Float.parseFloat(person[_flirter1].trait.get("appearance").toString())) - abs((int)Float.parseFloat(person[_flirter2].trait.get("appearance").toString())) <= 2) { if (abs((int)Float.parseFloat(person[_flirter1].trait.get("money").toString())) - abs((int)Float.parseFloat(person[_flirter2].trait.get("money").toString())) <= 3) { if (abs((int)Float.parseFloat(person[_flirter1].trait.get("religiosity").toString())) - abs((int)Float.parseFloat(person[_flirter2].trait.get("religiosity").toString())) <= 1) { procreate = true; } } } } } return procreate; } // takes two parents and creates an offspring person object Person sex(Person comp1, Person comp2) { Person newPerson; String _gender = ""; int _pickGender = (int)random(0,1.99); int _parent1 = comp1.uniqueID; int _parent2 = comp2.uniqueID; switch (_pickGender) { case 0: _gender = "male"; break; case 1: _gender = "female"; break; } newPerson = new Person(numPeople, (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 300), (int)random(1, 100), (int)random(1, 10), (int)random(1, 120), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1, 10), (int)random(1,10), "person"+Integer.toString(numPeople), _gender, _parent1, _parent2); int _appearance; int _diameter1 = (int)Float.parseFloat(comp1.trait.get("appearance").toString()); int _diameter2 = (int)Float.parseFloat(comp2.trait.get("appearance").toString()); _appearance = ceil((_diameter1 + _diameter2)/2); newPerson.trait.put("appearance", _appearance); return newPerson; } /* int calcCultureMoveX(int personID, int personX) { int totalMoveX = 0; float _influence; for (int i=0;i<numNations;i++) { _influence = Float.parseFloat(person[personID].trait.get("intelligence").toString()) - Float.parseFloat(nation[i].trait.get("innovation").toString()); int _absInfluence = abs(int(_influence)); if (_absInfluence <= 10) { totalMoveX = nation[i].xPos - personX; totalMoveX = ceil(totalMoveX / 20); } } return totalMoveX; } int calcCultureMoveY(int personID, int personY) { int totalMoveY = 0; float _influence; for (int i=0;i<numNations;i++) { _influence = Float.parseFloat(person[personID].trait.get("intelligence").toString()) - ceil(Float.parseFloat(nation[i].trait.get("innovation").toString()) / 10); int _absInfluence = abs(int(_influence)); System.out.println(_absInfluence); if (_absInfluence <= 1) { totalMoveY = (nation[i].yPos + personY) / 2; } } return totalMoveY; } */ void drawPeople() { // only draw actual people, not empty objects for (int i=0;i<numPeople;i++) { int strength = (int)Float.parseFloat(person[i].trait.get("strength").toString()); if (strength != 0) { person[i].display(); /* person[i].xPos = person[i].xPos + calcCultureMoveX(i, person[i].xPos); int finalY = calcCultureMoveY(i, person[i].yPos); int speedY = ceil(abs(person[i].yPos - finalY) / 20); if (person[i].yPos < finalY) person[i].yPos = person[i].yPos + speedY; */ // draw familial connection lines if (person[i].parent1 != -1) { stroke(0,0,255,100); line(person[person[i].parent1].xPos, person[person[i].parent1].yPos, person[i].xPos, person[i].yPos); line(person[person[i].parent2].xPos, person[person[i].parent2].yPos, person[i].xPos, person[i].yPos); stroke(0,255,0,100); line(person[person[i].parent1].xPos, person[person[i].parent1].yPos, person[person[i].parent2].xPos, person[person[i].parent2].yPos); stroke(0); } } } } void drawNations() { for (int i=0;i<numNations;i++) { int security = (int)Float.parseFloat(nation[i].trait.get("security").toString()); if (security != 0) { nation[i].display(); } } } void drawLegend() { int i = 0; // iterator for which characteristic to print for the legend int j = 30; // distance between each item in the legend stroke(0); // loads circle diameters from hashtable, iterates thru all characteristics // person[0] arbitrary usage for pulling out characteristics for (Enumeration e = person[1].trait.keys() ; e.hasMoreElements() ; ) { fill(colorArray[i][0], colorArray[i][1], colorArray[i][2], 100); rect(445, j, 5, 5); fill(colorArray[i][0], colorArray[i][1], colorArray[i][2]); text(e.nextElement().toString(), 455, j+7); i++; j = j + 15; } } // when you mouseover a node, some basic data is displayed void drawPopUpBox() { for (int i=0;i<numPeople;i++) { int strength = (int)Float.parseFloat(person[i].trait.get("strength").toString()); if (strength != 0) { if (mouseX >= person[i].xPos-(int(personNodeSize/2)) && mouseX <= person[i].xPos+(int(personNodeSize/2)) && mouseY >= person[i].yPos-(int(personNodeSize/2)) && mouseY <= person[i].yPos+(int(personNodeSize/2))) { int drawBoxX = mouseX; int drawBoxY = mouseY; int drawBoxWidth = 200; int drawBoxHeight = 350; if ((drawBoxY + drawBoxHeight) > height) { drawBoxY = drawBoxY - 30 - abs(height-(drawBoxY + drawBoxHeight)); } fill(255); stroke(0); rect(drawBoxX+15,drawBoxY+15,drawBoxWidth,drawBoxHeight); fill(0); text(person[i].gender + ", " + (int)Float.parseFloat(person[i].trait.get("age").toString()) * ageDivider + "yo, " + (int)Float.parseFloat(person[i].trait.get("pWeight").toString()) * weightDivider + "lbs, " + (int)Float.parseFloat(person[i].trait.get("pHeight").toString()) * heightDivider + "\"" , drawBoxX+30, drawBoxY+30); int j = 0; int k = 0; // distance between each item in the legend // draws popup window for values from each person node Object characteristic; for (Enumeration e = person[1].trait.keys() ; e.hasMoreElements() ; ) { characteristic = e.nextElement(); fill(colorArray[j][0], colorArray[j][1], colorArray[j][2]); text(characteristic.toString(), drawBoxX+45, drawBoxY+55+k); text(person[i].trait.get(characteristic).toString(), drawBoxX+20, drawBoxY+55+k); j++; k += 15; } } } } } void keyPressed() { if (keyCode == 32) { if (toggleNoLoop == false) { noLoop(); toggleNoLoop = true; } else if (toggleNoLoop == true) { loop(); toggleNoLoop = false; } } } class Person { Hashtable trait = new Hashtable(); String namePerson, gender; int parent1, parent2, uniqueID, xPos, yPos; // constructor Person(int _uniqueID, int _strength, int _intelligence, int _wisdom, int _charisma, int _stamina, int _wit, int _humor, int _pWeight, int _pHeight, int _education, int _age, int _creativity, int _responsibility, int _discipline, int _honesty, int _religiosity, int _entrepreneurialism, int _appearance, int _money, String _namePerson, String _gender, int _parent1, int _parent2) { trait.put("strength", _strength); trait.put("intelligence", _intelligence); trait.put("wisdom", _wisdom); trait.put("charisma", _charisma); trait.put("stamina", _stamina); trait.put("wit", _wit); trait.put("humor", _humor); trait.put("pWeight", ceil(_pWeight / 40)); trait.put("pHeight", ceil(_pHeight / 10)); trait.put("education", _education); trait.put("age", ceil(_age / 5)); trait.put("creativity", _creativity); trait.put("responsibility", _responsibility); trait.put("discipline", _discipline); trait.put("honesty", _honesty); trait.put("religiosity", _religiosity); trait.put("entrepreneurialism", _entrepreneurialism); trait.put("appearance", _appearance); trait.put("money", _money); uniqueID = _uniqueID; namePerson = _namePerson; xPos = int(random(50, 350)); yPos = int(random(50, 650)); parent1 = _parent1; parent2 = _parent2; gender = _gender; } // end Person method void display() { stroke(0); int i = 0; // loads circle diameters from hashtable, iterates thru all characteristics for (Enumeration e = trait.keys() ; e.hasMoreElements() ; ) { fill(colorArray[i][0], colorArray[i][1], colorArray[i][2], 100); Object characteristic = e.nextElement(); Object diameterCirc = trait.get(characteristic); float _diameter = Float.parseFloat(diameterCirc.toString()); int diam = ceil(_diameter)*2; noStroke(); ellipse(xPos+int(random(-40, 40)), yPos+int(random(-40, 40)), diam, diam); i++; } // displays main circle for each Person fill(0); ellipse(xPos, yPos, personNodeSize, personNodeSize); // overall rating, in middle text(namePerson, xPos+15, yPos+15); } // display for Person } // end Person class class Nation { Hashtable trait = new Hashtable(); int uniqueID, xPos, yPos; String nameNation; Nation(int _uniqueID, String _nameNation, int _xPos, int _yPos, int _security, int _innovation, int _jobOpportunity, int _immigrationPolicy) { trait.put("security", _security); trait.put("innovation", _innovation); trait.put("jobOpportunity", _jobOpportunity); trait.put("immigrationPolicy", _immigrationPolicy); uniqueID = _uniqueID; nameNation = _nameNation; xPos = _xPos; yPos = _yPos; } void display() { stroke(0); int i = 0; // loads rect diameters from hashtable, iterates thru all characteristics for (Enumeration e = trait.keys() ; e.hasMoreElements() ; ) { fill(colorArray[i][0], colorArray[i][1], colorArray[i][2], 20); Object characteristic = e.nextElement(); Object diameterRect = trait.get(characteristic); float _diameter = Float.parseFloat(diameterRect.toString()); int diam = ceil(_diameter)*2; noStroke(); rect(xPos+int(random(-40, 40)), yPos+int(random(-40, 40)), diam, diam); i++; } // displays main rect for each Nation fill(0,100); text(nameNation, xPos+15, yPos+15); } // display for Nation }