Advertisement
Guest User

Untitled

a guest
Nov 21st, 2019
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.90 KB | None | 0 0
  1. import java.util.HashMap;
  2. import java.util.LinkedList;
  3. import java.util.List;
  4. import java.util.Map;
  5.  
  6. public class ChainReaction implements ChainReactionInterface {
  7.     private final Map<Integer, Node> nodes = new HashMap<>();
  8.     private volatile int workingThreads = 0;
  9.     private volatile boolean simulationStarted = false;
  10.     private volatile boolean initializationInProgress = false;
  11.     private DamagePropagationInterface damagePropagationInterface;
  12.  
  13.     @Override
  14.     public synchronized void addObject(int id) {
  15.         nodes.put(id, new Node(id));
  16.     }
  17.  
  18.     @Override
  19.     public synchronized void neighbour(int idA, int idB) {
  20.         if (idA != idB) {
  21.             Node nodeA = nodes.get(idA);
  22.             Node nodeB = nodes.get(idB);
  23.  
  24.             nodeA.addNeighbor(nodeB);
  25.             nodeB.addNeighbor(nodeA);
  26.         }
  27.     }
  28.  
  29.     @Override
  30.     public boolean resultReady() {
  31.         return simulationStarted && !initializationInProgress && workingThreads == 0;
  32.     }
  33.  
  34.     @Override
  35.     public boolean isDestroyed(int id) {
  36.         return nodes.get(id).isDestroyed();
  37.     }
  38.  
  39.     @Override
  40.     public synchronized void setDamagePropagator(DamagePropagationInterface dpi) {
  41.         this.damagePropagationInterface = dpi;
  42.     }
  43.  
  44.     @Override
  45.     public void destroyed(int id) {
  46.         initializationInProgress = true;
  47.         simulationStarted = true;
  48.  
  49.         Node node = nodes.get(id);
  50.         boolean destroyed = false;
  51.         if (node.isLive()) {
  52.             synchronized (node) {
  53.                 if (node.isLive()) {
  54.                     node.destroy();
  55.                     destroyed = true;
  56.                 }
  57.             }
  58.         }
  59.  
  60.         if (destroyed) {
  61.             findNeighboursToDestroy(node).stream()
  62.                     .map(DestroyingRunnable::new)
  63.                     .forEach(this::startTrackedThread);
  64.         }
  65.  
  66.         initializationInProgress = false;
  67.     }
  68.  
  69.     private List<Node> findNeighboursToDestroy(Node node) {
  70.         List<Node> neighboursToDestroy = new LinkedList<>();
  71.         for (Node neighbour : node.getNeighbours()) {
  72.             if (neighbour.isLive()) {
  73.                 synchronized (neighbour) {
  74.                     if (neighbour.isLive() && damagePropagationInterface.destroyedBy(node.id, neighbour.id)) {
  75.                         neighbour.markToDestroy();
  76.                         neighboursToDestroy.add(neighbour);
  77.                     }
  78.                 }
  79.             }
  80.         }
  81.         return neighboursToDestroy;
  82.     }
  83.  
  84.     private void startTrackedThread(DestroyingRunnable runnable) {
  85.         new Thread(new TrackingRunnable(runnable)).start();
  86.     }
  87.  
  88.     private class DestroyingRunnable implements Runnable {
  89.         private final Node node;
  90.  
  91.         private DestroyingRunnable(Node node) {
  92.             this.node = node;
  93.         }
  94.  
  95.         @Override
  96.         public void run() {
  97.             node.destroy();
  98.  
  99.             List<Node> neighboursToProcess = findNeighboursToDestroy(node);
  100.             if (!neighboursToProcess.isEmpty()) {
  101.                 neighboursToProcess.subList(1, neighboursToProcess.size()).stream()
  102.                         .map(DestroyingRunnable::new)
  103.                         .forEach(ChainReaction.this::startTrackedThread);
  104.  
  105.                 new DestroyingRunnable(neighboursToProcess.get(0)).run();
  106.             }
  107.         }
  108.     }
  109.  
  110.     private class TrackingRunnable implements Runnable {
  111.         private final Runnable runnable;
  112.  
  113.         private TrackingRunnable(Runnable runnable) {
  114.             this.runnable = runnable;
  115.         }
  116.  
  117.         @Override
  118.         public void run() {
  119.             try {
  120.                 synchronized (ChainReaction.this) {
  121.                     workingThreads++;
  122.                 }
  123.                 runnable.run();
  124.             } finally {
  125.                 synchronized (ChainReaction.this) {
  126.                     workingThreads--;
  127.                 }
  128.             }
  129.         }
  130.     }
  131.  
  132.     private static class Node {
  133.         private final int id;
  134.         private final List<Node> neighbours = new LinkedList<>();
  135.         private volatile NodeState state = NodeState.LIVE;
  136.  
  137.         private Node(int id) {
  138.             this.id = id;
  139.         }
  140.  
  141.         private List<Node> getNeighbours() {
  142.             return neighbours;
  143.         }
  144.  
  145.         private void addNeighbor(Node neighbor) {
  146.             neighbours.add(neighbor);
  147.         }
  148.  
  149.         private boolean isLive() {
  150.             return state == NodeState.LIVE;
  151.         }
  152.  
  153.         private boolean isDestroyed() {
  154.             return state == NodeState.DESTROYED;
  155.         }
  156.  
  157.         private void markToDestroy() {
  158.             state = NodeState.MARKED_TO_DESTROY;
  159.         }
  160.  
  161.         private void destroy() {
  162.             System.out.println("DESTROYED " + id);
  163.             state = NodeState.DESTROYED;
  164.         }
  165.  
  166.         private enum NodeState {
  167.             LIVE, MARKED_TO_DESTROY, DESTROYED
  168.         }
  169.     }
  170. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement