package polly.rx.core.orion.http;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.AbstractList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.TreeSet;
import java.util.stream.Collectors;
import javax.imageio.ImageIO;
import polly.rx.MSG;
import polly.rx.core.AZEntryManager;
import polly.rx.core.orion.FleetHeatMap;
import polly.rx.core.orion.Orion;
import polly.rx.core.orion.OrionException;
import polly.rx.core.orion.PortalDecorator;
import polly.rx.core.orion.PortalProvider;
import polly.rx.core.orion.PortalProviderDecorator;
import polly.rx.core.orion.QuadrantProvider;
import polly.rx.core.orion.QuadrantProviderDecorator;
import polly.rx.core.orion.QuadrantUtils;
import polly.rx.core.orion.ResourcePriceProvider;
import polly.rx.core.orion.WormholeProvider;
import polly.rx.core.orion.WormholeProviderDecorator;
import polly.rx.core.orion.model.AlienRace;
import polly.rx.core.orion.model.AlienSpawn;
import polly.rx.core.orion.model.Portal;
import polly.rx.core.orion.model.PortalType;
import polly.rx.core.orion.model.Production;
import polly.rx.core.orion.model.Quadrant;
import polly.rx.core.orion.model.QuadrantDecorator;
import polly.rx.core.orion.model.Resources;
import polly.rx.core.orion.model.Sector;
import polly.rx.core.orion.model.SectorDecorator;
import polly.rx.core.orion.model.SectorType;
import polly.rx.core.orion.model.Wormhole;
import polly.rx.core.orion.model.WormholeDecorator;
import polly.rx.core.orion.model.json.FromClientSector;
import polly.rx.core.orion.model.json.OrionJsonAdapter;
import polly.rx.core.orion.pathplanning.PathPlanner;
import polly.rx.core.orion.pathplanning.PathPlanner.Group;
import polly.rx.core.orion.pathplanning.PathPlanner.HighlightedQuadrant;
import polly.rx.core.orion.pathplanning.PathPlanner.UniversePath;
import polly.rx.core.orion.pathplanning.RouteOptions;
import polly.rx.entities.DBAlienRace;
import polly.rx.parsing.ParseException;
import polly.rx.parsing.QuadrantCnPParser;
import de.skuzzle.polly.http.annotations.Get;
import de.skuzzle.polly.http.annotations.OnRegister;
import de.skuzzle.polly.http.annotations.Param;
import de.skuzzle.polly.http.annotations.Post;
import de.skuzzle.polly.http.api.AlternativeAnswerException;
import de.skuzzle.polly.http.api.Controller;
import de.skuzzle.polly.http.api.HttpException;
import de.skuzzle.polly.http.api.HttpSession;
import de.skuzzle.polly.http.api.answers.HttpAnswer;
import de.skuzzle.polly.http.api.answers.HttpAnswers;
import de.skuzzle.polly.http.api.answers.HttpInputStreamAnswer;
import de.skuzzle.polly.sdk.MyPolly;
import de.skuzzle.polly.sdk.Types;
import de.skuzzle.polly.sdk.Types.TimespanType;
import de.skuzzle.polly.sdk.httpv2.GsonHttpAnswer;
import de.skuzzle.polly.sdk.httpv2.PollyController;
import de.skuzzle.polly.sdk.httpv2.SuccessResult;
import de.skuzzle.polly.sdk.httpv2.WebinterfaceManager;
import de.skuzzle.polly.sdk.httpv2.html.HTMLTools;
import de.skuzzle.polly.sdk.resources.Constants;
import de.skuzzle.polly.sdk.time.Milliseconds;
import de.skuzzle.polly.tools.collections.TemporaryValueMap;
import de.skuzzle.polly.tools.concurrent.Parallel;
import de.skuzzle.polly.tools.io.FastByteArrayInputStream;
import de.skuzzle.polly.tools.io.FastByteArrayOutputStream;
public class OrionController extends PollyController {
public final static String VIEW_ORION_PREMISSION = "polly.permission.VIEW_ORION"; //$NON-NLS-1$
public final static String WRITE_ORION_PREMISSION = "polly.permission.WRITE_ORION"; //$NON-NLS-1$
public final static String ROUTE_ORION_PREMISSION = "polly.permission.ROUTE_ORION"; //$NON-NLS-1$
public final static String MANAGE_RACE_PERMISSION = "polly.permission.MANAGE_ALIEN_RACES"; //$NON-NLS-1$
public final static String SEARCH_SECTORS_PERMISSION = "polly.permission.SEARCH_SECTORS"; //$NON-NLS-1$
public final static String PAGE_ORION = "/pages/orion"; //$NON-NLS-1$
public final static String PAGE_QUAD_LAYOUT = "/pages/orion/quadlayout"; //$NON-NLS-1$
public final static String PAGE_ALIEN_MANAGEMENT = "/pages/orion/manageAliens"; //$NON-NLS-1$
public final static String PAGE_PORTALS = "/pages/orion/portals"; //$NON-NLS-1$
public final static String PAGE_SECTORS = "/pages/sectors"; //$NON-NLS-1$
public final static String PAGE_USER_HEATMAPS = "/pages/userheatmap"; //$NON-NLS-1$
public final static String API_GET_QUADRANT = "/api/orion/quadrant"; //$NON-NLS-1$
public final static String API_GET_SECTOR_INFO = "/api/orion/sector"; //$NON-NLS-1$
public final static String API_SET_ROUTE_TO = "/api/orion/routeTo"; //$NON-NLS-1$
public final static String API_SET_ROUTE_FROM = "/api/orion/routeFrom"; //$NON-NLS-1$
public final static String API_GET_ROUTE = "/api/orion/getRoute"; //$NON-NLS-1$
public final static String API_POST_LAYOUT = "/api/orion/postLayout"; //$NON-NLS-1$
public final static String API_SHARE_ROUTE = "/api/orion/share"; //$NON-NLS-1$
public final static String API_GET_NTH_ROUTE = "/api/orion/nthRoute"; //$NON-NLS-1$
public final static String API_GET_GROUP_IMAGE = "/api/orion/groupImage"; //$NON-NLS-1$
public final static String API_JSON_QUADRANT = "/api/orion/json/quadrant"; //$NON-NLS-1$
public final static String API_JSON_SECTOR = "/api/orion/json/sector"; //$NON-NLS-1$
public final static String API_JSON_ROUTE = "/api/orion/json/route"; //$NON-NLS-1$
public final static String API_JSON_POST_SECTOR = "/api/orion/json/postSector"; //$NON-NLS-1$
public final static String API_SUBMIT_CODE = "/api/orion/get/loginCode"; //$NON-NLS-1$
public final static String API_REQUEST_CODE = "/api/orion/json/requestCode"; //$NON-NLS-1$
public final static String API_REMOVE_RACE = "/api/removeRace"; //$NON-NLS-1$
public final static String API_ADD_RACE = "/api/addRace"; //$NON-NLS-1$
public final static String API_ADD_SPAWN = "/api/addSpawn"; //$NON-NLS-1$
public final static String API_REMOVE_SPAWN = "/api/orion/removeSpawn"; //$NON-NLS-1$
public final static String API_GET_PRICES = "/api/orion/prices"; //$NON-NLS-1$
public final static String API_HEAT_MAP = "/api/orion/heatMap"; //$NON-NLS-1$
public final static String API_SINGLE_HEAT_MAP_IMAGE = "/api/orion/heatMapImage"; //$NON-NLS-1$
private final static String CONTENT_QUAD_LAYOUT = "/polly/rx/httpv2/view/orion/quadlayout.html"; //$NON-NLS-1$
private final static String CONTENT_QUADRANT = "/polly/rx/httpv2/view/orion/quadrant.html"; //$NON-NLS-1$
private final static String CONTENT_SECTOR_INFO = "/polly/rx/httpv2/view/orion/sec_info.html"; //$NON-NLS-1$
private final static String CONTENT_ORION = "/polly/rx/httpv2/view/orion/orion.html"; //$NON-NLS-1$
private final static String CONTENT_ALIEN_MANAGER = "/polly/rx/httpv2/view/orion/alien.manager.html"; //$NON-NLS-1$
private final static String CONTENT_ROUTE = "/polly/rx/httpv2/view/orion/route.html"; //$NON-NLS-1$
private final static String CONTENT_ROUTE_SINGLE = "/polly/rx/httpv2/view/orion/route.single.html"; //$NON-NLS-1$
private final static String CONTENT_SHARE_ROUTE = "/polly/rx/httpv2/view/orion/route.share.html"; //$NON-NLS-1$
private final static String CONTENT_PORTALS = "/polly/rx/httpv2/view/portals.overview.html"; //$NON-NLS-1$
private final static String CONTENT_SECTOR_SEARCH = "/polly/rx/httpv2/view/sectors.overview.html"; //$NON-NLS-1$
private final static String CONTENT_USER_HEATMAPS = "/polly/rx/httpv2/view/user.heatmaps.html"; //$NON-NLS-1$
private final static String REVORIX_CATEGORY_KEY = "httpRxCategory"; //$NON-NLS-1$
private final static String ORION_NAME_KEY = "htmlOrionName"; //$NON-NLS-1$
private final static String ORION_DESC_KEY = "htmlOrionDesc"; //$NON-NLS-1$
private final static String ALIEN_MANAGEMENT_NAME_KEY = "htmlOrionAlienManagement"; //$NON-NLS-1$
private final static String ALIEN_MANAGEMENT_DESC_KEY = "htmlOrionAlienManagementDesc"; //$NON-NLS-1$
private final static String PORTALS_NAME_KEY = "htmlPortals"; //$NON-NLS-1$
private final static String PORTALS_DESC_KEY = "htmlPortalsDesc"; //$NON-NLS-1$
private final static String SECTORS_NAME_KEY = "htmlSectorsTitle"; //$NON-NLS-1$
private final static String SECTORS_DESC_KEY = "htmlSectorsDesc"; //$NON-NLS-1$
private final static String ROUTE_FROM_KEY = "routeFrom"; //$NON-NLS-1$
private final static String ROUTE_TO_KEY = "routeTo"; //$NON-NLS-1$
private final static String ROUTE_OPTIONS_KEY = "routeOptions"; //$NON-NLS-1$
private final static String ROUTE_COUNT_KEY = "routeCount"; //$NON-NLS-1$
private static final String HEAT_MAPS_KEY = "heatMaps"; //$NON-NLS-1$
public final static class DisplaySector extends SectorDecorator {
private DisplaySector(Sector wrapped) {
super(wrapped);
}
@Override
public String getQuadId() {
return getQuadName().replace(" ", "_"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public final static class DisplayQuadrant extends QuadrantDecorator {
private DisplayQuadrant(Quadrant wrapped) {
super(wrapped);
}
@Override
public String getQuadId() {
return getName().replace(" ", "_"); //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
public Sector getSector(int x, int y) {
return new DisplaySector(super.getSector(x, y));
}
}
public final static class DisplayPortal extends PortalDecorator {
public DisplayPortal(Portal wrapped) {
super(wrapped);
}
@Override
public Sector getSector() {
return new DisplaySector(super.getSector());
}
}
public final static class DisplayPortalProvider extends PortalProviderDecorator {
public DisplayPortalProvider(PortalProvider wrapped) {
super(wrapped);
}
private List<? extends Portal> decorate(final List<? extends Portal> portals) {
return new AbstractList<Portal>() {
@Override
public Portal get(int idx) {
return new DisplayPortal(portals.get(idx));
}
@Override
public int size() {
return portals.size();
}
};
}
@Override
public Portal getClanPortal(String nameOrTag) {
final Portal p = super.getClanPortal(nameOrTag);
if (p == null) {
return null;
}
return new DisplayPortal(p);
}
@Override
public Portal getPersonalPortal(String ownerName) {
final Portal p = super.getPersonalPortal(ownerName);
if (p == null) {
return null;
}
return new DisplayPortal(p);
}
@Override
public List<? extends Portal> getPortals(Sector sector, PortalType type) {
return decorate(super.getPortals(sector, type));
}
@Override
public List<? extends Portal> getPortals(Quadrant quadrant, PortalType type) {
return decorate(super.getPortals(quadrant, type));
}
@Override
public List<? extends Portal> getPortals(Sector sector) {
return decorate(super.getPortals(sector));
}
}
public final static class DisplayWormholeProvider extends WormholeProviderDecorator {
public DisplayWormholeProvider(WormholeProvider wrapped) {
super(wrapped);
}
private List<Wormhole> decorate(final List<Wormhole> holes) {
return new AbstractList<Wormhole>() {
@Override
public Wormhole get(int index) {
return new WormholeDecorator(holes.get(index)) {
@Override
public Sector getSource() {
return new DisplaySector(super.getSource());
}
@Override
public Sector getTarget() {
return new DisplaySector(super.getTarget());
}
};
}
@Override
public int size() {
return holes.size();
}
};
}
@Override
public List<Wormhole> getWormholes(Quadrant quadrant, QuadrantProvider quads) {
return decorate(super.getWormholes(quadrant, quads));
}
@Override
public List<Wormhole> getWormholes(Sector sector, QuadrantProvider quads) {
return decorate(super.getWormholes(sector, quads));
}
}
public final static class DisplayQuadrantProvider extends QuadrantProviderDecorator {
public DisplayQuadrantProvider(QuadrantProvider wrapped) {
super(wrapped);
}
private List<Quadrant> decorate(final List<? extends Quadrant> quadrants) {
return new AbstractList<Quadrant>() {
@Override
public Quadrant get(int index) {
return new DisplayQuadrant(quadrants.get(index));
}
@Override
public int size() {
return quadrants.size();
}
};
}
@Override
public List<Quadrant> getAllQuadrants() {
return decorate(super.getAllQuadrants());
}
@Override
public Quadrant getQuadrant(Sector sector) {
return new DisplayQuadrant(super.getQuadrant(sector));
}
@Override
public Quadrant getQuadrant(String name) {
name = name.replace('_', ' ');
return new DisplayQuadrant(super.getQuadrant(name));
}
}
private class RouteContext {
private final String routeId;
private final Sector start;
private final Sector target;
private final RouteOptions options;
private final List<UniversePath> paths;
public RouteContext(String routeId, Sector start, Sector target, RouteOptions options,
List<UniversePath> paths) {
super();
this.routeId = routeId;
this.start = start;
this.target = target;
this.options = options;
this.paths = paths;
}
public FastByteArrayOutputStream getQuadImage(int n, final int groupId) {
final UniversePath p = this.paths.get(n - 1);
final Group g = p.getGroups().stream()
.filter(grp -> grp.getId() == groupId)
.findFirst().get();
final BufferedImage quadImg = QuadrantUtils.createQuadImage(g.getQuadrant());
final FastByteArrayOutputStream out = new FastByteArrayOutputStream();
try {
ImageIO.write(quadImg, "png", out); //$NON-NLS-1$
} catch (final IOException e) {
e.printStackTrace();
}
return out;
}
public void putInto(Map<String, Object> c, int n) {
c.put("routeId", this.routeId); //$NON-NLS-1$
c.put("start", this.start); //$NON-NLS-1$
c.put("target", this.target); //$NON-NLS-1$
c.put("options", this.options); //$NON-NLS-1$
c.put("path", this.paths.get(n - 1)); //$NON-NLS-1$
c.put("n", n); //$NON-NLS-1$
c.put("routeCount", this.paths.size()); //$NON-NLS-1$
}
}
private final static long ROUTE_CACHE_TIME = Milliseconds.fromMinutes(5);
private final static Random RANDOM = new Random();
private final static TemporaryValueMap<String, RouteContext> ROUTES =
new TemporaryValueMap<>(ROUTE_CACHE_TIME);
private final QuadrantProvider quadProvider;
private final WormholeProvider holeProvider;
private final PortalProvider portalProvider;
private final PathPlanner pathPlanner;
private final AZEntryManager azManager;
public OrionController(MyPolly myPolly, AZEntryManager azManager) {
this(myPolly, new DisplayQuadrantProvider(Orion.INSTANCE.getQuadrantProvider()),
new DisplayWormholeProvider(Orion.INSTANCE.getWormholeProvider()),
new DisplayPortalProvider(Orion.INSTANCE.getPortalProvider()),
Orion.INSTANCE.getPathPlanner(), azManager);
}
/**
* Copy Constructor for {@link #createInstance()}
*
* @param myPolly
* @param quadProvider
* @param holeProvider
* @param portalProvider
* @param planner
* @param azManager
*/
private OrionController(MyPolly myPolly, QuadrantProvider quadProvider,
WormholeProvider holeProvider, PortalProvider portalProvider,
PathPlanner planner, AZEntryManager azManager) {
super(myPolly);
this.quadProvider = quadProvider;
this.holeProvider = holeProvider;
this.portalProvider = portalProvider;
this.pathPlanner = planner;
this.azManager = azManager;
}
@Override
protected Controller createInstance() {
return new OrionController(getMyPolly(), this.quadProvider,
this.holeProvider, this.portalProvider, this.pathPlanner, this.azManager);
}
@Override
protected Map<String, Object> createContext(String content) {
final Map<String, Object> c = super.createContext(content);
HTMLTools.gainFieldAccess(c, MSG.class, "MSG"); //$NON-NLS-1$
c.put("Messages", Constants.class); //$NON-NLS-1$
return c;
}
@Get(API_SUBMIT_CODE)
@Deprecated
public HttpAnswer submitCode(@Param("code") String code, @Param("user") String user,
@Param("pw") String pw) throws AlternativeAnswerException {
checkLogin(user, pw);
/*if (Orion.INSTANCE.getLoginCodeManager().updateCurrentCode(code)) {
return new GsonHttpAnswer(200, new SuccessResult(true, "")); //$NON-NLS-1$
}*/
return new GsonHttpAnswer(200, new SuccessResult(true, "")); //$NON-NLS-1$
}
@Get(API_HEAT_MAP)
public HttpAnswer getHeatmap(@Param("venad") String venad,
@Param("quadrant") String quadrant, @Param("user") String user,
@Param("pw") String pw) throws AlternativeAnswerException {
checkLogin(user, pw);
final FleetHeatMap heatMap = Orion.INSTANCE.getHeatMap();
final Quadrant quad = this.quadProvider.getQuadrant(quadrant);
final BufferedImage map = QuadrantUtils.drawHeatMap(quad, venad, heatMap);
final FastByteArrayOutputStream out = new FastByteArrayOutputStream();
try {
ImageIO.write(map, "png", out); //$NON-NLS-1$
} catch (final IOException e) {
e.printStackTrace();
}
final InputStream in = new FastByteArrayInputStream(out);
return new HttpInputStreamAnswer(200, in);
}
@Get(PAGE_USER_HEATMAPS)
public HttpAnswer getUserHeatmaps(@Param("venad") String venad,
@Param("user") String user, @Param("pw") String pw)
throws AlternativeAnswerException {
// -checkLogin(user, pw);
final FleetHeatMap heatMap = Orion.INSTANCE.getHeatMap();
final Map<Quadrant, BufferedImage> images = QuadrantUtils.drawUserHeatMap(venad, heatMap);
getSession().set(HEAT_MAPS_KEY, images);
final Map<String, Object> context = createContext(CONTENT_USER_HEATMAPS);
context.put("maps", images); //$NON-NLS-1$
context.put("venad", venad); //$NON-NLS-1$
return makeAnswer(context);
}
@Get(API_SINGLE_HEAT_MAP_IMAGE)
public HttpAnswer getSessionHeatMap(@Param("num") int num) {
final Map<Quadrant, BufferedImage> images = getSession().get(HEAT_MAPS_KEY,
Collections.emptyMap());
if (num >= 0 && num <= images.size()) {
final Iterator<BufferedImage> it = images.values().iterator();
for (int i = 0; i < num - 1; ++i) {
it.next();
}
final BufferedImage image = it.next();
final FastByteArrayOutputStream out = new FastByteArrayOutputStream();
try {
ImageIO.write(image, "png", out); //$NON-NLS-1$
} catch (final IOException e) {
e.printStackTrace();
}
final InputStream in = new FastByteArrayInputStream(out);
return new HttpInputStreamAnswer(200, in);
}
return HttpAnswers.newStringAnswer(404, "image not found"); //$NON-NLS-1$
}
@Get(value = PAGE_ORION, name = ORION_NAME_KEY)
@OnRegister({ WebinterfaceManager.ADD_MENU_ENTRY, MSG.FAMILY, REVORIX_CATEGORY_KEY,
ORION_DESC_KEY, VIEW_ORION_PREMISSION })
public HttpAnswer orion() throws AlternativeAnswerException {
requirePermissions(VIEW_ORION_PREMISSION);
final Map<String, Object> c = createContext(CONTENT_ORION);
final Collection<Quadrant> allQuads = new TreeSet<>(new Comparator<Quadrant>() {
@Override
public int compare(Quadrant o1, Quadrant o2) {
return o1.getName().compareTo(o2.getName());
}
});
allQuads.addAll(this.quadProvider.getAllQuadrants());
c.put("allQuads", allQuads); //$NON-NLS-1$
c.put("routeStart", getSession().get(ROUTE_FROM_KEY)); //$NON-NLS-1$
c.put("routeTarget", getSession().get(ROUTE_TO_KEY)); //$NON-NLS-1$
c.put("personalPortals", Orion.INSTANCE.getPersonalPortals(getSessionUser())); //$NON-NLS-1$
c.put("entryPortals", this.quadProvider.getEntryPortals()); //$NON-NLS-1$
c.put("entries", this.azManager.getEntries(getSessionUser().getId())); //$NON-NLS-1$
return this.makeAnswer(c);
}
@Get(value = PAGE_PORTALS, name = PORTALS_NAME_KEY)
@OnRegister({ WebinterfaceManager.ADD_MENU_ENTRY, MSG.FAMILY, REVORIX_CATEGORY_KEY,
PORTALS_DESC_KEY, VIEW_ORION_PREMISSION })
public HttpAnswer portals() throws AlternativeAnswerException {
requirePermissions(VIEW_ORION_PREMISSION);
return this.makeAnswer(createContext(CONTENT_PORTALS));
}
@Get(value = PAGE_QUAD_LAYOUT, name = ORION_NAME_KEY)
//@OnRegister({ WebinterfaceManager.ADD_SUB_ENTRY, "Orion", MSG.FAMILY, ORION_DESC_KEY,
// VIEW_ORION_PREMISSION })
public HttpAnswer quadLayout() throws AlternativeAnswerException {
requirePermissions(OrionController.WRITE_ORION_PREMISSION);
return this.makeAnswer(createContext(CONTENT_QUAD_LAYOUT));
}
@Get(value = PAGE_ALIEN_MANAGEMENT, name = ALIEN_MANAGEMENT_NAME_KEY)
@OnRegister({ WebinterfaceManager.ADD_SUB_ENTRY, "Orion", MSG.FAMILY,
ALIEN_MANAGEMENT_DESC_KEY, MANAGE_RACE_PERMISSION })
public HttpAnswer alienManagement() throws AlternativeAnswerException {
requirePermissions(OrionController.MANAGE_RACE_PERMISSION);
final Map<String, Object> c = createContext(CONTENT_ALIEN_MANAGER);
c.put("allRaces", Orion.INSTANCE.getAlienManager().getAllRaces()); //$NON-NLS-1$
return this.makeAnswer(c);
}
@Get(value = PAGE_SECTORS, name = SECTORS_NAME_KEY)
@OnRegister({ WebinterfaceManager.ADD_SUB_ENTRY, "Orion", MSG.FAMILY,
SECTORS_DESC_KEY, SEARCH_SECTORS_PERMISSION })
public HttpAnswer sectorSearch() throws AlternativeAnswerException {
requirePermissions(OrionController.SEARCH_SECTORS_PERMISSION);
final Map<String, Object> c = createContext(CONTENT_SECTOR_SEARCH);
return this.makeAnswer(c);
}
@Get(API_REMOVE_RACE)
public HttpAnswer removeRace(@Param("id") int id) throws AlternativeAnswerException {
requirePermissions(OrionController.MANAGE_RACE_PERMISSION);
final AlienRace ar = Orion.INSTANCE.getAlienManager().getRaceById(id);
try {
Orion.INSTANCE.getAlienManager().removeRace(ar);
return new GsonHttpAnswer(200, new SuccessResult(true, "")); //$NON-NLS-1$
} catch (final OrionException e) {
return new GsonHttpAnswer(200, new SuccessResult(false, e.getMessage()));
}
}
public final static class AddRaceResult extends SuccessResult {
public final int id;
private AddRaceResult(int id) {
super(true, ""); //$NON-NLS-1$
this.id = id;
}
}
@Get(API_ADD_RACE)
public HttpAnswer addRace(@Param("name") String name,
@Param(value = "type", optional = true) String type,
@Param("aggr") boolean aggressive) throws AlternativeAnswerException {
requirePermissions(MANAGE_RACE_PERMISSION);
try {
final DBAlienRace race = (DBAlienRace) Orion.INSTANCE.getAlienManager().addRace(
name, type, aggressive);
return new GsonHttpAnswer(200, new AddRaceResult(race.getId()));
} catch (final OrionException e) {
return new GsonHttpAnswer(200, new SuccessResult(false, e.getMessage()));
}
}
@Get(API_ADD_SPAWN)
public HttpAnswer addSpawn(@Param("name") String name, @Param("raceId") int raceId,
@Param("sector") String sectorString) {
try {
final Sector s = QuadrantUtils.parse(sectorString);
final AlienRace race = Orion.INSTANCE.getAlienManager().getRaceById(raceId);
Orion.INSTANCE.getAlienManager().addSpawn(name, race, s);
return new GsonHttpAnswer(200, new SuccessResult(true, "")); //$NON-NLS-1$
} catch (final Exception e) {
return new GsonHttpAnswer(200, new SuccessResult(false, e.getMessage()));
}
}
@Get(API_REMOVE_SPAWN)
public HttpAnswer removeSpawn(@Param("id") int spawnId) throws AlternativeAnswerException {
requirePermissions(MANAGE_RACE_PERMISSION);
try {
final AlienSpawn spawn = Orion.INSTANCE.getAlienManager().getSpawnById(spawnId);
Orion.INSTANCE.getAlienManager().removeAlienSpawn(spawn);
return new GsonHttpAnswer(200, new SuccessResult(true, "")); //$NON-NLS-1$
} catch (final Exception e) {
return new GsonHttpAnswer(200, new SuccessResult(false, e.getMessage()));
}
}
@Post(API_POST_LAYOUT)
public HttpAnswer postQuadLayout(@Param("quadName") String quadName,
@Param("paste") String paste) throws HttpException {
try {
final Collection<Sector> sectors = QuadrantCnPParser.parse(paste, quadName);
Orion.INSTANCE.getQuadrantUpdater().updateSectorInformation(sectors);
} catch (ParseException | OrionException e) {
throw new HttpException(e);
}
return HttpAnswers.newRedirectAnswer(PAGE_QUAD_LAYOUT);
}
private void fillQuadrantContext(String quadName, Map<String, Object> c,
boolean showInfo, boolean abstractView) {
Quadrant q = this.quadProvider.getQuadrant(quadName);
if (showInfo) {
final List<Wormhole> holes = this.holeProvider.getWormholes(q,
this.quadProvider);
final Collection<? extends Portal> pportals = this.portalProvider.getPortals(
q, PortalType.PRIVATE);
final Collection<? extends Portal> cportals = this.portalProvider.getPortals(
q, PortalType.CLAN);
// TODO: this should use an alien manager which returns DisplaySectors within
// the alien spawns
final Collection<? extends AlienSpawn> spawns =
Orion.INSTANCE.getAlienManager().getSpawnsByQuadrant(q.getName());
if (abstractView) {
q = createAbstract(q, holes, spawns);
}
final Resources hourlyProduction = QuadrantUtils.calculateHourlyProduction(q);
final DecimalFormat nf = (DecimalFormat) DecimalFormat
.getInstance(Locale.ENGLISH);
nf.applyPattern("0.00"); //$NON-NLS-1$
c.put("holes", holes); //$NON-NLS-1$
c.put("pportals", pportals); //$NON-NLS-1$
c.put("cportals", cportals); //$NON-NLS-1$
c.put("spawns", spawns); //$NON-NLS-1$
c.put("nf", nf); //$NON-NLS-1$
c.put("hourlyProduction", hourlyProduction.getAmountArray()); //$NON-NLS-1$
}
c.put("showQuadInfo", showInfo); //$NON-NLS-1$
c.put("abstract", abstractView); //$NON-NLS-1$
c.put("quad", q); //$NON-NLS-1$
}
private Quadrant createAbstract(Quadrant quad, Collection<? extends Wormhole> holes,
Collection<? extends AlienSpawn> spawns) {
final HighlightedQuadrant q = new HighlightedQuadrant(quad, true);
holes.forEach(h -> q.highlight(h.getSource(), SectorType.HIGHLIGHT_WH_START));
spawns.forEach(s -> q.highlight(s.getSector(), SectorType.HIGHLIGHT_ALIEN_SPAWN));
return q;
}
@Get(API_GET_QUADRANT)
public HttpAnswer quadrant(@Param("quadName") String name,
@Param(value = "abstract", defaultValue = "false", optional = true) boolean renderAbstract) {
if (!getMyPolly().roles()
.hasPermission(getSessionUser(), VIEW_ORION_PREMISSION)) {
return HttpAnswers.newStringAnswer(403, MSG.httpNoPermission);
}
final Map<String, Object> c = createContext(""); //$NON-NLS-1$
fillQuadrantContext(name, c, true, renderAbstract);
return HttpAnswers.newTemplateAnswer(CONTENT_QUADRANT, c);
}
@Get(API_GET_QUADRANT)
public HttpAnswer quadrant(@Param("quadName") String name, @Param("hlX") int hlX,
@Param("hlY") int hlY) {
if (!getMyPolly().roles()
.hasPermission(getSessionUser(), VIEW_ORION_PREMISSION)) {
return HttpAnswers.newStringAnswer(403, MSG.httpNoPermission);
}
final Map<String, Object> c = createContext(""); //$NON-NLS-1$
fillQuadrantContext(name, c, true, false);
c.put("hlX", hlX); //$NON-NLS-1$
c.put("hlY", hlY); //$NON-NLS-1$
return HttpAnswers.newTemplateAnswer(CONTENT_QUADRANT, c);
}
@Get(API_GET_SECTOR_INFO)
public HttpAnswer sectorInfo(@Param("quadrant") String quadrant, @Param("x") int x,
@Param("y") int y) {
if (!getMyPolly().roles()
.hasPermission(getSessionUser(), VIEW_ORION_PREMISSION)) {
return HttpAnswers.newStringAnswer(403, MSG.httpNoPermission);
}
final NumberFormat nf = new DecimalFormat("0.00"); //$NON-NLS-1$
final Quadrant q = this.quadProvider.getQuadrant(quadrant);
final Sector sector = q.getSector(x, y);
final Map<String, Object> c = createContext(CONTENT_SECTOR_INFO);
c.put("sector", sector); //$NON-NLS-1$
c.put("nf", nf); //$NON-NLS-1$
if (sector != null) {
final List<Wormhole> holes = this.holeProvider.getWormholes(sector,
this.quadProvider);
final Collection<? extends Portal> pportals = this.portalProvider.getPortals(
sector, PortalType.PRIVATE);
final Collection<? extends Portal> cportals = this.portalProvider.getPortals(
sector, PortalType.CLAN);
c.put("pportals", pportals); //$NON-NLS-1$
c.put("cportals", cportals); //$NON-NLS-1$
c.put("holes", holes); //$NON-NLS-1$
}
return HttpAnswers.newTemplateAnswer(CONTENT_SECTOR_INFO, c);
}
public class SectorResult extends SuccessResult {
public final String quadName;
public final int x;
public final int y;
public SectorResult(Sector sector) {
super(true, ""); //$NON-NLS-1$
this.quadName = sector.getQuadName();
this.x = sector.getX();
this.y = sector.getY();
}
}
private HttpAnswer updateRouteInformation(String quadrant, int x, int y, String key) {
if (!getMyPolly().roles()
.hasPermission(getSessionUser(), ROUTE_ORION_PREMISSION)) {
return new GsonHttpAnswer(403, new SuccessResult(false, MSG.httpNoPermission));
}
final Quadrant q = this.quadProvider.getQuadrant(quadrant);
final Sector sector = q.getSector(x, y);
if (sector != null) {
getSession().set(key, sector);
return new GsonHttpAnswer(200, new SectorResult(sector));
}
getSession().set(key, sector);
return new GsonHttpAnswer(200, new SuccessResult(false, "")); //$NON-NLS-1$
}
@Get(API_SET_ROUTE_FROM)
public HttpAnswer setRouteFrom(@Param("quadrant") String quadrant, @Param("x") int x,
@Param("y") int y) {
return updateRouteInformation(quadrant, x, y, ROUTE_FROM_KEY);
}
@Get(API_SET_ROUTE_TO)
public HttpAnswer setRouteTo(@Param("quadrant") String quadrant, @Param("x") int x,
@Param("y") int y) {
return updateRouteInformation(quadrant, x, y, ROUTE_TO_KEY);
}
@Get(API_SHARE_ROUTE)
public HttpAnswer shareRoute(@Param("routeId") String routeId) {
final RouteContext rc = ROUTES.get(routeId);
if (rc == null) {
return HttpAnswers.newStringAnswer(MSG.htmlOrionRouteTimeOut);
}
final Map<String, Object> c = createContext(""); //$NON-NLS-1$
rc.putInto(c, 1);
c.put("legend", SectorType.HIGHLIGHTS); //$NON-NLS-1$
return HttpAnswers.newTemplateAnswer(CONTENT_SHARE_ROUTE, c);
}
@Get(API_GET_NTH_ROUTE)
public HttpAnswer getNthRoute(@Param("id") String routeId, @Param("n") int n) {
final RouteContext rc = ROUTES.get(routeId);
if (rc == null) {
return HttpAnswers.newStringAnswer(MSG.htmlOrionRouteTimeOut);
}
final Map<String, Object> c = createContext(""); //$NON-NLS-1$
rc.putInto(c, n);
return HttpAnswers.newTemplateAnswer(CONTENT_ROUTE_SINGLE, c);
}
@Get(API_GET_ROUTE)
public HttpAnswer getRoute(
@Param("fleetId") int fleetId,
@Param(value = "jt", optional = true) String jt,
@Param(value = "cjt", optional = true) String cjt,
@Param(value = "bt", optional = true, defaultValue = "false") boolean blockTail,
@Param(value = "be", optional = true, defaultValue = "false") boolean blockEntryPortals,
@Param(value = "re", optional = true, defaultValue = "true") boolean renderDark) {
if (!getMyPolly().roles()
.hasPermission(getSessionUser(), ROUTE_ORION_PREMISSION)) {
return HttpAnswers.newStringAnswer(403, MSG.httpNoPermission);
}
final Map<String, Object> c = createContext(""); //$NON-NLS-1$
final HttpSession s = getSession();
final List<Sector> personalPortals = Orion.INSTANCE.getPersonalPortals(getSessionUser());
if (!s.isSet(ROUTE_FROM_KEY)) {
if (!personalPortals.isEmpty()) {
s.set(ROUTE_FROM_KEY, personalPortals.iterator().next());
} else {
return HttpAnswers.newStringAnswer(""); //$NON-NLS-1$
}
}
if (!s.isSet(ROUTE_TO_KEY)) {
return HttpAnswers.newStringAnswer(""); //$NON-NLS-1$
}
final Sector start = (Sector) s.get(ROUTE_FROM_KEY);
final Sector target = (Sector) s.get(ROUTE_TO_KEY);
final TimespanType jumpTime;
if (fleetId == -1) {
jumpTime = parse(jt, new TimespanType(0));
} else {
jumpTime = this.azManager.getJumpTime(fleetId, getSessionUser());
}
final TimespanType currentJumpTime = parse(cjt, jumpTime);
final RouteOptions options = new RouteOptions(jumpTime, currentJumpTime,
personalPortals, blockTail, blockEntryPortals, renderDark);
final List<UniversePath> path = this.pathPlanner.findShortestPaths(start,
target, options);
s.set(ROUTE_OPTIONS_KEY, options);
s.set(ROUTE_COUNT_KEY, path.size());
final String routeId = createRouteId();
final RouteContext rc = new RouteContext(routeId, start, target, options,
path);
rc.putInto(c, 1);
c.put("legend", SectorType.HIGHLIGHTS); //$NON-NLS-1$
ROUTES.put(routeId, rc);
return HttpAnswers.newTemplateAnswer(CONTENT_ROUTE, c);
}
private static String createRouteId() {
synchronized (ROUTES) {
String s = ""; //$NON-NLS-1$
do {
final long l = RANDOM.nextLong();
s = Long.toHexString(l);
} while (ROUTES.containsKey(s));
return s;
}
}
@Get(API_GET_GROUP_IMAGE)
public HttpAnswer getImageForGroup(@Param("routeId") String routeId,
@Param("n") int n, @Param("grp") int id) {
final RouteContext rc = ROUTES.get(routeId);
if (rc == null) {
return HttpAnswers.newStringAnswer(404, ""); //$NON-NLS-1$
}
final FastByteArrayOutputStream out = rc.getQuadImage(n, id);
final InputStream in = new FastByteArrayInputStream(out);
return new HttpInputStreamAnswer(200, in);
}
private TimespanType parse(String jumpTime, TimespanType alternative) {
final Types types = getMyPolly().parse(jumpTime);
if (types == null || !(types instanceof TimespanType)) {
return alternative;
}
return (TimespanType) types;
}
@Get(API_JSON_ROUTE)
public HttpAnswer getJsonRoute() {
return HttpAnswers.newStringAnswer(""); //$NON-NLS-1$
}
@Get(API_JSON_SECTOR)
public HttpAnswer getJsonSector(@Param("q") String quadName, @Param("x") int x,
@Param("y") int y) {
final Quadrant quad = this.quadProvider.getQuadrant(quadName);
final Sector sector = quad.getSector(x, y);
return OrionJsonAdapter.sectorAnswer(sector);
}
@Get(API_JSON_QUADRANT)
public HttpAnswer getJsonQuadrant(@Param("q") String name) {
final Quadrant quad = this.quadProvider.getQuadrant(name);
return OrionJsonAdapter.quadrantAnswer(quad);
}
@Post(API_JSON_POST_SECTOR)
public HttpAnswer postJson() {
final String json = getEvent().getRequestBody();
final FromClientSector sector = OrionJsonAdapter.readSectorFromClient(json);
final String reporter = sector.getSelf();
Parallel.run(new Runnable() {
@Override
public void run() {
try {
Orion.INSTANCE.getQuadrantUpdater().updateSectorInformation(
Collections.singleton(sector));
Orion.INSTANCE.getPortalUpdater().updatePortals(reporter, sector,
sector.getClanPortals());
Orion.INSTANCE.getPortalUpdater().updatePortals(reporter, sector,
sector.getPersonalPortals());
Orion.INSTANCE.getFleetTracker().updateOrionFleets(reporter,
sector.getOwnFleets());
Orion.INSTANCE.getFleetTracker().updateFleets(reporter,
sector.getFleets());
} catch (final OrionException e) {
e.printStackTrace();
}
}
});
return new GsonHttpAnswer(200, new SuccessResult(true, "")); //$NON-NLS-1$
}
public final class ResourcePrices {
public String date;
public String[] prices;
private ResourcePrices(String date, String[] prices) {
this.date = date;
this.prices = prices;
}
}
@Get(API_GET_PRICES)
public HttpAnswer getPrices(@Param("user") String user, @Param("pw") String pw) throws AlternativeAnswerException {
checkLogin(user, pw);
final NumberFormat nf = new DecimalFormat("0.00"); //$NON-NLS-1$
final ResourcePriceProvider rpp = Orion.INSTANCE.getPriceProvider();
final List<String> priceList = rpp.getAllPrices().stream()
.map(Production::getRate)
.map(nf::format)
.collect(Collectors.toList());
final String[] priceArray = priceList.toArray(new String[priceList.size()]);
final String date = getMyPolly().formatting().formatDate(rpp.getRefreshTime());
return new GsonHttpAnswer(200, new ResourcePrices(date, priceArray));
}
}