herd_immunity.pde 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. class Doctor {
  2. private PVector position;
  3. private PVector direction;
  4. private int size = 10;
  5. public Doctor() {
  6. position = new PVector(random(size, width - size), random(size, height - size));
  7. direction = new PVector(random(-1, 1), random(-1, 1));
  8. }
  9. public void update() {
  10. if (position.x <= size || position.x >= width - 10) {
  11. direction.x = -1 * direction.x;
  12. }
  13. if (position.y <= size || position.y >= height - 10) {
  14. direction.y = -1 * direction.y;
  15. }
  16. position.x += direction.x;
  17. position.y += direction.y;
  18. }
  19. public void draw() {
  20. stroke(0, 0, 0);
  21. fill(255, 255, 255);
  22. ellipse(position.x, position.y, size, size);
  23. noStroke();
  24. fill(255, 0, 0);
  25. rect(position.x - 1.5, position.y - 4, 3, 8);
  26. rect(position.x - 4, position.y - 1.5, 8, 3);
  27. }
  28. public boolean checkCollision(int xPos1, int yPos1, int xPos2, int yPos2) {
  29. if (position.x > xPos1 && position.x < xPos2 &&
  30. position.y > yPos1 && position.y < yPos2) {
  31. return true;
  32. }
  33. return false;
  34. }
  35. public void interact(ArrayList<Patient> population) {
  36. int xBounds = size / 2;
  37. int yBounds = size / 2;
  38. for (Patient neighbor : population) {
  39. if (neighbor.checkCollision((int)position.x - xBounds, (int)position.y - yBounds,
  40. (int)position.x + xBounds, (int)position.y + yBounds)) {
  41. neighbor.vaccinate();
  42. }
  43. }
  44. }
  45. }ArrayList<Patient> population = new ArrayList<Patient>();
  46. ArrayList<Doctor> medicalCommunity = new ArrayList<Doctor>();
  47. void setup() {
  48. size(800, 600);
  49. boolean isVaccinated = false;
  50. for (int i = 0; i < Settings.population; i++) {
  51. isVaccinated = Settings.vaccinationPercentage >= random(0, 100);
  52. population.add(new Patient(isVaccinated));
  53. }
  54. for (int i = 0; i < Settings.doctorPopulation; i++) {
  55. medicalCommunity.add(new Doctor());
  56. }
  57. }
  58. void draw() {
  59. for (Patient patient : population) {
  60. patient.update();
  61. patient.interact(population);
  62. }
  63. for (Doctor doctor : medicalCommunity) {
  64. doctor.update();
  65. doctor.interact(population);
  66. }
  67. background(255, 255, 255);
  68. noStroke();
  69. for (Patient patient : population) {
  70. patient.draw();
  71. }
  72. for (Doctor doctor : medicalCommunity) {
  73. doctor.draw();
  74. }
  75. int[] counts = {0, 0, 0, 0, 0};
  76. for (Patient patient : population) {
  77. counts[patient.getState()]++;
  78. }
  79. String message = "Uninfected: " + nf(counts[Patient.UNINFECTED], 4)+ " Vaccinated: "+nf(counts[Patient.VACCINATED], 4)+" Sick: "+nf(counts[Patient.SICK], 4)+" Immune: "+nf(counts[Patient.IMMUNE], 4)+" Dead: "+nf(counts[Patient.DEAD], 4);
  80. fill(0, 0, 0);
  81. textSize(18);
  82. text(message, 60, height - 5);
  83. fill(0, 0, 255, 180);
  84. ellipse(55, height - 12, 10, 10);
  85. fill(255, 127, 0, 180);
  86. ellipse(220, height - 12, 10, 10);
  87. fill(0, 255, 0, 180);
  88. ellipse(390, height - 12, 10, 10);
  89. fill(255, 127, 127, 180);
  90. ellipse(496, height - 12, 10, 10);
  91. fill(127, 127, 127, 180);
  92. ellipse(643, height - 12, 10, 10);
  93. }
  94. void mouseClicked() {
  95. fill(255, 0, 0);
  96. int clickSize = Settings.infectionClickSize;
  97. ellipse(mouseX, mouseY, clickSize * 2, clickSize * 2);
  98. for (Patient patient : population) {
  99. if (patient.checkCollision(mouseX - clickSize, mouseY - clickSize, mouseX + clickSize, mouseY + clickSize)) {
  100. patient.infect();
  101. }
  102. }
  103. }class Patient {
  104. private PVector position;
  105. private PVector direction;
  106. public static final int UNINFECTED = 0;
  107. public static final int VACCINATED = 1;
  108. public static final int SICK = 2;
  109. public static final int IMMUNE = 3;
  110. public static final int DEAD = 4;
  111. private int size = 10;
  112. private int infectedTimer = 0;
  113. private int immuneTimer = 0;
  114. private boolean hasDeath = false;
  115. private int state = UNINFECTED;
  116. public Patient(boolean isVaccinated) {
  117. position = new PVector(random(size, width - size), random(size, height - size - 20));
  118. direction = new PVector(random(-1, 1), random(-1, 1));
  119. if (isVaccinated) {
  120. state = VACCINATED;
  121. }
  122. hasDeath = Settings.deathProbability >= random(0, 100);
  123. }
  124. public int getState() {
  125. return state;
  126. }
  127. public void update() {
  128. if (state != DEAD) {
  129. if (position.x <= size || position.x >= width - size) {
  130. direction.x = -1 * direction.x;
  131. }
  132. if (position.y <= size || position.y >= height - size - 20) {
  133. direction.y = -1 * direction.y;
  134. }
  135. position.x += direction.x;
  136. position.y += direction.y;
  137. }
  138. if (state == SICK) {
  139. infectedTimer--;
  140. if (infectedTimer <= 0) {
  141. state = UNINFECTED;
  142. if (Settings.canBecomeImmune) {
  143. this.immunize();
  144. }
  145. if (hasDeath) {
  146. state = DEAD;
  147. }
  148. }
  149. }
  150. if (state == IMMUNE && !Settings.immuneForLife) {
  151. immuneTimer--;
  152. if (immuneTimer <= 0) {
  153. state = UNINFECTED;
  154. }
  155. }
  156. if (state == VACCINATED && !Settings.vaccinatedForLife) {
  157. immuneTimer--;
  158. if (immuneTimer <= 0) {
  159. state = UNINFECTED;
  160. }
  161. }
  162. }
  163. public void draw() {
  164. switch(state) {
  165. case UNINFECTED:
  166. fill(0, 0, 255, 180);
  167. break;
  168. case VACCINATED:
  169. fill(255, 127, 0, 180);
  170. break;
  171. case SICK:
  172. fill(0, 255, 0, 180);
  173. break;
  174. case IMMUNE:
  175. fill(255, 127, 127, 180);
  176. break;
  177. case DEAD:
  178. fill(127, 127, 127, 180);
  179. break;
  180. }
  181. ellipse(position.x, position.y, size, size);
  182. }
  183. public boolean checkCollision(int xPos1, int yPos1, int xPos2, int yPos2) {
  184. if (position.x > xPos1 && position.x < xPos2 &&
  185. position.y > yPos1 && position.y < yPos2) {
  186. return true;
  187. }
  188. return false;
  189. }
  190. public void infect() {
  191. if (state == UNINFECTED) {
  192. state = SICK;
  193. infectedTimer = Settings.sickDuration;
  194. }
  195. }
  196. public void immunize() {
  197. if (state == UNINFECTED || state == IMMUNE) {
  198. state = IMMUNE;
  199. immuneTimer = max(Settings.immuneDuration, immuneTimer);
  200. }
  201. }
  202. public void vaccinate() {
  203. if (state == UNINFECTED || state == IMMUNE) {
  204. state = VACCINATED;
  205. immuneTimer = max(Settings.vaccineDuration, immuneTimer);
  206. }
  207. }
  208. public void interact(ArrayList<Patient> population) {
  209. if ((Settings.canDeadInfect && state == DEAD) || state == SICK) {
  210. int xBounds = size / 2;
  211. int yBounds = size / 2;
  212. for (Patient neighbor : population) {
  213. if (neighbor.checkCollision((int)position.x - xBounds, (int)position.y - yBounds,
  214. (int)position.x + xBounds, (int)position.y + yBounds)) {
  215. neighbor.infect();
  216. }
  217. }
  218. }
  219. }
  220. }abstract static class Settings {
  221. public static int population = 1000;
  222. public static float vaccinationPercentage = 0.0;
  223. public static float deathProbability = 5.0;
  224. public static int sickDuration = 200;
  225. public static int infectionClickSize = 10;
  226. public static boolean canBecomeImmune = true;
  227. public static boolean immuneForLife = false;
  228. public static boolean vaccinatedForLife = false;
  229. public static int immuneDuration = 3000;
  230. public static int vaccineDuration = 3000;
  231. public static boolean canDeadInfect = false;
  232. public static int doctorPopulation = 0;
  233. }