mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2025-02-06 20:29:10 +01:00
DroidFish: Time control information is now stored in pgn header data.
This commit is contained in:
parent
da625e085d
commit
26ac3b6ab5
|
@ -53,6 +53,7 @@ import org.petero.droidfish.gamelogic.Position;
|
|||
import org.petero.droidfish.gamelogic.TextIO;
|
||||
import org.petero.droidfish.gamelogic.PgnToken;
|
||||
import org.petero.droidfish.gamelogic.GameTree.Node;
|
||||
import org.petero.droidfish.gamelogic.TimeControlData;
|
||||
import org.petero.droidfish.gtb.Probe;
|
||||
|
||||
import com.larvalabs.svgandroid.SVG;
|
||||
|
@ -166,6 +167,7 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
private int maxNumArrows;
|
||||
private GameMode gameMode;
|
||||
private boolean mPonderMode;
|
||||
private TimeControlData tcData = new TimeControlData();
|
||||
private int mEngineThreads;
|
||||
private String playerName;
|
||||
private boolean boardFlipped;
|
||||
|
@ -405,18 +407,21 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
ctrl = new DroidChessController(this, gameTextListener, pgnOptions);
|
||||
egtbForceReload = true;
|
||||
readPrefs();
|
||||
ctrl.newGame(gameMode);
|
||||
ctrl.newGame(gameMode, tcData);
|
||||
{
|
||||
byte[] data = null;
|
||||
int version = 1;
|
||||
if (savedInstanceState != null) {
|
||||
data = savedInstanceState.getByteArray("gameState");
|
||||
version = savedInstanceState.getInt("gameStateVersion", version);
|
||||
} else {
|
||||
String dataStr = settings.getString("gameState", null);
|
||||
version = settings.getInt("gameStateVersion", version);
|
||||
if (dataStr != null)
|
||||
data = strToByteArr(dataStr);
|
||||
}
|
||||
if (data != null)
|
||||
ctrl.fromByteArray(data);
|
||||
ctrl.fromByteArray(data, version);
|
||||
}
|
||||
ctrl.setGuiPaused(true);
|
||||
ctrl.setGuiPaused(false);
|
||||
|
@ -813,6 +818,7 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
if (ctrl != null) {
|
||||
byte[] data = ctrl.toByteArray();
|
||||
outState.putByteArray("gameState", data);
|
||||
outState.putInt("gameStateVersion", 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -835,6 +841,7 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
Editor editor = settings.edit();
|
||||
String dataStr = byteArrToString(data);
|
||||
editor.putString("gameState", dataStr);
|
||||
editor.putInt("gameStateVersion", 2);
|
||||
editor.commit();
|
||||
}
|
||||
lastVisibleMillis = System.currentTimeMillis();
|
||||
|
@ -892,7 +899,7 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
int timeControl = getIntSetting("timeControl", 120000);
|
||||
int movesPerSession = getIntSetting("movesPerSession", 60);
|
||||
int timeIncrement = getIntSetting("timeIncrement", 0);
|
||||
ctrl.setTimeLimit(timeControl, movesPerSession, timeIncrement);
|
||||
tcData.setTimeControl(timeControl, movesPerSession, timeIncrement);
|
||||
updateTimeControlTitle();
|
||||
|
||||
boardGestures = settings.getBoolean("boardGestures", true);
|
||||
|
@ -1654,7 +1661,7 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
gameMode = new GameMode(gameModeType);
|
||||
}
|
||||
// savePGNToFile(".autosave.pgn", true);
|
||||
ctrl.newGame(gameMode);
|
||||
ctrl.newGame(gameMode, tcData);
|
||||
ctrl.startGame();
|
||||
setBoardFlip(true);
|
||||
updateEngineTitle();
|
||||
|
|
|
@ -34,7 +34,6 @@ import org.petero.droidfish.engine.DroidComputerPlayer.SearchRequest;
|
|||
import org.petero.droidfish.engine.DroidComputerPlayer.SearchType;
|
||||
import org.petero.droidfish.gamelogic.Game.GameState;
|
||||
import org.petero.droidfish.gamelogic.GameTree.Node;
|
||||
import org.petero.droidfish.gamelogic.TimeControlData.TimeControlField;
|
||||
|
||||
/**
|
||||
* The glue between the chess engine and the GUI.
|
||||
|
@ -55,8 +54,6 @@ public class DroidChessController {
|
|||
private int strength = 1000;
|
||||
private int numPV = 1;
|
||||
|
||||
private TimeControlData tcData;
|
||||
|
||||
private SearchListener listener;
|
||||
private boolean guiPaused = false;
|
||||
|
||||
|
@ -71,13 +68,12 @@ public class DroidChessController {
|
|||
this.gameTextListener = gameTextListener;
|
||||
gameMode = new GameMode(GameMode.TWO_PLAYERS);
|
||||
pgnOptions = options;
|
||||
tcData = new TimeControlData();
|
||||
listener = new SearchListener();
|
||||
searchId = 0;
|
||||
}
|
||||
|
||||
/** Start a new game. */
|
||||
public final synchronized void newGame(GameMode gameMode) {
|
||||
public final synchronized void newGame(GameMode gameMode, TimeControlData tcData) {
|
||||
boolean updateGui = abortSearch();
|
||||
if (updateGui)
|
||||
updateGUI();
|
||||
|
@ -103,23 +99,11 @@ public class DroidChessController {
|
|||
updateGameMode();
|
||||
}
|
||||
|
||||
/** Set time control parameters. */
|
||||
public final synchronized void setTimeLimit(int time, int moves, int inc) {
|
||||
tcData.setTimeControl(time, moves, inc);
|
||||
if (game != null)
|
||||
game.timeController.setTimeControl(tcData);
|
||||
}
|
||||
|
||||
/** @return Array containing time control, moves per session and time increment. */
|
||||
public final int[] getTimeLimit() {
|
||||
if (game != null)
|
||||
return game.timeController.getTimeLimit(game.currPos().whiteMove);
|
||||
int[] ret = new int[3];
|
||||
TimeControlField tc = tcData.getTC(true).get(0);
|
||||
ret[0] = (int)tc.timeControl;
|
||||
ret[1] = tc.movesPerSession;
|
||||
ret[2] = (int)tc.increment;
|
||||
return ret;
|
||||
return new int[]{5*60*1000, 60, 0};
|
||||
}
|
||||
|
||||
/** The chess clocks are stopped when the GUI is paused. */
|
||||
|
@ -214,8 +198,8 @@ public class DroidChessController {
|
|||
}
|
||||
|
||||
/** De-serialize from byte array. */
|
||||
public final synchronized void fromByteArray(byte[] data) {
|
||||
game.fromByteArray(data);
|
||||
public final synchronized void fromByteArray(byte[] data, int version) {
|
||||
game.fromByteArray(data, version);
|
||||
game.tree.translateMoves();
|
||||
}
|
||||
|
||||
|
@ -236,7 +220,7 @@ public class DroidChessController {
|
|||
|
||||
/** Parse a string as FEN or PGN data. */
|
||||
public final synchronized void setFENOrPGN(String fenPgn) throws ChessParseError {
|
||||
Game newGame = new Game(gameTextListener, tcData);
|
||||
Game newGame = new Game(gameTextListener, game.timeController.tcData);
|
||||
try {
|
||||
Position pos = TextIO.readFEN(fenPgn);
|
||||
newGame.setPos(pos);
|
||||
|
|
|
@ -40,16 +40,16 @@ public class Game {
|
|||
|
||||
public Game(PgnToken.PgnTokenReceiver gameTextListener, TimeControlData tcData) {
|
||||
this.gameTextListener = gameTextListener;
|
||||
tree = new GameTree(gameTextListener);
|
||||
timeController = new TimeControl();
|
||||
timeController.setTimeControl(tcData);
|
||||
gamePaused = false;
|
||||
newGame();
|
||||
tree.setTimeControlData(tcData);
|
||||
}
|
||||
|
||||
/** De-serialize from byte array. */
|
||||
final void fromByteArray(byte[] data) {
|
||||
tree.fromByteArray(data);
|
||||
final void fromByteArray(byte[] data, int version) {
|
||||
tree.fromByteArray(data, version);
|
||||
updateTimeControl(true);
|
||||
}
|
||||
|
||||
|
@ -83,8 +83,12 @@ public class Game {
|
|||
|
||||
final boolean readPGN(String pgn, PGNOptions options) throws ChessParseError {
|
||||
boolean ret = tree.readPGN(pgn, options);
|
||||
if (ret)
|
||||
updateTimeControl(false);
|
||||
if (ret) {
|
||||
TimeControlData tcData = tree.getTimeControlData();
|
||||
if (tcData != null)
|
||||
timeController.setTimeControl(tcData);
|
||||
updateTimeControl(tcData != null);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,11 +28,13 @@ import java.util.Calendar;
|
|||
import java.util.Collections;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.petero.droidfish.PGNOptions;
|
||||
import org.petero.droidfish.gamelogic.Game.GameState;
|
||||
import org.petero.droidfish.gamelogic.TimeControlData.TimeControlField;
|
||||
|
||||
public class GameTree {
|
||||
// Data from the seven tag roster (STR) part of the PGN standard
|
||||
|
@ -40,7 +42,7 @@ public class GameTree {
|
|||
// Result is the last tag pair in the STR, but it is computed on demand from the game tree.
|
||||
|
||||
Position startPos;
|
||||
private String timeControl;
|
||||
private String timeControl, whiteTimeControl, blackTimeControl;
|
||||
|
||||
// Non-standard tags
|
||||
static private final class TagPair {
|
||||
|
@ -88,6 +90,8 @@ public class GameTree {
|
|||
black = "?";
|
||||
startPos = pos;
|
||||
timeControl = "?";
|
||||
whiteTimeControl = "?";
|
||||
blackTimeControl = "?";
|
||||
tagPairs = new ArrayList<TagPair>();
|
||||
rootNode = new Node();
|
||||
currentNode = rootNode;
|
||||
|
@ -308,6 +312,10 @@ public class GameTree {
|
|||
}
|
||||
if (!timeControl.equals("?"))
|
||||
addTagPair(out, "TimeControl", timeControl);
|
||||
if (!whiteTimeControl.equals("?"))
|
||||
addTagPair(out, "WhiteTimeControl", whiteTimeControl);
|
||||
if (!blackTimeControl.equals("?"))
|
||||
addTagPair(out, "BlackTimeControl", blackTimeControl);
|
||||
|
||||
// Write other non-standard tag pairs
|
||||
for (int i = 0; i < tagPairs.size(); i++)
|
||||
|
@ -559,6 +567,10 @@ public class GameTree {
|
|||
result = val;
|
||||
} else if (name.equals("TimeControl")) {
|
||||
timeControl = val;
|
||||
} else if (name.equals("WhiteTimeControl")) {
|
||||
whiteTimeControl = val;
|
||||
} else if (name.equals("BlackTimeControl")) {
|
||||
blackTimeControl = val;
|
||||
} else {
|
||||
this.tagPairs.add(tagPairs.get(i));
|
||||
}
|
||||
|
@ -614,6 +626,8 @@ public class GameTree {
|
|||
dos.writeUTF(black);
|
||||
dos.writeUTF(TextIO.toFEN(startPos));
|
||||
dos.writeUTF(timeControl);
|
||||
dos.writeUTF(whiteTimeControl);
|
||||
dos.writeUTF(blackTimeControl);
|
||||
int nTags = tagPairs.size();
|
||||
dos.writeInt(nTags);
|
||||
for (int i = 0; i < nTags; i++) {
|
||||
|
@ -637,7 +651,7 @@ public class GameTree {
|
|||
}
|
||||
|
||||
/** De-serialize from byte array. */
|
||||
public final void fromByteArray(byte[] data) {
|
||||
public final void fromByteArray(byte[] data, int version) {
|
||||
try {
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
DataInputStream dis = new DataInputStream(bais);
|
||||
|
@ -650,6 +664,13 @@ public class GameTree {
|
|||
startPos = TextIO.readFEN(dis.readUTF());
|
||||
currentPos = new Position(startPos);
|
||||
timeControl = dis.readUTF();
|
||||
if (version >= 2) {
|
||||
whiteTimeControl = dis.readUTF();
|
||||
blackTimeControl = dis.readUTF();
|
||||
} else {
|
||||
whiteTimeControl = "?";
|
||||
blackTimeControl = "?";
|
||||
}
|
||||
int nTags = dis.readInt();
|
||||
tagPairs.clear();
|
||||
for (int i = 0; i < nTags; i++) {
|
||||
|
@ -1516,9 +1537,118 @@ public class GameTree {
|
|||
headers.put("Round", round);
|
||||
headers.put("White", white);
|
||||
headers.put("Black", black);
|
||||
if (!timeControl.equals("?"))
|
||||
headers.put("TimeControl", timeControl);
|
||||
if (!whiteTimeControl.equals("?"))
|
||||
headers.put("WhiteTimeControl", whiteTimeControl);
|
||||
if (!blackTimeControl.equals("?"))
|
||||
headers.put("BlackTimeControl", blackTimeControl);
|
||||
for (int i = 0; i < tagPairs.size(); i++) {
|
||||
TagPair tp = tagPairs.get(i);
|
||||
headers.put(tp.tagName, tp.tagValue);
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<TimeControlField> stringToTCFields(String tcStr) {
|
||||
String[] fields = tcStr.split(":");
|
||||
int nf = fields.length;
|
||||
ArrayList<TimeControlField> ret = new ArrayList<TimeControlField>(nf);
|
||||
for (int i = 0; i < nf; i++) {
|
||||
String f = fields[i].trim();
|
||||
if (f.equals("?") || f.equals("-") || f.contains("*")) {
|
||||
// Not supported
|
||||
} else {
|
||||
try {
|
||||
int moves = 0;
|
||||
int time = 0;
|
||||
int inc = 0;
|
||||
int idx = f.indexOf('/');
|
||||
if (idx > 0)
|
||||
moves = Integer.parseInt(f.substring(0, idx).trim());
|
||||
if (idx >= 0)
|
||||
f = f.substring(idx+1);
|
||||
idx = f.indexOf('+');
|
||||
if (idx >= 0) {
|
||||
if (idx > 0)
|
||||
time = (int)(Double.parseDouble(f.substring(0, idx).trim())*1e3);
|
||||
if (idx >= 0)
|
||||
f = f.substring(idx+1);
|
||||
inc = (int)(Double.parseDouble(f.trim())*1e3);
|
||||
} else {
|
||||
time = (int)(Double.parseDouble(f.trim())*1e3);
|
||||
}
|
||||
ret.add(new TimeControlField(time, moves, inc));
|
||||
} catch (NumberFormatException ex) {
|
||||
// Invalid syntax, ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private String tcFieldsToString(ArrayList<TimeControlField> tcFields) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int nf = tcFields.size();
|
||||
for (int i = 0; i < nf; i++) {
|
||||
if (i > 0)
|
||||
sb.append(':');
|
||||
TimeControlField t = tcFields.get(i);
|
||||
if (t.movesPerSession > 0) {
|
||||
sb.append(t.movesPerSession);
|
||||
sb.append('/');
|
||||
}
|
||||
sb.append(t.timeControl / 1000);
|
||||
int ms = (int)t.timeControl % 1000;
|
||||
if (ms > 0) {
|
||||
sb.append('.');
|
||||
sb.append(String.format(Locale.US, "%03d", ms));
|
||||
}
|
||||
if (t.increment > 0) {
|
||||
sb.append('+');
|
||||
sb.append(t.increment / 1000);
|
||||
ms = (int)t.increment % 1000;
|
||||
if (ms > 0) {
|
||||
sb.append('.');
|
||||
sb.append(String.format(Locale.US, "%03d", ms));
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/** Get time control data, or null if not present. */
|
||||
public TimeControlData getTimeControlData() {
|
||||
if (!whiteTimeControl.equals("?") && !blackTimeControl.equals("?")) {
|
||||
ArrayList<TimeControlField> tcW = stringToTCFields(whiteTimeControl);
|
||||
ArrayList<TimeControlField> tcB = stringToTCFields(blackTimeControl);
|
||||
if (!tcW.isEmpty() && !tcB.isEmpty()) {
|
||||
TimeControlData tcData = new TimeControlData();
|
||||
tcData.tcW = tcW;
|
||||
tcData.tcB = tcB;
|
||||
return tcData;
|
||||
}
|
||||
}
|
||||
if (!timeControl.equals("?")) {
|
||||
ArrayList<TimeControlField> tc = stringToTCFields(timeControl);
|
||||
if (!tc.isEmpty()) {
|
||||
TimeControlData tcData = new TimeControlData();
|
||||
tcData.tcW = tc;
|
||||
tcData.tcB = tc;
|
||||
return tcData;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setTimeControlData(TimeControlData tcData) {
|
||||
if (tcData.isSymmetric()) {
|
||||
timeControl = tcFieldsToString(tcData.tcW);
|
||||
whiteTimeControl = "?";
|
||||
blackTimeControl = "?";
|
||||
} else {
|
||||
whiteTimeControl = tcFieldsToString(tcData.tcW);
|
||||
blackTimeControl = tcFieldsToString(tcData.tcB);
|
||||
timeControl = "?";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import org.petero.droidfish.gamelogic.TimeControlData.TimeControlField;
|
|||
|
||||
/** Keep track of time control information for both players. */
|
||||
public class TimeControl {
|
||||
private TimeControlData tcData;
|
||||
TimeControlData tcData;
|
||||
|
||||
private long whiteBaseTime; // Current remaining time, or remaining time when clock started
|
||||
private long blackBaseTime; // Current remaining time, or remaining time when clock started
|
||||
|
|
|
@ -4,9 +4,9 @@ import java.util.ArrayList;
|
|||
|
||||
public final class TimeControlData {
|
||||
public static final class TimeControlField {
|
||||
long timeControl;
|
||||
long timeControl; // Time in milliseconds
|
||||
int movesPerSession;
|
||||
long increment;
|
||||
long increment; // Increment in milliseconds
|
||||
|
||||
public TimeControlField(long time, int moves, long inc) {
|
||||
timeControl = time;
|
||||
|
@ -17,13 +17,15 @@ public final class TimeControlData {
|
|||
|
||||
ArrayList<TimeControlField> tcW, tcB;
|
||||
|
||||
TimeControlData() {
|
||||
/** Constructor. Set a default time control. */
|
||||
public TimeControlData() {
|
||||
tcW = new ArrayList<TimeControlField>();
|
||||
tcW.add(new TimeControlField(5*60*1000, 60, 0));
|
||||
tcB = new ArrayList<TimeControlField>();
|
||||
tcB.add(new TimeControlField(5*60*1000, 60, 0));
|
||||
}
|
||||
|
||||
/** Set a single time control for both white and black. */
|
||||
public final void setTimeControl(long time, int moves, long inc) {
|
||||
tcW = new ArrayList<TimeControlField>();
|
||||
tcW.add(new TimeControlField(time, moves, inc));
|
||||
|
@ -35,4 +37,32 @@ public final class TimeControlData {
|
|||
public ArrayList<TimeControlField> getTC(boolean whiteMove) {
|
||||
return whiteMove ? tcW : tcB;
|
||||
}
|
||||
|
||||
/** Return true if white and black time controls are equal. */
|
||||
public boolean isSymmetric() {
|
||||
return arrayEquals(tcW, tcB);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof TimeControlData))
|
||||
return false;
|
||||
TimeControlData tc2 = (TimeControlData)o;
|
||||
return arrayEquals(tcW, tc2.tcW) && arrayEquals(tcB, tc2.tcB);
|
||||
}
|
||||
|
||||
private static boolean arrayEquals(ArrayList<TimeControlField> a1,
|
||||
ArrayList<TimeControlField> a2) {
|
||||
if (a1.size() != a2.size())
|
||||
return false;
|
||||
for (int i = 0; i < a1.size(); i++) {
|
||||
TimeControlField f1 = a1.get(i);
|
||||
TimeControlField f2 = a2.get(i);
|
||||
if ((f1.timeControl != f2.timeControl) ||
|
||||
(f1.movesPerSession != f2.movesPerSession) ||
|
||||
(f1.increment != f2.increment))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.petero.droidfish.gamelogic;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
@ -28,6 +30,7 @@ import org.petero.droidfish.PGNOptions;
|
|||
import org.petero.droidfish.gamelogic.Game.GameState;
|
||||
import org.petero.droidfish.gamelogic.GameTree.Node;
|
||||
import org.petero.droidfish.gamelogic.GameTree.PgnScanner;
|
||||
import org.petero.droidfish.gamelogic.TimeControlData.TimeControlField;
|
||||
|
||||
public class GameTreeTest extends TestCase {
|
||||
|
||||
|
@ -96,7 +99,7 @@ public class GameTreeTest extends TestCase {
|
|||
|
||||
byte[] serialState = gt.toByteArray();
|
||||
gt = new GameTree(null);
|
||||
gt.fromByteArray(serialState);
|
||||
gt.fromByteArray(serialState, 2);
|
||||
assertEquals(expectedPos, gt.currentPos);
|
||||
|
||||
gt.goBack();
|
||||
|
@ -694,4 +697,90 @@ public class GameTreeTest extends TestCase {
|
|||
gt.goNode(ne4);
|
||||
assertEquals("e4* e5 Nf3 Nc6 Bb5 a6", getMoveListAsString(gt));
|
||||
}
|
||||
|
||||
public final void testTimeControl() throws ChessParseError {
|
||||
GameTree gt = new GameTree(null);
|
||||
PGNOptions options = new PGNOptions();
|
||||
|
||||
TimeControlData tcData = new TimeControlData();
|
||||
tcData.setTimeControl(180*1000, 35, 0);
|
||||
gt.setTimeControlData(tcData);
|
||||
TimeControlData tcData2 = gt.getTimeControlData();
|
||||
assertTrue(tcData2.isSymmetric());
|
||||
assertTrue(tcData.equals(tcData2));
|
||||
|
||||
Map<String,String> headers = new TreeMap<String,String>();
|
||||
gt.getHeaders(headers);
|
||||
assertEquals("35/180", headers.get("TimeControl"));
|
||||
assertEquals(null, headers.get("WhiteTimeControl"));
|
||||
assertEquals(null, headers.get("BlackTimeControl"));
|
||||
|
||||
String pgn = gt.toPGN(options);
|
||||
boolean res = gt.readPGN(pgn, options);
|
||||
assertTrue(res);
|
||||
tcData2 = gt.getTimeControlData();
|
||||
assertTrue(tcData2.isSymmetric());
|
||||
assertEquals(tcData, tcData2);
|
||||
headers = new TreeMap<String,String>();
|
||||
gt.getHeaders(headers);
|
||||
assertEquals("35/180", headers.get("TimeControl"));
|
||||
assertEquals(null, headers.get("WhiteTimeControl"));
|
||||
assertEquals(null, headers.get("BlackTimeControl"));
|
||||
|
||||
tcData = new TimeControlData();
|
||||
tcData.tcW.clear();
|
||||
tcData.tcW.add(new TimeControlField(15*60*1000,40,0));
|
||||
tcData.tcW.add(new TimeControlField(5*60*1000+345,20,0));
|
||||
tcData.tcW.add(new TimeControlField(0,10,1000));
|
||||
tcData.tcW.add(new TimeControlField(0,0,5000));
|
||||
tcData.tcB.clear();
|
||||
tcData.tcB.add(new TimeControlField(60*1000,20,3004));
|
||||
tcData.tcB.add(new TimeControlField(30*1000,0,0));
|
||||
gt.setTimeControlData(tcData);
|
||||
headers = new TreeMap<String,String>();
|
||||
gt.getHeaders(headers);
|
||||
assertEquals(null, headers.get("TimeControl"));
|
||||
assertEquals("40/900:20/300.345:10/0+1:0+5", headers.get("WhiteTimeControl"));
|
||||
assertEquals("20/60+3.004:30", headers.get("BlackTimeControl"));
|
||||
|
||||
tcData2 = gt.getTimeControlData();
|
||||
assertTrue(!tcData2.isSymmetric());
|
||||
assertEquals(tcData, tcData2);
|
||||
|
||||
pgn = gt.toPGN(options);
|
||||
res = gt.readPGN(pgn, options);
|
||||
assertTrue(res);
|
||||
tcData2 = gt.getTimeControlData();
|
||||
assertTrue(!tcData2.isSymmetric());
|
||||
assertEquals(tcData, tcData2);
|
||||
headers = new TreeMap<String,String>();
|
||||
gt.getHeaders(headers);
|
||||
assertEquals(null, headers.get("TimeControl"));
|
||||
assertEquals("40/900:20/300.345:10/0+1:0+5", headers.get("WhiteTimeControl"));
|
||||
assertEquals("20/60+3.004:30", headers.get("BlackTimeControl"));
|
||||
|
||||
tcData = new TimeControlData();
|
||||
tcData.setTimeControl(2*60*1000, 0, 12000);
|
||||
gt.setTimeControlData(tcData);
|
||||
headers = new TreeMap<String,String>();
|
||||
gt.getHeaders(headers);
|
||||
assertEquals("120+12", headers.get("TimeControl"));
|
||||
assertEquals(null, headers.get("WhiteTimeControl"));
|
||||
assertEquals(null, headers.get("BlackTimeControl"));
|
||||
|
||||
// Test pgn data with extra white space
|
||||
res = gt.readPGN("[TimeControl \" 40 / 5400 + 60 : 3.14 + 2.718 \"]", options);
|
||||
assertTrue(res);
|
||||
tcData = gt.getTimeControlData();
|
||||
assertTrue(tcData.isSymmetric());
|
||||
assertEquals(2, tcData.tcW.size());
|
||||
TimeControlField tf = tcData.tcW.get(0);
|
||||
assertEquals(40, tf.movesPerSession);
|
||||
assertEquals(5400*1000, tf.timeControl);
|
||||
assertEquals(60*1000, tf.increment);
|
||||
tf = tcData.tcW.get(1);
|
||||
assertEquals(0, tf.movesPerSession);
|
||||
assertEquals(3140, tf.timeControl);
|
||||
assertEquals(2718, tf.increment);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user