Compare commits

..

No commits in common. "master" and "creeps-live-msg" have entirely different histories.

8 changed files with 84 additions and 205 deletions

View file

@ -16,15 +16,11 @@ import java.util.function.Supplier;
@NoArgsConstructor @NoArgsConstructor
public class AsyncExec<T> { public class AsyncExec<T> {
@Getter
@Setter
private static float ticksPerSecond = 1; private static float ticksPerSecond = 1;
// private CompletableFuture<T> task; // private CompletableFuture<T> task;
public static void setTicksPerSecond(float ticksPerSecond) {
AsyncExec.ticksPerSecond = ticksPerSecond;
}
public static long ticksToTime(long ticks) { public static long ticksToTime(long ticks) {
return Math.ceilDiv(ticks, (long)Math.ceil(ticksPerSecond)); return Math.ceilDiv(ticks, (long)Math.ceil(ticksPerSecond));
} }

View file

@ -1,29 +1,21 @@
package com.epita.creeps; package com.epita.creeps;
import com.epita.creeps.commands.Basics; import com.epita.creeps.commands.Basics;
import com.epita.creeps.given.extra.Cartographer;
import com.epita.creeps.given.vo.geometry.Direction; import com.epita.creeps.given.vo.geometry.Direction;
import com.epita.creeps.given.vo.geometry.Point;
import com.epita.creeps.given.vo.response.CommandResponse; import com.epita.creeps.given.vo.response.CommandResponse;
import com.epita.creeps.given.vo.response.InitResponse; import com.epita.creeps.given.vo.response.InitResponse;
import com.epita.creeps.given.vo.response.StatisticsResponse; import com.epita.creeps.units.Citizen;
import com.epita.creeps.units.*;
import kong.unirest.core.HttpResponse; import kong.unirest.core.HttpResponse;
import kong.unirest.core.JsonNode; import kong.unirest.core.JsonNode;
import kong.unirest.core.Unirest; import kong.unirest.core.Unirest;
import kong.unirest.core.UnirestException; import kong.unirest.core.UnirestException;
import lombok.Getter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class Program { public class Program {
private static String srvUrl; private static String srvUrl;
private static Logger logger; private static Logger logger;
@Getter
private static String login; private static String login;
public static void main(String[] args) { public static void main(String[] args) {
@ -61,23 +53,70 @@ public class Program {
logger.error("Cannot connect to the server. Aborting..."); logger.error("Cannot connect to the server. Aborting...");
throw e; throw e;
} }
// AsyncExec.justWait(0);
// Create account and get init infos // Create account and get init infos
logger.info("Creating account"); logger.info("Creating account");
InitResponse initResponse = Basics.connectAccount(login); InitResponse initResponse = Basics.connectAccount(login);
login = initResponse.login; // Just in case login = initResponse.login; // Just in case
AsyncExec.setTicksPerSecond((float) initResponse.setup.ticksPerSeconds); AsyncExec.setTicksPerSecond((long)initResponse.setup.ticksPerSeconds);
Citizen citizen1 = new Citizen(login, initResponse.citizen1Id, initResponse.householdCoordinates); Citizen citizen1 = new Citizen(login, initResponse.citizen1Id);
Citizen citizen2 = new Citizen(login, initResponse.citizen2Id, initResponse.householdCoordinates); Citizen citizen2 = new Citizen(login, initResponse.citizen2Id);
Unit.getUnits().add(citizen1);
Unit.getUnits().add(citizen2);
// Et voilà, machtou pichtou for(int i = 0; i < 3; i++) {
citizen1.move(Direction.RIGHT);
citizen2.move(Direction.UP);
citizen1.waitFinished();
citizen2.waitFinished();
// logger.debug("Received actions responses");
// logger.debug("citizen1.error: " + citizen1_resp.error);
// logger.debug("citizen2.error: " + citizen2_resp.error);
}
for(int i = 0; i < 3; i++) {
citizen1.move(Direction.LEFT);
citizen2.move(Direction.DOWN);
citizen1.waitFinished();
citizen2.waitFinished();
// logger.debug("Received actions responses");
// logger.debug("citizen1.error: " + citizen1_resp.error);
// logger.debug("citizen2.error: " + citizen2_resp.error);
}
logger.info("Done");
// logger.info("Done");
} }
// ### Get statistics
//GET http://localhost:1664/statistics
//
//### Get status
//GET http://localhost:1664/status
//
//### Get report
//GET http://localhost:1664/report/148997e9b
//
//### Login with user login_l
//POST http://localhost:1664/init/login_l
//
//> {%
//client.global.set("baseId", response.body.baseId);
//client.global.set("probeId", response.body.probeId);
//client.global.set("login", response.body.login);
//%}
//
//### Post noop commande
//POST http://localhost:1664/command/{{login}}/{{probeId}}/noop
//
//###
//POST http://localhost:1664/command/dumeig_a/8d87eea10/inspect
//
//###
} }

View file

@ -1,16 +1,10 @@
package com.epita.creeps.commands; package com.epita.creeps.commands;
import com.epita.creeps.AsyncExec; import com.epita.creeps.AsyncExec;
import com.epita.creeps.Program;
import com.epita.creeps.given.exception.NoReportException; import com.epita.creeps.given.exception.NoReportException;
import com.epita.creeps.given.extra.Cartographer;
import com.epita.creeps.given.json.Json; import com.epita.creeps.given.json.Json;
import com.epita.creeps.given.vo.report.*; import com.epita.creeps.given.vo.report.Report;
import com.epita.creeps.given.vo.response.InitResponse; import com.epita.creeps.given.vo.response.InitResponse;
import com.epita.creeps.given.vo.response.StatisticsResponse;
import com.epita.creeps.units.BomberBot;
import com.epita.creeps.units.Turret;
import com.epita.creeps.units.Unit;
import kong.unirest.core.HttpResponse; import kong.unirest.core.HttpResponse;
import kong.unirest.core.JsonNode; import kong.unirest.core.JsonNode;
import kong.unirest.core.Unirest; import kong.unirest.core.Unirest;
@ -29,12 +23,9 @@ import java.util.concurrent.CompletableFuture;
public class Basics { public class Basics {
private static final Logger logger = LoggerFactory.getLogger(Basics.class); private static final Logger logger = LoggerFactory.getLogger(Basics.class);
@Getter @Setter
private static String srvUrl; private static String srvUrl;
public static void setSrvUrl(String srvUrl) {
Basics.srvUrl = srvUrl;
}
public static InitResponse connectAccount(String login) { public static InitResponse connectAccount(String login) {
try { try {
CompletableFuture<HttpResponse<JsonNode>> resp = AsyncExec.asyncExec(() -> Unirest.post(srvUrl + "/init/" + login).asJson(), 0); CompletableFuture<HttpResponse<JsonNode>> resp = AsyncExec.asyncExec(() -> Unirest.post(srvUrl + "/init/" + login).asJson(), 0);
@ -52,78 +43,20 @@ public class Basics {
} }
} }
public static StatisticsResponse getStatistics() {
try {
CompletableFuture<HttpResponse<JsonNode>> resp = AsyncExec.asyncExec(() -> Unirest.get(srvUrl + "/statistics").asJson(), 0);
HttpResponse<JsonNode> response = resp.join();
return Json.parse(response.getBody().toString(), StatisticsResponse.class);
} catch (UnirestException e) {
logger.error("Cannot retrieve statistics.");
throw e;
}
}
// Asks the server for a certain report // Asks the server for a certain report
public static Report getReport (String reportId) { public static Report getReport (String reportId) {
HttpResponse<JsonNode> response = null; HttpResponse<JsonNode> response;
try { try {
response = Unirest.get(srvUrl + "/report/" + reportId).asJson(); response = Unirest.get(srvUrl + "/report/" + reportId).asJson();
// logger.debug("Got report: " + response.getBody().toPrettyString()); logger.debug("Got report: " + response.getBody().toPrettyString());
Report report = Json.parseReport(response.getBody().toString()); return Json.parseReport(response.getBody().toString());
handleReport(report);
return report;
} catch (UnirestException e) { } catch (UnirestException e) {
logger.error("Could not retrieve report"); logger.error("Could not retrieve report");
throw new RuntimeException(e); throw new RuntimeException(e);
} catch (NoReportException e) { } catch (NoReportException e) {
logger.error("Could not parse report: not a report"); logger.error("Could not parse report: not a report");
logger.debug(response.getBody().toPrettyString());
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public static void handleReport(Report report) {
Cartographer c = Cartographer.INSTANCE;
if (report.opcode.startsWith("farm")) {
c.register((FarmReport) report);
}
else if (report.opcode.startsWith("gather")) {
c.register((GatherReport) report);
}
else if (report.opcode.startsWith("move")) {
c.register((MoveReport) report);
}
else if (report.opcode.startsWith("build")) {
c.register((BuildReport) report);
}
else if (report.opcode.startsWith("observe")) {
c.register((ObserveReport) report);
}
else if (report.opcode.startsWith("spawn"))
{
SpawnReport spawnReport = (SpawnReport) report;
if (spawnReport.errorCode != null) {
logger.warn("Could not spawn unit: got report with an error: " + report.errorCode);
}
if (spawnReport.spawnedUnit.opcode.endsWith("turret")) {
Turret turret = new Turret(Program.getLogin(), spawnReport.spawnedUnitId, spawnReport.spawnedUnit.position);
Unit.getUnits().add(turret);
}
else if (spawnReport.spawnedUnit.opcode.endsWith("bomber-bot")) {
BomberBot bombhero = new BomberBot(Program.getLogin(), spawnReport.spawnedUnitId, spawnReport.spawnedUnit.position);
Unit.getUnits().add(bombhero);
}
else {
logger.warn("Spawned unit is an unknown type. Ignored...");
}
}
else if (report.opcode.startsWith("fire")) {
logger.debug("FIRREEE!!");
}
else {
logger.warn("Unknown opcode '" + report.opcode + "' in the server report. Ignored...");
}
}
} }

View file

@ -1,26 +0,0 @@
package com.epita.creeps.units;
import com.epita.creeps.given.extra.Cartographer;
import com.epita.creeps.given.json.Json;
import com.epita.creeps.given.vo.geometry.Point;
import com.epita.creeps.given.vo.parameter.FireParameter;
import java.util.List;
public class BomberBot extends Unit {
public BomberBot(String login, String id, Point position) {
super(login, id, position);
}
// Retrieves all units that are turrets
public static List<Unit> getBomberBotUnits() {
return getUnits().stream().filter(unit -> unit.getClass() == BomberBot.class).toList();
}
public BomberBot fire() {
FireParameter fp = new FireParameter(this.position);
sendActionWithBody("fire:bomber-bot", Json.serialize(fp), 2);
return this;
}
}

View file

@ -6,7 +6,6 @@ import com.epita.creeps.commands.Basics;
import com.epita.creeps.given.exception.NoReportException; import com.epita.creeps.given.exception.NoReportException;
import com.epita.creeps.given.json.Json; import com.epita.creeps.given.json.Json;
import com.epita.creeps.given.vo.geometry.Direction; import com.epita.creeps.given.vo.geometry.Direction;
import com.epita.creeps.given.vo.geometry.Point;
import com.epita.creeps.given.vo.parameter.MessageParameter; import com.epita.creeps.given.vo.parameter.MessageParameter;
import com.epita.creeps.given.vo.report.MoveReport; import com.epita.creeps.given.vo.report.MoveReport;
import com.epita.creeps.given.vo.report.Report; import com.epita.creeps.given.vo.report.Report;
@ -20,50 +19,40 @@ import java.util.concurrent.CompletableFuture;
public class Citizen extends Unit { public class Citizen extends Unit {
public Citizen(String login, String citizen_id, Point position) { public Citizen(String login, String citizen_id ) {
super(login, citizen_id, position); super(login, citizen_id);
} }
public Citizen move(Direction direction) { public void move(Direction direction) {
sendAction("move:"+direction.direction, 2); sendAction("move:"+direction.direction, 2);
return this;
} }
public Citizen observe() { public void observe() {
sendAction("observe", 1); sendAction("observe", 1);
return this;
} }
public Citizen gather() { public void gather() {
sendAction("gather", 4); sendAction("gather", 4);
return this;
} }
public Citizen unload() { public void unload() {
sendAction("unload", 3); sendAction("unload", 3);
return this;
} }
public Citizen farm() { public void farm() {
sendAction("farm", 10); sendAction("farm", 10);
return this;
} }
public Citizen build(Building building) { public void build(Building building) {
sendAction("build:" + building.name, 20); sendAction("build:" + building.name, 20);
return this;
} }
public Citizen spawn(String unit) { public void spawn(String unit) {
sendAction("spawn:" + unit, 6); sendAction("spawn:" + unit, 6);
return this;
} }
public Citizen refine(String resource) { public void refine(String resource) {
sendAction("refine:" + resource, 8); sendAction("refine:" + resource, 8);
return this;
} }
public Citizen sendMessage(String receiver, String message) { public void sendMessage(String receiver, String message) {
MessageParameter mp = new MessageParameter(receiver, message); MessageParameter mp = new MessageParameter(receiver, message);
sendActionWithBody("message:send", Json.serialize(mp), 1); sendActionWithBody("message:send", Json.serialize(mp), 1);
return this;
} }
public Citizen fetchMessages() { public void fetchMessages() {
sendAction("message:fetch", 1); sendAction("message:fetch", 1);
return this;
} }

View file

@ -1,27 +0,0 @@
package com.epita.creeps.units;
import com.epita.creeps.given.extra.Cartographer;
import com.epita.creeps.given.json.Json;
import com.epita.creeps.given.vo.geometry.Point;
import com.epita.creeps.given.vo.parameter.FireParameter;
import java.util.List;
public class Turret extends Unit {
public Turret(String login, String id, Point position) {
super(login, id, position);
}
// Retrieves all units that are turrets
public static List<Unit> getTurretUnits() {
return getUnits().stream().filter(unit -> unit.getClass() == Turret.class).toList();
}
public Turret fire(Point target) {
FireParameter fp = new FireParameter(target);
Cartographer cartographer = Cartographer.INSTANCE;
sendActionWithBody("fire:turret", Json.serialize(fp), 2);
return this;
}
}

View file

@ -4,55 +4,37 @@ import com.epita.creeps.AsyncExec;
import com.epita.creeps.ServerReponseException; import com.epita.creeps.ServerReponseException;
import com.epita.creeps.commands.Basics; import com.epita.creeps.commands.Basics;
import com.epita.creeps.given.json.Json; import com.epita.creeps.given.json.Json;
import com.epita.creeps.given.vo.geometry.Point;
import com.epita.creeps.given.vo.report.Report; import com.epita.creeps.given.vo.report.Report;
import com.epita.creeps.given.vo.response.CommandResponse; import com.epita.creeps.given.vo.response.CommandResponse;
import kong.unirest.core.HttpResponse; import kong.unirest.core.HttpResponse;
import kong.unirest.core.JsonNode; import kong.unirest.core.JsonNode;
import kong.unirest.core.Unirest; import kong.unirest.core.Unirest;
import lombok.Getter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public abstract class Unit { public abstract class Unit {
@Getter
private static final List<Unit> units = new ArrayList<>();
public static String srvUrl;
public static final Logger logger = LoggerFactory.getLogger(Unit.class);
protected final String id; protected final String id;
@Getter
protected final Point position;
protected final String command_uri; protected final String command_uri;
protected CompletableFuture<HttpResponse<JsonNode>> pendingAction; protected CompletableFuture<HttpResponse<JsonNode>> pendingAction;
protected CompletableFuture<Report> pendingReport; protected CompletableFuture<Report> pendingReport;
protected Report lastReport; public static String srvUrl;
protected boolean idle = true; public static final Logger logger = LoggerFactory.getLogger(Unit.class);
public Unit(String login, String id, Point position) { public Unit(String login, String id) {
if (srvUrl == null) { if (srvUrl == null) {
throw new RuntimeException("Tried to create a citizen without properly initializing static fields"); throw new RuntimeException("Tried to create a citizen without properly initializing static fields");
} }
this.id = id; this.id = id;
this.position = position;
command_uri = srvUrl + "/command/" + login + "/" + id + "/"; command_uri = srvUrl + "/command/" + login + "/" + id + "/";
} }
// Sends a specific action to the server using it's HTTPS string representation // Sends a specific action to the server using it's HTTPS string representation
// Sets pending action accordingly and asks for a report after `delay` ticks // Sets pending action accordingly and asks for a report after `delay` ticks
public void sendActionWithBody(String actionCode, String body, long delay) { public void sendActionWithBody(String actionCode, String body, long delay) {
if (!idle) { // Move
// logger.warn("Unit is already busy, queuing action"); pendingAction = AsyncExec.asyncExec(() -> Unirest.post(command_uri + actionCode).asJson(), delay)
this.waitFinished();
}
// Do
idle = false;
pendingAction = AsyncExec.asyncExec(() -> Unirest.post(command_uri + actionCode).body(body).asJson(), delay)
.thenApplyAsync( x -> x ); .thenApplyAsync( x -> x );
// Get report // Get report
pendingReport = getCommandReport(); pendingReport = getCommandReport();
@ -74,23 +56,18 @@ public abstract class Unit {
* @return true if action succeeded, false otherwise * @return true if action succeeded, false otherwise
*/ */
public boolean waitFinished() { public boolean waitFinished() {
if (idle) {
logger.warn("Tried to wait for an idle citizen");
return false;
}
if (pendingAction == null || pendingReport == null) { if (pendingAction == null || pendingReport == null) {
logger.warn("Tried to wait a citizen with no pending action or report"); logger.warn("Tried to wait a citizen with no pending action or report");
return false; return false;
} }
lastReport = pendingReport.join(); Report r = pendingReport.join();
if (lastReport == null) { if (r == null) {
logger.warn("Invalid report received: null value"); logger.warn("Invalid report received: null value");
return false; return false;
} }
// logger.debug("Got report: " + lastReport); logger.debug("Got report: " + r);
idle = true;
return lastReport.errorCode != null; return r.errorCode != null;
} }
@ -102,10 +79,8 @@ public abstract class Unit {
} }
return AsyncExec.thenAsyncExec(pendingAction, x -> { return AsyncExec.thenAsyncExec(pendingAction, x -> {
CommandResponse cr = Json.parse(x.getBody().toString(), CommandResponse.class); CommandResponse cr = Json.parse(x.getBody().toString(), CommandResponse.class);
if (cr.error != null) { if (cr.error != null)
logger.debug("Server reponse: " + cr.toString());
throw new ServerReponseException("Error retrieving the report id"); throw new ServerReponseException("Error retrieving the report id");
}
String reportId = cr.reportId; String reportId = cr.reportId;
return Basics.getReport(reportId); return Basics.getReport(reportId);
}, 0); }, 0);