Skip to content

Commit cc84940

Browse files
committed
Merge branch 'jpn/feat-sdk-execution-time' into 'master'
[FEAT][SDK] enable access to Player bot execution time See merge request codingame/game-engine!330
2 parents 5e682ae + b4e6d2f commit cc84940

File tree

8 files changed

+78
-10
lines changed

8 files changed

+78
-10
lines changed

engine/core/src/main/java/com/codingame/gameengine/core/AbstractPlayer.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public static class TimeoutException extends Exception {
3131
private int score;
3232
private boolean hasBeenExecuted;
3333
private boolean hasNeverBeenExecuted = true;
34+
private long lastExecutionTimeMs = -1;
3435

3536
/**
3637
* Returns a string that will be converted into the real nickname by the viewer.
@@ -174,4 +175,12 @@ final void setHasBeenExecuted(boolean hasBeenExecuted) {
174175
final boolean hasNeverBeenExecuted() {
175176
return hasNeverBeenExecuted;
176177
}
178+
179+
final public void setLastExecutionTimeMs(long ms) {
180+
this.lastExecutionTimeMs = ms;
181+
}
182+
183+
public long getLastExectionTimeMs() {
184+
return lastExecutionTimeMs;
185+
}
177186
}

engine/core/src/main/java/com/codingame/gameengine/core/GameManager.java

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ abstract public class GameManager<T extends AbstractPlayer> {
7575
private int totalTurnTime = 0;
7676

7777
private boolean viewWarning, summaryWarning;
78+
private boolean monitoringRequested;
7879

7980
/**
8081
* GameManager main loop.
@@ -110,6 +111,7 @@ void start(InputStream is, PrintStream out) {
110111

111112
referee.init();
112113
registeredModules.forEach(Module::onGameInit);
114+
monitoringRequested = false;
113115
initDone = true;
114116

115117
// Game Loop ----------------------------------------------------------
@@ -186,6 +188,9 @@ protected void execute(T player, int nbrOutputLines) {
186188
}
187189

188190
dumpView();
191+
if (!monitoringRequested) {
192+
requestMonitoring();
193+
}
189194
dumpInfos();
190195
dumpNextPlayerInput(player.getInputs().toArray(new String[0]));
191196
if (nbrOutputLines > 0) {
@@ -196,8 +201,16 @@ protected void execute(T player, int nbrOutputLines) {
196201
// READ PLAYER OUTPUTS
197202
iCmd = InputCommand.parse(s.nextLine());
198203
if (iCmd.cmd == InputCommand.Command.SET_PLAYER_OUTPUT) {
199-
List<String> output = new ArrayList<>(iCmd.lineCount);
200-
for (int i = 0; i < iCmd.lineCount; i++) {
204+
int lineCount = iCmd.lineCount;
205+
List<String> output = new ArrayList<>(lineCount);
206+
207+
if (monitoringRequested) {
208+
String exectionTime = s.nextLine();
209+
long ms = Long.valueOf(exectionTime);
210+
player.setLastExecutionTimeMs(ms);
211+
lineCount--;
212+
}
213+
for (int i = 0; i < lineCount; i++) {
201214
output.add(s.nextLine());
202215
}
203216
player.setOutputs(output);
@@ -216,6 +229,13 @@ protected void execute(T player, int nbrOutputLines) {
216229
}
217230
}
218231

232+
private void requestMonitoring() {
233+
OutputData data = new OutputData(OutputCommand.MONITORING);
234+
out.println(data);
235+
log.info(data);
236+
monitoringRequested = true;
237+
}
238+
219239
/**
220240
* Executes a player for a maximum of turnMaxTime milliseconds and store the output. Used by player.execute().
221241
*
@@ -363,7 +383,7 @@ boolean getOuputsRead() {
363383
/**
364384
* Puts a new metadata that will be included in the game's <code>GameResult</code>.
365385
* <p>
366-
* Can be used for:
386+
* Can be used for:
367387
* </p>
368388
* <ul>
369389
* <li>Setting the value of an optimization criteria for OPTI games, used by the CodinGame IDE</li>
@@ -461,7 +481,7 @@ public void setTurnMaxTime(int turnMaxTime) throws IllegalArgumentException {
461481
}
462482
this.turnMaxTime = turnMaxTime;
463483
}
464-
484+
465485
/**
466486
* Set the timeout delay of the first turn for every player. Default is 1000ms.
467487
*
@@ -487,7 +507,7 @@ public void setFirstTurnMaxTime(int firstTurnMaxTime) throws IllegalArgumentExce
487507
public int getTurnMaxTime() {
488508
return turnMaxTime;
489509
}
490-
510+
491511
/**
492512
* Get the timeout delay of the first turn for every player.
493513
*

engine/core/src/main/java/com/codingame/gameengine/core/OutputCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.codingame.gameengine.core;
22
enum OutputCommand {
3-
VIEW, INFOS, NEXT_PLAYER_INPUT, NEXT_PLAYER_INFO, SCORES, UINPUT, TOOLTIP, SUMMARY, METADATA, FAIL;
3+
VIEW, INFOS, NEXT_PLAYER_INPUT, NEXT_PLAYER_INFO, SCORES, UINPUT, TOOLTIP, SUMMARY, METADATA, FAIL, MONITORING;
44
public String format(int lineCount) {
55
return String.format("[[%s] %d]", this.name(), lineCount);
66
}

playground/misc/misc-3-release-notes.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
The CodinGame SDK is regularly updated and improved. This document lets you know what changed in the latest releases.
44

5+
## Next Release
6+
7+
### 🎁 Features
8+
9+
- Added a method to Player to get execution time for current frame.
10+
511
## 4.5.0
612

713
### 🎁 Features

runner/src/main/java/com/codingame/gameengine/runner/Agent.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ abstract class Agent {
2828
private String nickname;
2929
private String avatar;
3030

31+
public long lastExecutionTimeMs;
3132
public Agent() {
3233
}
3334

@@ -44,6 +45,7 @@ public Agent() {
4445
* Global configuration
4546
*/
4647
public void initialize(Properties conf) {
48+
this.lastExecutionTimeMs = 0;
4749
}
4850

4951
/**

runner/src/main/java/com/codingame/gameengine/runner/Command.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ static enum OutputCommand implements CommandKey {
1515
}
1616

1717
static enum InputCommand implements CommandKey {
18-
VIEW, INFOS, NEXT_PLAYER_INPUT, NEXT_PLAYER_INFO, SCORES, UINPUT, TOOLTIP, SUMMARY, METADATA, FAIL;
18+
VIEW, INFOS, NEXT_PLAYER_INPUT, NEXT_PLAYER_INFO, SCORES, UINPUT, TOOLTIP, SUMMARY, METADATA, FAIL, MONITORING;
1919
}
2020

2121
private List<String> lines;

runner/src/main/java/com/codingame/gameengine/runner/GameRunner.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ abstract class GameRunner {
4646

4747
private String[] avatars = new String[] { "16085734516701", "16085846089817", "16085713250612", "16085756802960", "16085746254929",
4848
"16085763837151", "16085720641630", "16085834521247" };
49+
private boolean monitoringRequested;
4950

5051
private static enum OutputResult {
5152
OK, TIMEOUT, TOOLONG, TOOSHORT
@@ -86,6 +87,7 @@ private void initialize(Properties conf) {
8687
agent.name = player.getNickname() != null ? player.getNickname() : "Player " + i;
8788
gameResult.agents.add(agent);
8889
}
90+
monitoringRequested = false;
8991
}
9092

9193
private void bootstrapPlayers() {
@@ -127,6 +129,10 @@ private void runAgents() {
127129
GameTurnInfo turnInfo = readGameInfo(round);
128130
boolean validTurn = turnInfo.isComplete();
129131

132+
if (turnInfo.requestedMonitoring()) {
133+
monitoringRequested = true;
134+
}
135+
130136
gameResult.failCause = turnInfo.get(InputCommand.FAIL).orElse(null);
131137

132138
if (validTurn) {
@@ -139,6 +145,7 @@ private void runAgents() {
139145
NextPlayerInfo nextPlayerInfo = new NextPlayerInfo(
140146
turnInfo.get(InputCommand.NEXT_PLAYER_INFO).orElse(null)
141147
);
148+
142149
String nextPlayerOutput = getNextPlayerOutput(
143150
nextPlayerInfo,
144151
turnInfo.get(InputCommand.NEXT_PLAYER_INPUT).orElse(null)
@@ -152,7 +159,8 @@ private void runAgents() {
152159
log.info("\t=== Read from player");
153160
log.info(nextPlayerOutput);
154161
log.info("\t=== End Player");
155-
sendPlayerOutput(nextPlayerOutput, nextPlayerInfo.nbLinesNextOutput);
162+
Agent player = players.get(nextPlayerInfo.nextPlayer);
163+
sendPlayerOutput(nextPlayerOutput, nextPlayerInfo.nbLinesNextOutput, player);
156164
} else {
157165
sendTimeOut();
158166
}
@@ -244,10 +252,25 @@ private void readError(Agent agent) {
244252
}
245253
}
246254

247-
private void sendPlayerOutput(String output, int nbLines) {
255+
private void sendPlayerOutput(String output, int nbLines, Agent player) {
248256
String[] lines = output.split("(\\n|\\r\\n)", -1);
257+
258+
if (monitoringRequested) {
259+
long time = player.lastExecutionTimeMs;
260+
lines = unshiftIntoArray(String.valueOf(time), lines, nbLines);
261+
nbLines++;
262+
}
263+
249264
Command command = new Command(OutputCommand.SET_PLAYER_OUTPUT, Arrays.copyOfRange(lines, 0, nbLines));
250265
referee.sendInput(command.toString());
266+
log.info(command.toString());
267+
}
268+
269+
private String[] unshiftIntoArray(String string, String[] lines, int length) {
270+
String[] newLines = new String[length + 1];
271+
newLines[0] = string;
272+
System.arraycopy(lines, 0, newLines, 1, length);
273+
return newLines;
251274
}
252275

253276
private void sendTimeOut() {
@@ -260,9 +283,13 @@ private String getNextPlayerOutput(NextPlayerInfo nextPlayerInfo, String nextPla
260283

261284
// Send player input to input queue
262285
queues.get(nextPlayerInfo.nextPlayer).offer(nextPlayerInput);
263-
286+
long start = System.nanoTime();
264287
// Wait for player output then read error
265288
String playerOutput = player.getOutput(nextPlayerInfo.nbLinesNextOutput, nextPlayerInfo.timeout);
289+
long end = System.nanoTime();
290+
291+
player.lastExecutionTimeMs = (end - start) / 1_000_000;
292+
266293
if (playerOutput != null)
267294
playerOutput = playerOutput.replace('\r', '\n');
268295

runner/src/main/java/com/codingame/gameengine/runner/GameTurnInfo.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,8 @@ public Optional<String> get(CommandKey key) {
6060
}
6161
return Optional.of(lines.get(0));
6262
}
63+
64+
public boolean requestedMonitoring() {
65+
return received.containsKey(InputCommand.MONITORING);
66+
}
6367
}

0 commit comments

Comments
 (0)