Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit tests for game state #122

Merged
merged 2 commits into from
Jul 28, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<pathelement location="test-libs/junit-4.11.jar"/>
<pathelement location="test-libs/hamcrest-core-1.3.jar"/>
<pathelement location="test-libs/mockito-all-1.9.5.jar"/>
<fileset dir="${jar.dir}" includes="deps/*.jar" />
<pathelement location="${dest.dir}"/>
</path>

Expand All @@ -52,7 +53,8 @@
<echo message=""/>
<echo message=" all clean compile"/>
<echo message=" clean Clean everything"/>
<echo message=" compile Compile all classes and create jarfile (default)"/>
<echo message=" compile Compile all classes and create jarfile"/>
<echo message=" test Compile all classes and run unit tests (default)"/>
<echo message=" launcher Create Windows scoreboard.exe"/>
<echo message=" manifest (Re)create the manifest file"/>
<echo message=" help Show this help"/>
Expand Down Expand Up @@ -164,7 +166,7 @@
</target>

<!-- Do everything -->
<target name="all" depends="clean,compile"/>
<target name="all" depends="clean,test"/>

<!-- Create Windows scoreboard.exe -->
<taskdef name="launch4j" classname="net.sf.launch4j.ant.Launch4jTask" classpath="${launch4j.dir}/launch4j.jar:${launch4j.dir}/lib/xstream.jar" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,10 @@ public static boolean ObjectsEquals(Object a, Object b) {
public static void setLogger(Logger l) { logger = l; }
public static File getDefaultPath() { return defaultPath; }
public static void setDefaultPath(File f) { defaultPath = f; }
public static void setPropertyOverride(String key, String value) { properties_overrides.put(key, value); }
public static void setPropertyOverride(String key, String value) {
properties_overrides.put(key, value);
properties.put(key, value);
}

private static Properties properties = new Properties();
private static Map<String,String> properties_overrides = new HashMap<String,String>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,11 @@ public void setTime(long ms) {
if (isRunning() && isSyncTime())
ms = ((ms / 1000) * 1000) + (time % 1000);
time = checkNewTime(ms);
scoreBoardChange(new ScoreBoardEvent(this, EVENT_TIME, new Long(time), last));
scoreBoardChange(new ScoreBoardEvent(this, EVENT_INVERTED_TIME, new Long(maximumTime) - new Long(time), maximumTime - last));
doStop = checkStop();
if (isDisplayChange(time, last)) {
scoreBoardChange(new ScoreBoardEvent(this, EVENT_TIME, new Long(time), last));
scoreBoardChange(new ScoreBoardEvent(this, EVENT_INVERTED_TIME, new Long(maximumTime) - new Long(time), maximumTime - last));
}
doStop = isTimeAtEnd();
}
if (doStop)
stop();
Expand All @@ -181,11 +183,11 @@ protected void _changeTime(long change, boolean sync) {
if (sync && isRunning() && isSyncTime())
change = ((change / 1000) * 1000);
time = checkNewTime(time + change);
if (time % 1000 == 0 || Math.abs(last - time) >= 1000) {
if (isDisplayChange(time, last)) {
scoreBoardChange(new ScoreBoardEvent(this, EVENT_TIME, new Long(time), last));
scoreBoardChange(new ScoreBoardEvent(this, EVENT_INVERTED_TIME, new Long(maximumTime) - new Long(time), maximumTime - last));
}
doStop = checkStop();
doStop = isTimeAtEnd();
}
if (doStop)
stop();
Expand All @@ -207,8 +209,13 @@ else if (ms > maximumTime && ms - maximumTime > 500)
else
return ms;
}
protected boolean checkStop() {
return (getTime() == (isCountDirectionDown() ? getMinimumTime() : getMaximumTime()));
protected boolean isDisplayChange(long current, long last) {
//on count down clocks are rounded down for display, on count up they are rounded down.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment reads oddly, and I don't understand why the directions have different logic.

if (isCountDirectionDown()) {
return ((current-1)/1000 != (last-1)/1000);
} else {
return (current/1000 != last/1000);
}
}

public long getMinimumTime() { return minimumTime; }
Expand Down Expand Up @@ -444,6 +451,7 @@ private void tick() {
}

public void run() {
if (paused) return;
long curSystemTime = System.currentTimeMillis();
long curTicks = (curSystemTime - startSystemTime) / update_interval;
while (curTicks != ticks) {
Expand All @@ -456,9 +464,23 @@ public long getCurrentTime() {
return currentTime;
}

// For unittests.
protected void advance(long time_ms) {
long curTicks = time_ms / update_interval;
while (curTicks != 0) {
curTicks--;
tick();
}
}
protected void setPaused(boolean p) {
paused = p;
}


private long currentTime = 0;
private long startSystemTime = 0;
private long ticks = 0;
private boolean paused = false;
protected static Timer timer = new Timer();
protected Object clockLock = new Object();
protected DefaultClockModel masterClock = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,9 @@ public void startOvertime() {
requestBatchStart();
ClockModel pc = getClockModel(Clock.ID_PERIOD);
ClockModel jc = getClockModel(Clock.ID_JAM);
ClockModel ic = getClockModel(Clock.ID_INTERMISSION);
ClockModel lc = getClockModel(Clock.ID_LINEUP);
ClockModel tc = getClockModel(Clock.ID_TIMEOUT);
ClockModel ic = getClockModel(Clock.ID_INTERMISSION);
if (pc.isRunning() || jc.isRunning())
return;
if (pc.getNumber() < pc.getMaximumNumber())
Expand All @@ -151,6 +152,7 @@ public void startOvertime() {
pc.setTime(1000); //TODO: Should not be needed
setInPeriod(true);
setInOvertime(true);
tc.stop();
ic.stop();
long otLineupTime = settings.getLong("Clock." + Clock.ID_LINEUP + ".OvertimeTime");
if (lc.getMaximumTime() < otLineupTime) {
Expand Down Expand Up @@ -241,14 +243,21 @@ private void _stopTimeout() {
synchronized (runLock) {
ClockModel tc = getClockModel(Clock.ID_TIMEOUT);
ClockModel lc = getClockModel(Clock.ID_LINEUP);
ClockModel pc = getClockModel(Clock.ID_PERIOD);
ClockModel ic = getClockModel(Clock.ID_INTERMISSION);
lastTimeoutOwner = getTimeoutOwner();
wasOfficialReview = isOfficialReview();
timeoutClockWasRunning = true;
jamClockWasRunning = false;

requestBatchStart();
lc.resetTime();
lc.start();
if (pc.isTimeAtEnd()) {
ic.resetTime(); //TODO: add a rule to make this optional
ic.start();
} else {
lc.resetTime();
lc.start();
}
tc.stop();
requestBatchEnd();
}
Expand All @@ -257,6 +266,7 @@ private void _startLineup() {
synchronized (runLock) {
ClockModel lc = getClockModel(Clock.ID_LINEUP);
ClockModel ic = getClockModel(Clock.ID_INTERMISSION);

ic.stop();

timeoutClockWasRunning = false;
Expand Down Expand Up @@ -286,25 +296,6 @@ public void timeout(TeamModel team, boolean review) {
}
setOfficialReview(review);

TeamModel t1 = getTeamModel("1");
TeamModel t2 = getTeamModel("2");
if (null==team) {
t1.setInTimeout(false);
t1.setInOfficialReview(false);
t2.setInTimeout(false);
t2.setInOfficialReview(false);
} else if (t1.getId().equals(team.getId())) {
t1.setInTimeout(!review);
t1.setInOfficialReview(review);
t2.setInTimeout(false);
t2.setInOfficialReview(false);
} else {
t1.setInTimeout(false);
t1.setInOfficialReview(false);
t2.setInTimeout(!review);
t2.setInOfficialReview(review);
}

if (!tc.isRunning()) {
// Make sure period clock, jam clock, and lineup clock are stopped
jamClockWasRunning = jc.isRunning();
Expand Down Expand Up @@ -458,6 +449,9 @@ public void setTimeoutOwner(String owner) {
synchronized (timeoutOwnerLock) {
String last = timeoutOwner;
timeoutOwner = owner;
for (TeamModel tm : getTeamModels()) {
tm.setInTimeout(tm.getId() == owner);
}
scoreBoardChange(new ScoreBoardEvent(this, EVENT_TIMEOUT_OWNER, timeoutOwner, last));
}
}
Expand All @@ -466,6 +460,9 @@ public void setOfficialReview(boolean official) {
synchronized (officialReviewLock) {
boolean last = officialReview;
officialReview = official;
for (TeamModel tm : getTeamModels()) {
tm.setInOfficialReview(tm.getId() == getTimeoutOwner() && official);
}
scoreBoardChange(new ScoreBoardEvent(this, EVENT_OFFICIAL_REVIEW, new Boolean(officialReview), last));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,6 @@ public void changeOfficialReviews(int c) {
public void resetTimeouts(boolean gameStart) {
setInTimeout(false);
setInOfficialReview(false);
setRetainedOfficialReview(false);
if (gameStart || timeoutsPerPeriod) {
setTimeouts(maximumTimeouts);
}
Expand Down Expand Up @@ -493,7 +492,7 @@ private void _setStarPass(boolean starPass) {
synchronized (skaterLock) {
requestBatchStart();

Boolean last = new Boolean(starPass);
Boolean last = new Boolean(this.starPass);
this.starPass = starPass;
scoreBoardChange(new ScoreBoardEvent(this, EVENT_STAR_PASS, new Boolean(starPass), last));

Expand All @@ -514,17 +513,17 @@ public void penalty(String skaterId, String penaltyId, boolean fo_exp, int perio

protected String id;
protected String name;
protected String logo;
protected int score;
protected int lastscore;
protected int timeouts;
protected int maximumTimeouts;
protected boolean timeoutsPerPeriod;
protected int officialReviews;
protected int maximumOfficialReviews;
protected boolean officialReviewsPerPeriod;
protected String leadJammer = Team.LEAD_NO_LEAD;
protected boolean starPass = false;
protected String logo = DEFAULT_LOGO;
protected int score = DEFAULT_SCORE;
protected int lastscore = DEFAULT_SCORE;
protected int timeouts = DEFAULT_TIMEOUTS;
protected int maximumTimeouts = DEFAULT_TIMEOUTS;
protected boolean timeoutsPerPeriod = DEFAULT_TIMEOUTS_PER_PERIOD;
protected int officialReviews = DEFAULT_OFFICIAL_REVIEWS;
protected int maximumOfficialReviews = DEFAULT_OFFICIAL_REVIEWS;
protected boolean officialReviewsPerPeriod = DEFAULT_REVIEWS_PER_PERIOD;
protected String leadJammer = DEFAULT_LEADJAMMER;
protected boolean starPass = DEFAULT_STARPASS;
protected boolean in_timeout = false;
protected boolean in_official_review = false;
protected boolean retained_official_review = false;
Expand Down Expand Up @@ -554,7 +553,9 @@ public void penalty(String skaterId, String penaltyId, boolean fo_exp, int perio
public static final String DEFAULT_LOGO = "";
public static final int DEFAULT_SCORE = 0;
public static final int DEFAULT_TIMEOUTS = 3;
public static final boolean DEFAULT_TIMEOUTS_PER_PERIOD = false;
public static final int DEFAULT_OFFICIAL_REVIEWS = 1;
public static final boolean DEFAULT_REVIEWS_PER_PERIOD = true;
public static final String DEFAULT_LEADJAMMER = Team.LEAD_NO_LEAD;
public static final boolean DEFAULT_STARPASS = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,28 @@ public void addScoreBoardEvent(ScoreBoardEventProvider p, ScoreBoardEvent e) {
}
}

// For unitests.
protected void waitForEvents() {
while (true) {
boolean empty = true;
synchronized (mapLock) {
for(Queue<ManagerRunnable> q: getSingleton().providerMap.values()) {
for(ManagerRunnable mr : q) {
if (!mr.isEmpty()) {
empty = false;
}
}
}
}
if (empty) {
break;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {};
}
}

protected Object mapLock = new Object();
protected Hashtable<ScoreBoardEventProvider, Queue<ManagerRunnable>> providerMap = new Hashtable<ScoreBoardEventProvider, Queue<ManagerRunnable>>();
protected Hashtable<ScoreBoardListener, ManagerRunnable> listenerMap = new Hashtable<ScoreBoardListener, ManagerRunnable>();
Expand All @@ -97,15 +119,20 @@ public void run() {
ScoreBoardEvent event;

synchronized (eventLock) {
if (null == (event = eventQueue.poll()))
if (null == (event = eventQueue.poll())) {
try { eventLock.wait(); }
catch ( Exception e ) { }
}
inProgress = true;
}

if (null != event) {
try { listener.scoreBoardChange(event); }
catch ( RuntimeException rE ) { /* Keep delivering events regardless of Exceptions in a listener's handler */ }
}
synchronized (eventLock) {
inProgress = false;
}
}
}

Expand All @@ -129,10 +156,17 @@ private void providerCountDec() {
}
}

protected boolean isEmpty() {
synchronized (eventLock) {
return eventQueue.size() == 0 && !inProgress;
}
}

protected Object eventLock = new Object();
protected Queue<ScoreBoardEvent> eventQueue = new LinkedList<ScoreBoardEvent>();

protected ScoreBoardListener listener;
protected int providerCount = 0;
protected boolean inProgress = false;
}
}
Loading