package main; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import de.uniba.wiai.lspi.chord.data.ID; import de.uniba.wiai.lspi.chord.service.NotifyCallback; import de.uniba.wiai.lspi.chord.service.impl.ChordImpl; import java.util.Collections; import java.util.logging.Level; import java.util.logging.Logger; public class GameNotify implements NotifyCallback { // package private members final List<BroadcastLog> broadcastLog = new ArrayList<>(); final List<ID> uniquePlayers = new ArrayList<>(); final Map<ID, ID[]> uniquePlayersSectors = new HashMap<>(); List<ID> shootableSectors = new ArrayList<>(); //private members private GameLogic gameLogic = null; private ChordImpl chordImpl = null; private int shipsLeft = 10; private final Map<ID, Integer> hitForID = new HashMap<>(); public void setChordClient(GameLogic chordClient, ChordImpl chordImpl) { this.gameLogic = chordClient; this.chordImpl = chordImpl; } /** * gets called, when someone shoots at us. It calls the proper methods to continue. * * @param target is the target ID */ @Override public void retrieved(ID target) { handleHit(target); calculateUniquePlayersSectors(); calculateShootableSectors(); gameLogic.shoot(); } /** * checks if one of our ships was in the targeted sector * * @param target is the target ID */ private void handleHit(ID target) { ID[] sectors = gameLogic.mySectors; System.out.println("Ships left: " + shipsLeft); for (int i = 0; i < sectors.length - 1; i++) { if (target.compareTo(sectors[i]) >= 0 && target.compareTo(sectors[i + 1]) < 0) { if (gameLogic.ships[i]) { System.out.println("Ship " + shipsLeft + " destroyed in sector " + (i + 1)); shipsLeft--; gameLogic.ships[i] = false; chordImpl.broadcast(target, Boolean.TRUE); break; } else { System.out.println("no Ship" + " in sector " + (i + 1)); chordImpl.broadcast(target, Boolean.FALSE); break; } } } if (target.compareTo(sectors[sectors.length - 1]) >= 0 && target.compareTo(gameLogic.myID) <= 0) { if (gameLogic.ships[sectors.length - 1]) { System.out.println("Ship " + shipsLeft + " destroyed in sector 100"); shipsLeft--; gameLogic.ships[sectors.length - 1] = false; chordImpl.broadcast(target, Boolean.TRUE); } else { System.out.println("no Ship" + " in sector 100"); chordImpl.broadcast(target, Boolean.FALSE); } } if (shipsLeft < 1) { System.out.println("I LOST!"); try { Thread.sleep(10000); } catch (InterruptedException ex) { Logger.getLogger(GameNotify.class.getName()).log(Level.SEVERE, null, ex); } } } /** * This is the callback method for fired shots. It informs as about the battle status. * * @param source player who is under fire * @param target the targeted sector of source * @param hit was the shot a hit or not */ @Override public void broadcast(ID source, ID target, Boolean hit) { int transactionID = chordImpl.getLastSeenTransactionID(); // chordImpl.setLastSeenTransactionID(transactionID); broadcastLog.add(new BroadcastLog(source, target, hit, transactionID)); if (hit) { if (hitForID.containsKey(source)) { int tmp = hitForID.get(source); hitForID.put(source, ++tmp); if (tmp == 10) { System.out.println("Player " + target + " lost!\nlast seen transaction ID: " + chordImpl.getLastSeenTransactionID()); try { Thread.sleep(10000); } catch (InterruptedException ex) { Logger.getLogger(GameNotify.class.getName()).log(Level.SEVERE, null, ex); } } } else { hitForID.put(source, 1); } } if (!uniquePlayers.contains(source)) { uniquePlayers.add(source); } Collections.sort(uniquePlayers); } /** * calculates the 100 sectors for every player, if it has changed since it was last called */ void calculateUniquePlayersSectors() { if (uniquePlayers.size() == uniquePlayersSectors.size()) { return; } for (int i = 0; i < uniquePlayers.size() - 1; i++) { ID[] newSectors = gameLogic.calculateSectors( uniquePlayers.get(i), uniquePlayers.get(i + 1)); uniquePlayersSectors.put(uniquePlayers.get(i), newSectors); } // case for the last player ID[] newSectors = gameLogic.calculateSectors( uniquePlayers.get(uniquePlayers.size() - 1), uniquePlayers.get(0)); uniquePlayersSectors.put(uniquePlayers.get(uniquePlayers.size() - 1), newSectors); } /** * regenerates the ArrayList of potential target sectors */ void calculateShootableSectors() { shootableSectors = new ArrayList<>(); // fill List for (ID uniquePlayer : uniquePlayers) { for (int j = 0; j < gameLogic.I; j++) { shootableSectors.add(uniquePlayersSectors.get(uniquePlayer)[j]); } } // remove fields, that are destroyed for (BroadcastLog bl : broadcastLog.toArray(new BroadcastLog[0])) { for (ID uniquePlayer : uniquePlayers) { ID[] sectors = uniquePlayersSectors.get(uniquePlayer); int index = gameLogic.isInSector(bl.getTarget(), sectors); if (index != -1) { shootableSectors.remove(sectors[index]); } } } // remove own fielde for (ID id : gameLogic.mySectors) { shootableSectors.remove(id); } System.out.println("Number of shootable sectors: " + shootableSectors.size()); } }