package org.drooms.impl; import org.drooms.api.Game; import org.drooms.api.GameProgressListener; import org.drooms.api.Player; import org.drooms.api.Playground; import org.drooms.impl.util.DroomsStrategyValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.sql.Timestamp; import java.time.Instant; import java.util.*; import java.util.stream.Collectors; /** * Convenient class used to create Drooms game based on the specified parameters. */ public class DroomsGame { private final File p; private final File c; private final Collection<Player> players; private final File f; private final Class<? extends Game> cls; private final Set<GameProgressListener> listeners = new HashSet<>(); private static final Logger LOGGER = LoggerFactory.getLogger(DroomsGame.class); public DroomsGame(final Class<? extends Game> game, final File p, final List<Player> players, final File gameConfig, final File reportFolder) { this.c = gameConfig; this.p = p; this.f = reportFolder; this.cls = game; this.players = players; // validate players final List<Player> invalidPlayers = this.players.stream().filter(player -> { boolean isInvalid = false; final DroomsStrategyValidator validator = DroomsStrategyValidator.getInstance(player.getStrategyReleaseId()); if (!validator.isValid()) { isInvalid = true; DroomsGame.LOGGER.error("Player {} has malformed strategy:", player.getName()); validator.getErrors().forEach(message -> DroomsGame.LOGGER.error(" {}", message)); } else if (!validator.isClean()) { DroomsGame.LOGGER.warn("Player {} has an incomplete strategy:", player.getName()); validator.getWarnings().forEach(message -> DroomsGame.LOGGER.warn(" {}", message)); } return isInvalid; }).collect(Collectors.toList()); if (invalidPlayers.size() > 0) { throw new IllegalArgumentException("Some players have invalid strategies. Check log for details."); } } public boolean addListener(final GameProgressListener listener) { return this.listeners.add(listener); } public Playground getPlayground() { try (final InputStream is = new FileInputStream(this.p)) { return this.cls.newInstance().buildPlayground(this.p.getName(), is); } catch (InstantiationException | IllegalAccessException e) { throw new IllegalStateException("Cannot find game class.", e); } catch (final IOException e) { throw new IllegalStateException("Cannot read playground.", e); } } public Map<Player, Integer> play(final String name) { final File f = new File(this.f, name + "-" + Timestamp.from(Instant.now())); if (!f.exists()) { f.mkdirs(); } try (final InputStream contextFis = new FileInputStream(this.c); final InputStream playgroundFis = new FileInputStream(this.p)) { final Game g = this.cls.newInstance(); g.setContext(contextFis); this.listeners.forEach(listener -> g.addListener(listener)); final Map<Player, Integer> result = g.play(g.buildPlayground(name, playgroundFis), this.players, f); // report try (final Writer w = new BufferedWriter(new FileWriter(new File(f, "report.xml")))) { g.getReport().write(w); } catch (final IOException e) { DroomsGame.LOGGER.info("Failed writing report for game: {}.", name); } return result; } catch (final Exception ex) { throw new IllegalStateException("Cannot play the game.", ex); } } public boolean removeListener(final GameProgressListener listener) { return this.listeners.remove(listener); } }