Advertisement
Guest User

Untitled

a guest
Feb 24th, 2020
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.34 KB | None | 0 0
  1. import javafx.animation.AnimationTimer;
  2. import javafx.application.Application;
  3. import javafx.scene.Group;
  4. import javafx.scene.Scene;
  5. import javafx.scene.canvas.Canvas;
  6. import javafx.scene.canvas.GraphicsContext;
  7. import javafx.scene.paint.Color;
  8. import javafx.stage.Stage;
  9.  
  10. import java.util.Random;
  11.  
  12. import static java.lang.Math.sqrt;
  13. import static java.lang.System.exit;
  14. import static java.lang.System.out;
  15.  
  16. /*
  17. * Program to simulate segregation.
  18. * See : http://nifty.stanford.edu/2014/mccown-schelling-model-segregation/
  19. *
  20. * NOTE:
  21. * - JavaFX first calls method init() and then method start() far below.
  22. * - To test uncomment call to test() first in init() method!
  23. *
  24. */
  25. // Extends Application because of JavaFX (just accept for now)
  26. public class Neighbours extends Application {
  27.  
  28. class Actor {
  29. final Color color; // Color an existing JavaFX class
  30. boolean isSatisfied; // false by default
  31.  
  32. Actor(Color color) { // Constructor to initialize
  33. this.color = color;
  34. }
  35. }
  36.  
  37. // Below is the *only* accepted instance variable (i.e. variables outside any method)
  38. // This variable may *only* be used in methods init() and updateWorld()
  39. Actor[][] world; // The world is a square matrix of Actors
  40.  
  41. // Random object
  42. static Random rand = new Random();
  43.  
  44. // This is the method called by the timer to update the world
  45. // (i.e move unsatisfied) approx each 1/60 sec.
  46. void updateWorld() {
  47. // % of surrounding neighbours that are like me
  48. double threshold = 0.7;
  49.  
  50. // TODO update world
  51.  
  52.  
  53. for (int i = 0; i < (world.length - 1); i++) {
  54. for (int j = 0; j < (world.length - 1); j++) {
  55. if (world[i][j] != null) {
  56. world[i][j].isSatisfied = isSatisfied(world, i, j, threshold);
  57.  
  58. if(!world[i][j].isSatisfied) {
  59.  
  60. while (world[i][j] != null) {
  61. int rx = rand.nextInt(world.length);
  62. int ry = rand.nextInt(world.length);
  63.  
  64. if(isValidLocation(world.length, rx, ry)) {
  65. world[rx][ry] = world[i][j];
  66. world[i][j] = null;
  67. }
  68. }
  69. }
  70. }
  71. }
  72. }
  73. }
  74.  
  75. // This method initializes the world variable with a random distribution of Actors
  76. // Method automatically called by JavaFX runtime
  77. // That's why we must have "@Override" and "public" (just accept for now)
  78. @Override
  79. public void init() {
  80. //test(); // <---------------- Uncomment to TEST!
  81.  
  82. // %-distribution of RED, BLUE and NONE
  83. double[] dist = {0.25, 0.25, 0.50};
  84. // Number of locations (places) in world (must be a square)
  85. int nLocations = 900; // Should also try 90 000
  86. int width = (int)sqrt(nLocations);
  87.  
  88. // TODO initialize the world
  89. world = new Actor[width][width];
  90.  
  91. Actor[] entities = new Actor[nLocations];
  92. for (int i = 0, k = 0; i < entities.length; i++) {
  93. if(i <= (int)(dist[0]*nLocations)) {
  94. entities[(int)k++] = new Actor(Color.RED);
  95. } else if (i <= (int)(dist[0]*nLocations + dist[1]*nLocations)) {
  96. entities[(int)k++] = new Actor(Color.BLUE);
  97. } else {
  98. entities[(int)k++] = null;
  99. }
  100. }
  101. shuffleActorArray(entities);
  102.  
  103. for (int i = 0; i < width; i++) {
  104. System.arraycopy(entities, i * width + 0, world[i], 0, width);
  105. }
  106.  
  107. // Should be last
  108. fixScreenSize(nLocations);
  109. while (true) {
  110. updateWorld();
  111. }
  112. }
  113.  
  114. // --------------- Methods ------------------------------
  115.  
  116. // TODO Many ...
  117.  
  118. Boolean isSatisfied(Actor[][] world, int x, int y, double threshold) {
  119. Boolean[] neighbors = {true, true, true, true};
  120. Actor neighbor;
  121.  
  122. if (y < world.length) {
  123. neighbor = world[x][y + 1];
  124. if (neighbor != null) {
  125. neighbors[0] = neighbor.color == world[x][y].color;
  126. } else {
  127. neighbors[0] = true;
  128. }
  129. } else {
  130. neighbors[0] = true;
  131. }
  132.  
  133. if (y > 0) {
  134. neighbor = world[x][y - 1];
  135. if (neighbor != null) {
  136. neighbors[1] = neighbor.color == world[x][y].color;
  137. } else {
  138. neighbors[1] = true;
  139. }
  140. } else {
  141. neighbors[1] = true;
  142. }
  143.  
  144. if (x < world.length) {
  145. neighbor = world[x + 1][y];
  146. if (neighbor != null) {
  147. neighbors[2] = neighbor.color == world[x][y].color;
  148. } else {
  149. neighbors[2] = true;
  150. }
  151. } else {
  152. neighbors[2] = true;
  153. }
  154.  
  155. if (x > 0) {
  156. neighbor = world[x - 1][y];
  157. if (neighbor != null) {
  158. neighbors[3] = neighbor.color == world[x][y].color;
  159. } else {
  160. neighbors[3] = true;
  161. }
  162. } else {
  163. neighbors[3] = true;
  164. }
  165.  
  166. int i = 0;
  167. for (Boolean b : neighbors) {
  168. if(b){
  169. i++;
  170. }
  171. }
  172.  
  173. return threshold < i / neighbors.length;
  174. }
  175.  
  176.  
  177.  
  178.  
  179. // Check if inside world
  180. boolean isValidLocation(int size, int row, int col) {
  181. return 0 <= row && row < size && 0 <= col && col < size;
  182. }
  183.  
  184. // ----------- Utility methods -----------------
  185.  
  186. // TODO (general method possible reusable elsewhere)
  187. void shuffleActorArray(Actor[] array) {
  188. int n = array.length;
  189. // Loop over array.
  190. for (int i = 0; i < array.length; i++) {
  191. // Get a random index of the array past the current index.
  192. // ... The argument is an exclusive bound.
  193. // It will not go past the array's end.
  194. int randomValue = i + rand.nextInt(n - i);
  195. // Swap the random element with the present element.
  196. Actor randomElement = array[randomValue];
  197. array[randomValue] = array[i];
  198. array[i] = randomElement;
  199. }
  200. }
  201.  
  202. // ------- Testing -------------------------------------
  203.  
  204. // Here you run your tests i.e. call your logic methods
  205. // to see that they really work. Important!!!!
  206. void test() {
  207. // A small hard coded world for testing
  208. Actor[][] testWorld = new Actor[][]{
  209. {new Actor(Color.RED), new Actor(Color.RED), null},
  210. {null, new Actor(Color.BLUE), null},
  211. {new Actor(Color.RED), null, new Actor(Color.BLUE)}
  212. };
  213. double th = 0.5; // Simple threshold used for testing
  214.  
  215. int size = testWorld.length;
  216. out.println(isValidLocation(size, 0, 0));
  217. out.println(!isValidLocation(size, -1, 0));
  218. out.println(!isValidLocation(size, 0, 3));
  219.  
  220. // TODO
  221.  
  222. exit(0);
  223. }
  224.  
  225. // ******************** NOTHING to do below this row, it's JavaFX stuff **************
  226.  
  227. double width = 500; // Size for window
  228. double height = 500;
  229. final double margin = 50;
  230. double dotSize;
  231.  
  232. void fixScreenSize(int nLocations) {
  233. // Adjust screen window
  234. dotSize = 9000 / nLocations;
  235. if (dotSize < 1) {
  236. dotSize = 2;
  237. }
  238. width = sqrt(nLocations) * dotSize + 2 * margin;
  239. height = width;
  240. }
  241.  
  242. long lastUpdateTime;
  243. final long INTERVAL = 450_000_000; //450_000_000
  244.  
  245.  
  246. @Override
  247. public void start(Stage primaryStage) throws Exception {
  248.  
  249. // Build a scene graph
  250. Group root = new Group();
  251. Canvas canvas = new Canvas(width, height);
  252. root.getChildren().addAll(canvas);
  253. GraphicsContext gc = canvas.getGraphicsContext2D();
  254.  
  255. // Create a timer
  256. AnimationTimer timer = new AnimationTimer() {
  257. // This method called by FX, parameter is the current time
  258. public void handle(long now) {
  259. long elapsedNanos = now - lastUpdateTime;
  260. if (elapsedNanos > INTERVAL) {
  261. updateWorld();
  262. renderWorld(gc);
  263. lastUpdateTime = now;
  264. }
  265. }
  266. };
  267.  
  268. Scene scene = new Scene(root);
  269. primaryStage.setScene(scene);
  270. primaryStage.setTitle("Simulation");
  271. primaryStage.show();
  272.  
  273. timer.start(); // Start simulation
  274. }
  275.  
  276.  
  277. // Render the state of the world to the screen
  278. public void renderWorld(GraphicsContext g) {
  279. g.clearRect(0, 0, width, height);
  280. int size = world.length;
  281. for (int row = 0; row < size; row++) {
  282. for (int col = 0; col < size; col++) {
  283. int x = (int) (dotSize * col + margin);
  284. int y = (int) (dotSize * row + margin);
  285. if (world[row][col] != null) {
  286. g.setFill(world[row][col].color);
  287. g.fillOval(x, y, dotSize, dotSize);
  288. }
  289. }
  290. }
  291. }
  292.  
  293. public static void main(String[] args) {
  294. launch(args);
  295. }
  296.  
  297. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement