/******************************************************************************* * Copyright (c) 2001, 2010 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/epl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation * Pavel Savara * - Xml Serialization, refactoring *******************************************************************************/ package net.sf.robocode.battle.snapshot; import net.sf.robocode.battle.Battle; import net.sf.robocode.battle.peer.BulletPeer; import net.sf.robocode.battle.peer.BulletPeer; import net.sf.robocode.battle.peer.ProjectilePeer; import net.sf.robocode.battle.peer.RobotPeer; import net.sf.robocode.serialization.IXmlSerializable; import net.sf.robocode.serialization.XmlReader; import net.sf.robocode.serialization.SerializableOptions; import net.sf.robocode.serialization.XmlWriter; import robocode.control.snapshot.*; import java.io.IOException; import java.util.*; /** * A snapshot of a battle turn at a specific time instant in a battle. * The snapshot contains a snapshot of the battle turn data at that specific time. * * @author Flemming N. Larsen (original) * @author Pavel Savara (contributor) * @since 1.6.1 */ public final class TurnSnapshot implements java.io.Serializable, IXmlSerializable, ITurnSnapshot { private static final long serialVersionUID = 1L; /** List of snapshots for the robots participating in the battle */ private List<IRobotSnapshot> robots; /** List of snapshots for the bullets that are currently on the battlefield */ private List<IBulletSnapshot> bullets; /** Current TPS (turns per second) */ private int tps; /** Current round in the battle */ private int round; /** Current turn in the battle round */ private int turn; /** * Creates a snapshot of a battle turn that must be filled out with data later. */ public TurnSnapshot() {} /** * Creates a snapshot of a battle turn. * * @param battle the battle to make a snapshot of. * @param battleRobots the robots participating in the battle. * @param battleProjectiles the current bullet on the battlefield. * @param readoutText {@code true} if the output text from the robots must be included in the snapshot; * {@code false} otherwise. */ public TurnSnapshot(Battle battle, List<RobotPeer> battleRobots, List<BulletPeer> battleProjectiles, boolean readoutText) { robots = new ArrayList<IRobotSnapshot>(); bullets = new ArrayList<IBulletSnapshot>(); for (RobotPeer robotPeer : battleRobots) { robots.add(new RobotSnapshot(robotPeer, readoutText)); } for (ProjectilePeer bulletPeer : battleProjectiles) { bullets.add(new BulletSnapshot(bulletPeer)); } tps = battle.getTPS(); turn = battle.getTime(); round = battle.getRoundNum(); } @Override public String toString() { return this.round + "/" + turn + " (" + this.robots.size() + ")"; } /** * {@inheritDoc} */ public IRobotSnapshot[] getRobots() { return robots.toArray(new IRobotSnapshot[robots.size()]); } /** * {@inheritDoc} */ public IBulletSnapshot[] getBullets() { return bullets.toArray(new IBulletSnapshot[bullets.size()]); } /** * {@inheritDoc} */ public int getTPS() { return tps; } /** * {@inheritDoc} */ public int getRound() { return round; } /** * {@inheritDoc} */ public int getTurn() { return turn; } /** * {@inheritDoc} */ public IScoreSnapshot[] getSortedTeamScores() { List<IScoreSnapshot> copy = new ArrayList<IScoreSnapshot>(Arrays.asList(getIndexedTeamScores())); Collections.sort(copy); Collections.reverse(copy); return copy.toArray(new IScoreSnapshot[copy.size()]); } /** * {@inheritDoc} */ public IScoreSnapshot[] getIndexedTeamScores() { // team scores are computed on demand from team scores to not duplicate data in the snapshot List<IScoreSnapshot> results = new ArrayList<IScoreSnapshot>(); // noinspection ForLoopReplaceableByForEach for (int i = 0; i < robots.size(); i++) { results.add(null); } for (IRobotSnapshot robot : robots) { final IScoreSnapshot snapshot = results.get(robot.getContestantIndex()); if (snapshot == null) { results.set(robot.getContestantIndex(), robot.getScoreSnapshot()); } else { final ScoreSnapshot sum = new ScoreSnapshot(robot.getTeamName(), snapshot, robot.getScoreSnapshot()); results.set(robot.getContestantIndex(), sum); } } List<IScoreSnapshot> scores = new ArrayList<IScoreSnapshot>(); for (IScoreSnapshot scoreSnapshot : results) { if (scoreSnapshot != null) { scores.add(scoreSnapshot); } } return scores.toArray(new IScoreSnapshot[scores.size()]); } public void stripDetails(SerializableOptions options) { for (IRobotSnapshot r : getRobots()) { ((RobotSnapshot) r).stripDetails(options); } } /** * {@inheritDoc} */ public void writeXml(XmlWriter writer, SerializableOptions options) throws IOException { writer.startElement(options.shortAttributes ? "t" : "turn"); { writer.writeAttribute(options.shortAttributes ? "ro" : "round", round); writer.writeAttribute(options.shortAttributes ? "tu" : "turn", turn); if (!options.skipVersion) { writer.writeAttribute("ver", serialVersionUID); } writer.startElement(options.shortAttributes ? "rs" : "robots"); { SerializableOptions op = options; if (turn == 0) { op = new SerializableOptions(options); op.skipNames = false; } for (IRobotSnapshot r : robots) { final RobotSnapshot rs = (RobotSnapshot) r; if (!options.skipExploded || rs.getState() != RobotState.DEAD) { rs.writeXml(writer, op); } } } writer.endElement(); writer.startElement(options.shortAttributes ? "bs" : "bullets"); { for (IBulletSnapshot b : bullets) { final BulletSnapshot bs = (BulletSnapshot) b; final BulletState state = bs.getState(); if (!options.skipExploded || (state != BulletState.EXPLODED && state != BulletState.INACTIVE && (bs.getFrame() == 0 || state == BulletState.MOVING))) { bs.writeXml(writer, options); } } } writer.endElement(); } writer.endElement(); } /** * {@inheritDoc} */ public XmlReader.Element readXml(XmlReader reader) { return reader.expect("turn", new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { final TurnSnapshot snapshot = new TurnSnapshot(); reader.expect("turn", new XmlReader.Attribute() { public void read(String value) { snapshot.turn = Integer.parseInt(value); } }); reader.expect("round", new XmlReader.Attribute() { public void read(String value) { snapshot.round = Integer.parseInt(value); } }); reader.expect("robots", new XmlReader.ListElement() { public IXmlSerializable read(XmlReader reader) { snapshot.robots = new ArrayList<IRobotSnapshot>(); // prototype return new RobotSnapshot(); } public void add(IXmlSerializable child) { snapshot.robots.add((RobotSnapshot) child); } public void close() {} }); reader.expect("bullets", new XmlReader.ListElement() { public IXmlSerializable read(XmlReader reader) { snapshot.bullets = new ArrayList<IBulletSnapshot>(); // prototype return new BulletSnapshot(); } public void add(IXmlSerializable child) { snapshot.bullets.add((BulletSnapshot) child); } public void close() {} }); return snapshot; } }); } }