@@ -0,0 +1,3734 @@
+package com.google.research.bleth.simulator;%0A%0Aimport static com.google.common.base.Preconditions.checkNotNull;%0A%0Aimport com.google.common.collect.ArrayListMultimap;%0Aimport com.google.common.collect.HashBiMap;%0Aimport com.google.common.collect.Multimap;%0Aimport java.util.HashMap;%0Aimport java.util.List;%0Aimport java.util.Map;%0A%0A%0A/** Tracing Simulation's Resolver, which receives information from its observers and estimate the beacons' locations according to it. */%0Apublic final class GlobalResolver implements IGlobalResolver %7B%0A    private Board estimatedBoard;%0A    private final Simulation simulation;%0A    private Multimap%3CTransmission, Location%3E currentRoundTransmissions = ArrayListMultimap.create();%0A    private HashBiMap%3CBeacon, Transmission%3E beaconsToTransmissions;%0A    private Map%3CBeacon, Location%3E beaconsToEstimatedLocations = new HashMap%3C%3E();%0A%0A    /**%0A     * A wrapper method to create new global resolver for a specific simulation.%0A     * The new resolver has a board for storing the estimated beacons' locations.%0A     * @param simulation is the world the resolver exists in.%0A     */%0A    public static GlobalResolver createResolver(Simulation simulation) %7B%0A        checkNotNull(simulation);%0A        Board board = new Board(simulation.getBoard().getRowsNum(), simulation.getBoard().getColsNum());%0A        HashBiMap%3CBeacon, Transmission%3E beaconsToTransmissions = HashBiMap.create();%0A        for (Beacon beacon : simulation.getBeacons()) %7B%0A            beaconsToTransmissions.put(beacon, beacon.transmit());%0A        %7D%0A        return new GlobalResolver(simulation, board, beaconsToTransmissions);%0A    %7D%0A%0A    @Override%0A    public void receiveInformation(Location observerLocation, List%3CTransmission%3E transmissions) %7B%0A        for (Transmission transmission : transmissions) %7B%0A            currentRoundTransmissions.put(transmission, observerLocation);%0A        %7D%0A    %7D%0A%0A    @Override%0A    public void estimate() %7B%0A        // Update only the beacons that there's new information about their location%0A        for (Transmission transmission : currentRoundTransmissions.keySet()) %7B%0A            Beacon beacon = beaconsToTransmissions.inverse().get(transmission);%0A            // Take into consideration the current estimated location of the beacon if there's such%0A            if (beaconsToEstimatedLocations.containsKey(beacon)) %7B%0A                currentRoundTransmissions.put(transmission, beaconsToEstimatedLocations.get(beacon));%0A            %7D%0A            Location newLocation = calculateNewLocation(beacon);%0A%0A            if (!beaconsToEstimatedLocations.keySet().contains(beacon)) %7B%0A                estimatedBoard.placeAgent(newLocation, beacon);%0A            %7D else %7B%0A                estimatedBoard.moveAgent(beaconsToEstimatedLocations.get(beacon), newLocation, beacon);%0A            %7D%0A            beaconsToEstimatedLocations.put(beacon, newLocation);%0A        %7D%0A%0A         currentRoundTransmissions.clear();%0A    %7D%0A%0A    @Override%0A    public Board getBoard() %7B%0A        return estimatedBoard;%0A    %7D%0A%0A    private GlobalResolver(Simulation simulation, Board estimatedBoard, HashBiMap%3CBeacon, Transmission%3E beaconsToTransmissions) %7B%0A        this.simulation = simulation;%0A        this.estimatedBoard = estimatedBoard;%0A        this.beaconsToTransmissions = beaconsToTransmissions;%0A    %7D%0A%0A    private Location calculateNewLocation(Beacon beacon) %7B%0A        List%3CLocation%3E locations = (List%3CLocation%3E) currentRoundTransmissions.get(beacon.transmit());%0A        int newRow = (int) Math.round((locations.stream().mapToDouble(location -%3E location.row).average().getAsDouble()));%0A        int newCol = (int) Math.round((locations.stream().mapToDouble(location -%3E location.col).average().getAsDouble()));%0A        return new Location(newRow, newCol);%0A    %7D%0A%7D%0A

Implement the class GlobalResolver.