Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,16 @@ public static class TimeoutException extends Exception {
private List<String> inputs = new ArrayList<>();
private List<String> outputs;
private boolean timeout;
private int timelimit;
private int score;
private boolean hasBeenExecuted;
private boolean hasNeverBeenExecuted = true;
private long lastExecutionTimeMs = -1;
private int timelimitsExceeded = 0;
private boolean useTimebank = false;
private int timebank = 0;
private boolean timelimitExceededLastTurn = false;
private final int MAX_SOFT_TIMELIMIT_EXCEEDS = 2;

/**
* Returns a string that will be converted into the real nickname by the viewer.
Expand Down Expand Up @@ -79,6 +85,65 @@ void setScore(int score) {
this.score = score;
}

/**
* Set the player's time limit for the next turn
*
* @param timelimit
* The time limit in milliseconds
*/
void setTimelimit(int timelimit) {
this.timelimit = timelimit;
}

/**
* Set the player's timebank for the whole game
*
* @param timebank
* the timebank in milliseconds
*/
void setTimebank(int timebank) {
this.useTimebank = true;
this.timebank = timebank;
}

/**
* Get the remaining timebank
*
* @return the remaining timebank in milliseconds
*/
public int getRemainingTimebank() {
return timebank;
}

/**
* Get the execution time of the last successful execution
* Will still return the previous value in case of a timeout
*
* @return The execution time of the last execution in milliseconds
*/
public long getLastExectionTimeMs() {
return lastExecutionTimeMs;
}

/**
* Get how often the player has already exceeded the time limit in this game
*
* @return how often the player has already exceeded the time limit in this game
*/
public int getTimelimitsExceeded() {
return timelimitsExceeded;
}

/**
* Get whether the player exceeded the time limit in the last turn
*
* @return true, if the player exceeded the time limit in the last turn
*/
public boolean hasTimelimitExceededLastTurn() {
return timelimitExceededLastTurn;
}


/**
* Adds a new line to the input to send to the player on execute.
*
Expand All @@ -102,6 +167,13 @@ public final void execute() {
gameManagerProvider.get().execute(this);
this.hasBeenExecuted = true;
this.hasNeverBeenExecuted = false;
if (this.useTimebank) {
if (hasTimedOut()) this.timebank = 0;
else this.timebank -= getLastExectionTimeMs();
}
this.timelimitExceededLastTurn = getLastExectionTimeMs() > this.timelimit;
if (this.timelimitExceededLastTurn) this.timelimitsExceeded++;
if (this.timelimitsExceeded > MAX_SOFT_TIMELIMIT_EXCEEDS) this.timeout = true;
}

/**
Expand Down Expand Up @@ -179,8 +251,4 @@ final boolean hasNeverBeenExecuted() {
final public void setLastExecutionTimeMs(long ms) {
this.lastExecutionTimeMs = ms;
}

public long getLastExectionTimeMs() {
return lastExecutionTimeMs;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ abstract public class GameManager<T extends AbstractPlayer> {
private static final int GAME_DURATION_SOFT_QUOTA = 25_000;
private static final int MAX_TURN_TIME = GAME_DURATION_SOFT_QUOTA;
private static final int MIN_TURN_TIME = 50;
private static final int SOFT_TIMELIMIT_EXTRA = 50;

protected List<T> players;
private int maxTurns = 200;
Expand Down Expand Up @@ -73,6 +74,8 @@ abstract public class GameManager<T extends AbstractPlayer> {
private int totalViewDataBytesSent = 0;
private int totalGameSummaryBytes = 0;
private int totalTurnTime = 0;
private boolean useTurntime = false;
private boolean useTimebank = false;

private boolean viewWarning, summaryWarning;
private boolean monitoringRequested;
Expand Down Expand Up @@ -193,10 +196,13 @@ protected void execute(T player, int nbrOutputLines) {
}
dumpInfos();
dumpNextPlayerInput(player.getInputs().toArray(new String[0]));
if (nbrOutputLines > 0) {
if (nbrOutputLines > 0 && !useTimebank) {
addTurnTime();
}
dumpNextPlayerInfos(player.getIndex(), nbrOutputLines, player.hasNeverBeenExecuted() ? firstTurnMaxTime : turnMaxTime);
int timelimit = player.hasNeverBeenExecuted() ? firstTurnMaxTime : turnMaxTime;
if (useTimebank) timelimit = player.getRemainingTimebank();
player.setTimelimit(timelimit);
dumpNextPlayerInfos(player.getIndex(), nbrOutputLines, timelimit + (useTimebank ? 0 : SOFT_TIMELIMIT_EXTRA));

// READ PLAYER OUTPUTS
iCmd = InputCommand.parse(s.nextLine());
Expand Down Expand Up @@ -441,6 +447,29 @@ public boolean isGameEnd() {
return this.gameEnd;
}

/**
* Set the timeout delay for each player for the whole game. This will disable the time limit per turn
*
* @param timebank
* Duration in milliseconds
* @throws IllegalArgumentException
* if timebank &lt; 1000 or &gt; 30000 for all players combined
*/
public void setTimebank(int timebank) {
if (useTurntime) {
throw new UnsupportedOperationException("Use either setTimebank or setTurnMaxTime & setFirstTurnMaxTime, not both");
} else if (timebank < MIN_TURN_TIME) {
throw new IllegalArgumentException("Invalid time bank: use at least 1000ms");
} else if (timebank * players.size() > GAME_DURATION_HARD_QUOTA) {
throw new IllegalArgumentException("Invalid timebank: stay under " + GAME_DURATION_HARD_QUOTA + "ms total, " + (GAME_DURATION_HARD_QUOTA / players.size()) + " per player");
}
totalTurnTime += timebank * players.size();
this.useTimebank = true;
for (T player : players) {
player.setTimebank(timebank);
}
}

/**
* Set the maximum amount of turns. Default: 400.
*
Expand Down Expand Up @@ -474,12 +503,15 @@ public int getMaxTurns() {
* if turnMaxTime &lt; 50 or &gt; 25000
*/
public void setTurnMaxTime(int turnMaxTime) throws IllegalArgumentException {
if (turnMaxTime < MIN_TURN_TIME) {
if (useTimebank) {
throw new UnsupportedOperationException("Use either setTimebank or setTurnMaxTime & setFirstTurnMaxTime, not both");
} else if (turnMaxTime < MIN_TURN_TIME) {
throw new IllegalArgumentException("Invalid turn max time : stay above 50ms");
} else if (turnMaxTime > MAX_TURN_TIME) {
throw new IllegalArgumentException("Invalid turn max time : stay under 25s");
}
this.turnMaxTime = turnMaxTime;
this.useTurntime = true;
}

/**
Expand All @@ -491,12 +523,15 @@ public void setTurnMaxTime(int turnMaxTime) throws IllegalArgumentException {
* if firstTurnMaxTime &lt; 50 or &gt; 25000
*/
public void setFirstTurnMaxTime(int firstTurnMaxTime) throws IllegalArgumentException {
if (firstTurnMaxTime < MIN_TURN_TIME) {
if (useTurntime) {
throw new UnsupportedOperationException("Use either setTimebank or setTurnMaxTime & setFirstTurnMaxTime, not both");
} else if (firstTurnMaxTime < MIN_TURN_TIME) {
throw new IllegalArgumentException("Invalid turn max time : stay above 50ms");
} else if (firstTurnMaxTime > MAX_TURN_TIME) {
throw new IllegalArgumentException("Invalid turn max time : stay under 25s");
}
this.firstTurnMaxTime = firstTurnMaxTime;
this.useTurntime = true;
}

/**
Expand Down