aboutsummaryrefslogtreecommitdiff
path: root/diplomacy/web/src/gui/map
diff options
context:
space:
mode:
authornotoraptor <stevenbocco@gmail.com>2019-08-01 15:53:23 -0400
committerPhilip Paquette <pcpaquette@gmail.com>2019-08-01 16:32:55 -0400
commit891fb62a77b9a86f2bc71cc02a82089412982b2f (patch)
tree7152ec4ef8186741695a921d6cc7bac78102b0dd /diplomacy/web/src/gui/map
parent904ea5bcfab0ffe2b87d00fd0b938a8907c44842 (diff)
Refactored SVG map into a React component
- Create link to diplomacy map folder into web/src/diplomacy/maps - Remove old web/src/gui/map folder. - [web] Handle click only on current map. - [web/game] Remove useless `wait` state. - Remove unused nodejs modules. - [web] Use queue to handle game notifications in sequential order. - Make all calls to setState() asynchronous in Page and ContentGame components. - Make sure notifications are handled in the order in which they come.
Diffstat (limited to 'diplomacy/web/src/gui/map')
-rw-r--r--diplomacy/web/src/gui/map/dom_order_builder.js278
-rw-r--r--diplomacy/web/src/gui/map/dom_past_map.js114
-rw-r--r--diplomacy/web/src/gui/map/map.jsx94
-rw-r--r--diplomacy/web/src/gui/map/renderer.js615
4 files changed, 0 insertions, 1101 deletions
diff --git a/diplomacy/web/src/gui/map/dom_order_builder.js b/diplomacy/web/src/gui/map/dom_order_builder.js
deleted file mode 100644
index 14ba743..0000000
--- a/diplomacy/web/src/gui/map/dom_order_builder.js
+++ /dev/null
@@ -1,278 +0,0 @@
-// ==============================================================================
-// Copyright (C) 2019 - Philip Paquette, Steven Bocco
-//
-// This program is free software: you can redistribute it and/or modify it under
-// the terms of the GNU Affero General Public License as published by the Free
-// Software Foundation, either version 3 of the License, or (at your option) any
-// later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Affero General Public License along
-// with this program. If not, see <https://www.gnu.org/licenses/>.
-// ==============================================================================
-import {UTILS} from "../../diplomacy/utils/utils";
-import $ from "jquery";
-import {extendOrderBuilding} from "../utils/order_building";
-import {Diplog} from "../../diplomacy/utils/diplog";
-
-function parseLocation(txt) {
- if (txt.length > 2 && txt[1] === ' ' && ['A', 'F'].includes(txt[0]))
- return txt.substr(2);
- return txt;
-}
-
-export class DOMOrderBuilder {
-
- constructor(svgElement, onOrderBuilding, onOrderBuilt, onSelectLocation, onSelectVia, onError) {
- this.svg = svgElement;
- this.cbOrderBuilding = onOrderBuilding;
- this.cbOrderBuilt = onOrderBuilt;
- this.cbSelectLocation = onSelectLocation;
- this.cbSelectVia = onSelectVia;
- this.cbError = onError;
-
- this.game = null;
- this.mapData = null;
- this.orderBuilding = null;
-
- this.provinceColors = {};
- this.clickedID = null;
- this.clickedNeighbors = [];
-
- this.onProvinceClick = this.onProvinceClick.bind(this);
- this.onLabelClick = this.onLabelClick.bind(this);
- this.onUnitClick = this.onUnitClick.bind(this);
- }
-
- saveProvinceColors() {
- // Get province colors.
- const elements = this.svg.getElementsByTagName('path');
- for (let element of elements) {
- this.provinceColors[element.id] = element.getAttribute('class');
- }
- }
-
- provinceNameToMapID(name) {
- return `_${name.toLowerCase()}___${this.svg.parentNode.id}`;
- }
-
- mapID(id) {
- return `${id}___${this.svg.parentNode.id}`;
- }
-
- onOrderBuilding(svgPath, powerName, orderPath) {
- this.cbOrderBuilding(powerName, orderPath);
- }
-
- onOrderBuilt(svgPath, powerName, orderString) {
- this.cbOrderBuilt(powerName, orderString);
- }
-
- onError(svgPath, error) {
- this.cbError(error.toString());
- }
-
- handleSvgPath(svgPath) {
- const orderBuilding = this.orderBuilding;
- if (!orderBuilding.builder)
- return this.onError(svgPath, 'No orderable locations.');
-
- const province = this.mapData.getProvince(svgPath.id);
- if (!province)
- return;
-
- const stepLength = orderBuilding.builder.steps.length;
- if (orderBuilding.path.length >= stepLength)
- throw new Error(`Order building: current steps count (${orderBuilding.path.length}) should be less than` +
- ` expected steps count (${stepLength}) (${orderBuilding.path.join(', ')}).`);
-
- const lengthAfterClick = orderBuilding.path.length + 1;
- let validLocations = [];
- const testedPath = [orderBuilding.type].concat(orderBuilding.path);
- const value = UTILS.javascript.getTreeValue(this.game.ordersTree, testedPath);
- if (value !== null) {
- const checker = orderBuilding.builder.steps[lengthAfterClick - 1];
- try {
- const possibleLocations = checker(province, orderBuilding.power);
- for (let possibleLocation of possibleLocations) {
- possibleLocation = possibleLocation.toUpperCase();
- if (value.includes(possibleLocation))
- validLocations.push(possibleLocation);
- }
- } catch (error) {
- return this.onError(svgPath, error);
- }
- }
- if (!validLocations.length)
- return this.onError(svgPath, 'Disallowed.');
-
- if (validLocations.length > 1 && orderBuilding.type === 'S' && orderBuilding.path.length >= 2) {
- // We are building a support order and we have a multiple choice for a location.
- // Let's check if next location to choose is a coast. To have a coast:
- // - all possible locations must start with same 3 characters.
- // - we expect at least province name in possible locations (e.g. 'SPA' for 'SPA/NC').
- // If we have a coast, we will remove province name from possible locations.
- let isACoast = true;
- let validLocationsNoProvinceName = [];
- for (let i = 0; i < validLocations.length; ++i) {
- let location = validLocations[i];
- if (i > 0) {
- // Compare 3 first letters with previous location.
- if (validLocations[i - 1].substring(0, 3).toUpperCase() !== validLocations[i].substring(0, 3).toUpperCase()) {
- // No same prefix with previous location. We does not have a coast.
- isACoast = false;
- break;
- }
- }
- if (location.length !== 3)
- validLocationsNoProvinceName.push(location);
- }
- if (validLocations.length === validLocationsNoProvinceName.length) {
- // We have not found province name.
- isACoast = false;
- }
- if (isACoast) {
- // We want to choose location in a coastal province. Let's remove province name.
- validLocations = validLocationsNoProvinceName;
- }
- }
-
- if (validLocations.length > 1) {
- if (this.cbSelectLocation) {
- return this.cbSelectLocation(validLocations, orderBuilding.power, orderBuilding.type, orderBuilding.path);
- } else {
- Diplog.warn(`Forced to select first valid location.`);
- validLocations = [validLocations[0]];
- }
- }
- let orderBuildingType = orderBuilding.type;
- if (lengthAfterClick === stepLength && orderBuildingType === 'M') {
- const moveOrderPath = ['M'].concat(orderBuilding.path, validLocations[0]);
- const moveTypes = UTILS.javascript.getTreeValue(this.game.ordersTree, moveOrderPath);
- if (moveTypes !== null) {
- if (moveTypes.length === 2) {
- // This move can be done either regularly or VIA a fleet. Let user choose.
- return this.cbSelectVia(validLocations[0], orderBuilding.power, orderBuilding.path);
- } else {
- orderBuildingType = moveTypes[0];
- }
- }
- }
- this.clickedID = svgPath.id;
-
- this.cleanBuildingView();
- if (lengthAfterClick < stepLength)
- this.renderBuildingView(validLocations[0]);
- extendOrderBuilding(
- orderBuilding.power, orderBuildingType, orderBuilding.path, validLocations[0],
- this.cbOrderBuilding, this.cbOrderBuilt, this.cbError
- );
-
- }
-
- getPathFromProvince(province) {
- let path = this.svg.getElementById(this.provinceNameToMapID(province.name));
- if (!path) {
- for (let alias of province.aliases) {
- path = this.svg.getElementById(this.provinceNameToMapID(alias));
- if (path)
- break;
- }
- }
- return path;
- }
-
- onProvinceClick(event) {
- this.handleSvgPath(event.target);
- }
-
- onLabelClick(event) {
- const province = this.mapData.getProvince(event.target.textContent);
- if (province) {
- const path = this.getPathFromProvince(province);
- if (path)
- this.handleSvgPath(path);
- }
- }
-
- onUnitClick(event) {
- const province = this.mapData.getProvince(event.target.getAttribute('diplomacyUnit'));
- if (province) {
- let path = this.getPathFromProvince(province);
- if (!path && province.isCoast())
- path = this.svg.getElementById(this.provinceNameToMapID(province.parent.name));
- if (path) {
- this.handleSvgPath(path);
- }
- }
- }
-
- cleanBuildingView() {
- if (this.clickedID) {
- const path = this.svg.getElementById(this.clickedID);
- if (path)
- path.setAttribute('class', this.provinceColors[this.clickedID]);
- }
- for (let neighborName of this.clickedNeighbors) {
- const province = this.mapData.getProvince(neighborName);
- if (!province)
- continue;
- const path = this.getPathFromProvince(province);
- if (path)
- path.setAttribute('class', this.provinceColors[path.id]);
- }
- this.clickedNeighbors = [];
- }
-
- renderBuildingView(extraLocation) {
- if (this.clickedID) {
- const path = this.svg.getElementById(this.clickedID);
- if (path)
- path.setAttribute('class', 'provinceRed');
- }
- const selectedPath = [this.orderBuilding.type].concat(this.orderBuilding.path);
- if (extraLocation)
- selectedPath.push(extraLocation);
- const possibleNeighbors = UTILS.javascript.getTreeValue(this.game.ordersTree, selectedPath);
- if (!possibleNeighbors)
- return;
- this.clickedNeighbors = possibleNeighbors.map(neighbor => parseLocation(neighbor));
- if (this.clickedNeighbors.length) {
- for (let neighbor of this.clickedNeighbors) {
- let neighborProvince = this.mapData.getProvince(neighbor);
- if (!neighborProvince)
- throw new Error('Unknown neighbor province ' + neighbor);
- let path = this.getPathFromProvince(neighborProvince);
- if (!path && neighborProvince.isCoast())
- path = this.getPathFromProvince(neighborProvince.parent);
- if (!path)
- throw new Error(`Unable to find SVG path related to province ${neighborProvince.name}.`);
- path.setAttribute('class', neighborProvince.isWater() ? 'provinceBlue' : 'provinceGreen');
- }
- }
- }
-
- update(game, mapData, orderBuilding) {
- this.game = game;
- this.mapData = mapData;
- this.orderBuilding = orderBuilding;
- this.saveProvinceColors();
- // If there is a building path, then we are building, so we don't clean anything.
- this.cleanBuildingView();
- if (this.orderBuilding.path.length)
- this.renderBuildingView();
- // I don't yet know why I should place this here. Maybe because unit are re-rendered manually at every reloading ?
- $(`#${this.svg.parentNode.id} svg use[diplomacyUnit]`).click(this.onUnitClick);
- }
-
- init(game, mapData, orderBuilding) {
- $(`#${this.svg.parentNode.id} svg path`).click(this.onProvinceClick);
- $(`#${this.mapID('BriefLabelLayer')} text`).click(this.onLabelClick);
- this.update(game, mapData, orderBuilding);
- }
-
-}
diff --git a/diplomacy/web/src/gui/map/dom_past_map.js b/diplomacy/web/src/gui/map/dom_past_map.js
deleted file mode 100644
index eb44616..0000000
--- a/diplomacy/web/src/gui/map/dom_past_map.js
+++ /dev/null
@@ -1,114 +0,0 @@
-// ==============================================================================
-// Copyright (C) 2019 - Philip Paquette, Steven Bocco
-//
-// This program is free software: you can redistribute it and/or modify it under
-// the terms of the GNU Affero General Public License as published by the Free
-// Software Foundation, either version 3 of the License, or (at your option) any
-// later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Affero General Public License along
-// with this program. If not, see <https://www.gnu.org/licenses/>.
-// ==============================================================================
-import $ from "jquery";
-
-export class DOMPastMap {
-
- constructor(svgElement, onHover) {
- this.svg = svgElement;
- this.cbHover = onHover;
- this.game = null;
- this.orders = null;
- this.mapData = null;
- this.onProvinceHover = this.onProvinceHover.bind(this);
- this.onLabelHover = this.onLabelHover.bind(this);
- this.onUnitHover = this.onUnitHover.bind(this);
- }
-
- provinceNameToMapID(name) {
- return `_${name.toLowerCase()}___${this.svg.parentNode.id}`;
- }
-
- mapID(id) {
- return `${id}___${this.svg.parentNode.id}`;
- }
-
- onHover(name) {
- const orders = [];
- if (this.orders) {
- for (let powerOrders of Object.values(this.orders)) {
- if (powerOrders) {
- for (let order of powerOrders) {
- const pieces = order.split(/ +/);
- if (pieces[1].slice(0, 3) === name.toUpperCase().slice(0, 3))
- orders.push(order);
- }
- }
- }
- }
- return orders;
- }
-
- handleSvgPath(svgPath) {
- const province = this.mapData.getProvince(svgPath.id);
- if (province) {
- this.cbHover(province.name, this.onHover(province.name));
- }
- }
-
- getPathFromProvince(province) {
- let path = this.svg.getElementById(this.provinceNameToMapID(province.name));
- if (!path) {
- for (let alias of province.aliases) {
- path = this.svg.getElementById(this.provinceNameToMapID(alias));
- if (path)
- break;
- }
- }
- return path;
- }
-
- onProvinceHover(event) {
- this.handleSvgPath(event.target);
- }
-
- onLabelHover(event) {
- const province = this.mapData.getProvince(event.target.textContent);
- if (province) {
- const path = this.getPathFromProvince(province);
- if (path)
- this.handleSvgPath(path);
- }
- }
-
- onUnitHover(event) {
- const province = this.mapData.getProvince(event.target.getAttribute('diplomacyUnit'));
- if (province) {
- let path = this.getPathFromProvince(province);
- if (!path && province.isCoast())
- path = this.svg.getElementById(this.provinceNameToMapID(province.parent.name));
- if (path) {
- this.handleSvgPath(path);
- }
- }
- }
-
- update(game, mapData, orders) {
- this.game = game;
- this.mapData = mapData;
- this.orders = orders;
- // I don't yet know why I should place this here. Maybe because unit are re-rendered manually at every reloading ?
- $(`#${this.svg.parentNode.id} svg use[diplomacyUnit]`).hover(this.onUnitHover);
- }
-
- init(game, mapData, orders) {
- $(`#${this.svg.parentNode.id} svg path`).hover(this.onProvinceHover).mouseleave(() => this.cbHover(null, null));
- $(`#${this.mapID('BriefLabelLayer')} text`).hover(this.onLabelHover);
- this.update(game, mapData, orders);
- }
-
-}
diff --git a/diplomacy/web/src/gui/map/map.jsx b/diplomacy/web/src/gui/map/map.jsx
deleted file mode 100644
index 1130563..0000000
--- a/diplomacy/web/src/gui/map/map.jsx
+++ /dev/null
@@ -1,94 +0,0 @@
-// ==============================================================================
-// Copyright (C) 2019 - Philip Paquette, Steven Bocco
-//
-// This program is free software: you can redistribute it and/or modify it under
-// the terms of the GNU Affero General Public License as published by the Free
-// Software Foundation, either version 3 of the License, or (at your option) any
-// later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Affero General Public License along
-// with this program. If not, see <https://www.gnu.org/licenses/>.
-// ==============================================================================
-import React from "react";
-import SVG from 'react-inlinesvg';
-import mapSVG from '../../standard.svg';
-import {Renderer} from "./renderer";
-import {MapData} from "../utils/map_data";
-import {DOMOrderBuilder} from "./dom_order_builder";
-import PropTypes from 'prop-types';
-import {DOMPastMap} from "./dom_past_map";
-
-export class Map extends React.Component {
- // id: ID of div wrapping SVG map.
- // mapInfo: dict
- // game: game engine
- // onError: callback(error)
- // showOrders: bool
-
- // orderBuilding: dict
- // onOrderBuilding: callback(powerName, orderBuildingPath)
- // onOrderBuilt: callback(powerName, orderString)
-
- constructor(props) {
- super(props);
- this.renderer = null;
- this.domOrderBuilder = null;
- this.domPastMap = null;
- this.initSVG = this.initSVG.bind(this);
- }
-
- initSVG() {
- const svg = document.getElementById(this.props.id).getElementsByTagName('svg')[0];
-
- const game = this.props.game;
- const mapData = new MapData(this.props.mapInfo, game);
- this.renderer = new Renderer(svg, game, mapData);
- this.renderer.render(this.props.showOrders, this.props.orders);
- if (this.props.orderBuilding) {
- this.domOrderBuilder = new DOMOrderBuilder(
- svg,
- this.props.onOrderBuilding, this.props.onOrderBuilt, this.props.onSelectLocation, this.props.onSelectVia,
- this.props.onError
- );
- this.domOrderBuilder.init(game, mapData, this.props.orderBuilding);
- } else if (this.props.onHover) {
- this.domPastMap = new DOMPastMap(svg, this.props.onHover);
- this.domPastMap.init(game, mapData, this.props.orders);
- }
- }
-
- render() {
- if (this.renderer) {
- const game = this.props.game;
- const mapData = new MapData(this.props.mapInfo, game);
- this.renderer.update(game, mapData, this.props.showOrders, this.props.orders);
- if (this.domOrderBuilder)
- this.domOrderBuilder.update(game, mapData, this.props.orderBuilding);
- else if (this.domPastMap)
- this.domPastMap.update(game, mapData, this.props.orders);
- }
- const divFactory = ((props, children) => <div id={this.props.id} {...props}>{children}</div>);
- return <SVG wrapper={divFactory} uniquifyIDs={true} uniqueHash={this.props.id} src={mapSVG}
- onLoad={this.initSVG} onError={err => this.props.onError(err.message)}>Game map</SVG>;
- }
-}
-
-Map.propTypes = {
- id: PropTypes.string,
- showOrders: PropTypes.bool,
- orders: PropTypes.objectOf(PropTypes.arrayOf(PropTypes.string)),
- onSelectLocation: PropTypes.func,
- onSelectVia: PropTypes.func,
- game: PropTypes.object,
- mapInfo: PropTypes.object,
- orderBuilding: PropTypes.object,
- onOrderBuilding: PropTypes.func,
- onOrderBuilt: PropTypes.func,
- onError: PropTypes.func,
- onHover: PropTypes.func,
-};
diff --git a/diplomacy/web/src/gui/map/renderer.js b/diplomacy/web/src/gui/map/renderer.js
deleted file mode 100644
index e2586af..0000000
--- a/diplomacy/web/src/gui/map/renderer.js
+++ /dev/null
@@ -1,615 +0,0 @@
-// ==============================================================================
-// Copyright (C) 2019 - Philip Paquette, Steven Bocco
-//
-// This program is free software: you can redistribute it and/or modify it under
-// the terms of the GNU Affero General Public License as published by the Free
-// Software Foundation, either version 3 of the License, or (at your option) any
-// later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-// details.
-//
-// You should have received a copy of the GNU Affero General Public License along
-// with this program. If not, see <https://www.gnu.org/licenses/>.
-// ==============================================================================
-import $ from "jquery";
-
-const ARMY = 'Army';
-const FLEET = 'Fleet';
-// SVG tag names.
-const PREFIX_TAG = 'jdipNS'.toLowerCase();
-const TAG_ORDERDRAWING = 'jdipNS:ORDERDRAWING'.toLowerCase();
-const TAG_POWERCOLORS = 'jdipNS:POWERCOLORS'.toLowerCase();
-const TAG_POWERCOLOR = 'jdipNS:POWERCOLOR'.toLowerCase();
-const TAG_SYMBOLSIZE = 'jdipNS:SYMBOLSIZE'.toLowerCase();
-const TAG_PROVINCE_DATA = 'jdipNS:PROVINCE_DATA'.toLowerCase();
-const TAG_PROVINCE = 'jdipNS:PROVINCE'.toLowerCase();
-const TAG_UNIT = 'jdipNS:UNIT'.toLowerCase();
-const TAG_DISLODGED_UNIT = 'jdipNS:DISLODGED_UNIT'.toLowerCase();
-const TAG_SUPPLY_CENTER = 'jdipNS:SUPPLY_CENTER'.toLowerCase();
-const TAG_DISPLAY = 'jdipNS:DISPLAY'.toLowerCase();
-
-function attr(node, name) {
- return node.attributes[name].value;
-}
-
-function offset(floatString, offset) {
- return "" + (parseFloat(floatString) + offset);
-}
-
-export class Renderer {
- constructor(svgDomElement, game, mapData) {
- this.svg = svgDomElement;
- this.game = game;
- this.mapData = mapData;
- this.metadata = {
- color: {},
- symbol_size: {},
- orders: {},
- coord: {}
- };
- this.initialInfluences = {};
- this.__load_metadata();
- this.__save_initial_influences();
- }
-
- __hashed_id(id) {
- return `${id}___${this.svg.parentNode.id}`;
- }
-
- __svg_element_from_id(id) {
- const hashedID = this.__hashed_id(id);
- const element = this.svg.getElementById(hashedID);
- if (!element)
- throw new Error(`Unable to find ID ${id} (looked for hashed ID ${hashedID})`);
- return element;
- }
-
- __load_metadata() {
- // Order drawings.
- const order_drawings = this.svg.getElementsByTagName(TAG_ORDERDRAWING);
- if (!order_drawings.length)
- throw new Error('Unable to find order drawings (tag ' + TAG_ORDERDRAWING + ') in SVG map.');
- for (let order_drawing of order_drawings) {
- for (let child_node of order_drawing.childNodes) {
- if (child_node.nodeName === TAG_POWERCOLORS) {
- // Power colors.
- for (let power_color of child_node.childNodes) {
- if (power_color.nodeName === TAG_POWERCOLOR) {
- this.metadata.color[attr(power_color, 'power').toUpperCase()] = attr(power_color, 'color');
- }
- }
- } else if (child_node.nodeName === TAG_SYMBOLSIZE) {
- // Symbol size.
- this.metadata.symbol_size[attr(child_node, 'name')] = [attr(child_node, 'height'), attr(child_node, 'width')];
- } else if (child_node.nodeName.startsWith(PREFIX_TAG)) {
- // Order type.
- const order_type = child_node.nodeName.replace(PREFIX_TAG + ':', '');
- this.metadata.orders[order_type] = {};
- for (let attribute of child_node.attributes) {
- if (!attribute.name.includes(':')) {
- this.metadata.orders[order_type][attribute.name] = attribute.value;
- }
- }
- }
- }
- }
- // Object coordinates.
- const all_province_data = this.svg.getElementsByTagName(TAG_PROVINCE_DATA);
- if (!all_province_data.length)
- throw new Error('Unable to find province data in SVG map (tag ' + TAG_PROVINCE_DATA + ').');
- for (let province_data of all_province_data) {
- for (let child_node of province_data.childNodes) {
- // Province.
- if (child_node.nodeName === TAG_PROVINCE) {
- const province = attr(child_node, 'name').toUpperCase().replace('-', '/');
- this.metadata.coord[province] = {};
- for (let coord_node of child_node.childNodes) {
- if (coord_node.nodeName === TAG_UNIT) {
- this.metadata.coord[province].unit = [attr(coord_node, 'x'), attr(coord_node, 'y')];
- } else if (coord_node.nodeName === TAG_DISLODGED_UNIT) {
- this.metadata.coord[province].disl = [attr(coord_node, 'x'), attr(coord_node, 'y')];
- } else if (coord_node.nodeName === TAG_SUPPLY_CENTER) {
- this.metadata.coord[province].sc = [attr(coord_node, 'x'), attr(coord_node, 'y')];
- }
- }
- }
- }
- }
- // Deleting.
- this.svg.removeChild(this.svg.getElementsByTagName(TAG_DISPLAY)[0]);
- this.svg.removeChild(this.svg.getElementsByTagName(TAG_ORDERDRAWING)[0]);
- this.svg.removeChild(this.svg.getElementsByTagName(TAG_PROVINCE_DATA)[0]);
-
- // (this code was previously in render())
- // Removing mouse layer.
- this.svg.removeChild(this.__svg_element_from_id('MouseLayer'));
- }
-
- __save_initial_influences() {
- const mapLayer = this.__svg_element_from_id('MapLayer');
- if (!mapLayer)
- throw new Error('Unable to find map layer.');
- for (let element of mapLayer.childNodes) {
- if (element.tagName === 'path') {
- this.initialInfluences[element.id] = element.getAttribute('class');
- }
- }
- }
-
- __restore_initial_influences() {
- for (let id of Object.keys(this.initialInfluences)) {
- const className = this.initialInfluences[id];
- this.svg.getElementById(id).setAttribute('class', className);
- }
- }
-
- __set_current_phase() {
- const current_phase = (this.game.phase[0] === '?' || this.game.phase === 'COMPLETED') ? 'FINAL' : this.game.phase;
- const phase_display = this.__svg_element_from_id('CurrentPhase');
- if (phase_display) {
- phase_display.childNodes[0].nodeValue = current_phase;
- }
- }
-
- __set_note(note1, note2) {
- note1 = note1 || '';
- note2 = note2 || '';
- const display_note1 = this.__svg_element_from_id('CurrentNote');
- const display_note2 = this.__svg_element_from_id('CurrentNote2');
- if (display_note1)
- display_note1.childNodes[0].nodeValue = note1;
- if (display_note2)
- display_note2.childNodes[0].nodeValue = note2;
- }
-
- __add_unit(unit, power_name, is_dislogged) {
- const split_unit = unit.split(/ +/);
- const unit_type = split_unit[0];
- const loc = split_unit[1];
- const dislogged_type = is_dislogged ? 'disl' : 'unit';
- const symbol = unit_type === 'F' ? FLEET : ARMY;
- const loc_x = offset(this.metadata.coord[loc][dislogged_type][0], -11.5);
- const loc_y = offset(this.metadata.coord[loc][dislogged_type][1], -10.0);
- // Helpful link about creating SVG elements: https://stackoverflow.com/a/25949237
- const node = document.createElementNS("http://www.w3.org/2000/svg", 'use');
- node.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#' + this.__hashed_id((is_dislogged ? 'Dislodged' : '') + symbol));
- node.setAttribute('x', loc_x);
- node.setAttribute('y', loc_y);
- node.setAttribute('height', this.metadata.symbol_size[symbol][0]);
- node.setAttribute('width', this.metadata.symbol_size[symbol][1]);
- node.setAttribute('class', 'unit' + power_name.toLowerCase());
- node.setAttribute('diplomacyUnit', loc);
- const parent_node = this.__svg_element_from_id(is_dislogged ? 'DislodgedUnitLayer' : 'UnitLayer');
- if (parent_node)
- parent_node.appendChild(node);
- }
-
- __add_supply_center(loc, power_name) {
- const symbol = 'SupplyCenter';
- const loc_x = offset(this.metadata.coord[loc]['sc'][0], -8.5);
- const loc_y = offset(this.metadata.coord[loc]['sc'][1], -11.0);
- const node = document.createElementNS("http://www.w3.org/2000/svg", 'use');
- node.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#' + this.__hashed_id(symbol));
- node.setAttribute('x', loc_x);
- node.setAttribute('y', loc_y);
- node.setAttribute('height', this.metadata.symbol_size[symbol][0]);
- node.setAttribute('width', this.metadata.symbol_size[symbol][1]);
- node.setAttribute('class', power_name ? ('sc' + power_name.toLowerCase()) : 'scnopower');
- const parent_node = this.__svg_element_from_id('SupplyCenterLayer');
- if (parent_node)
- parent_node.appendChild(node);
- }
-
- __set_influence(loc, power_name) {
- loc = loc.toUpperCase().substr(0, 3);
- if (!['LAND', 'COAST'].includes(this.mapData.getProvince(loc).type))
- return;
- const path = this.__svg_element_from_id('_' + loc.toLowerCase());
- if (!path || path.nodeName !== 'path') {
- throw new Error(`Unable to find SVG path for loc ${loc}, got ${path ? path.nodeName : '(nothing)'}`);
- }
- path.setAttribute('class', power_name ? power_name.toLowerCase() : 'nopower');
- }
-
- issueHoldOrder(loc, power_name) {
- const polygon_coord = [];
- const loc_x = offset(this.metadata['coord'][loc]['unit'][0], 8.5);
- const loc_y = offset(this.metadata['coord'][loc]['unit'][1], 9.5);
- for (let ofs of [
- [13.8, -33.3], [33.3, -13.8], [33.3, 13.8], [13.8, 33.3], [-13.8, 33.3],
- [-33.3, 13.8], [-33.3, -13.8], [-13.8, -33.3]]
- ) {
- polygon_coord.push(offset(loc_x, ofs[0]) + ',' + offset(loc_y, ofs[1]));
- }
- const g_node = document.createElementNS("http://www.w3.org/2000/svg", 'g');
- const poly_1 = document.createElementNS("http://www.w3.org/2000/svg", 'polygon');
- const poly_2 = document.createElementNS("http://www.w3.org/2000/svg", 'polygon');
- poly_1.setAttribute('stroke-width', '10');
- poly_1.setAttribute('class', 'varwidthshadow');
- poly_1.setAttribute('points', polygon_coord.join(' '));
- poly_2.setAttribute('stroke-width', '6');
- poly_2.setAttribute('class', 'varwidthorder');
- poly_2.setAttribute('points', polygon_coord.join(' '));
- poly_2.setAttribute('stroke', this.metadata['color'][power_name]);
- g_node.appendChild(poly_1);
- g_node.appendChild(poly_2);
- const orderLayer = this.__svg_element_from_id('Layer1');
- if (!orderLayer)
- throw new Error(`Unable to find svg order layer.`);
- orderLayer.appendChild(g_node);
- }
-
- issueMoveOrder(src_loc, dest_loc, power_name) {
- let src_loc_x = 0;
- let src_loc_y = 0;
- const phaseType = this.game.getPhaseType();
- if (phaseType === 'R') {
- src_loc_x = offset(this.metadata.coord[src_loc]['unit'][0], -2.5);
- src_loc_y = offset(this.metadata.coord[src_loc]['unit'][1], -2.5);
- } else {
- src_loc_x = offset(this.metadata.coord[src_loc]['unit'][0], 10);
- src_loc_y = offset(this.metadata.coord[src_loc]['unit'][1], 10);
- }
- let dest_loc_x = offset(this.metadata.coord[dest_loc]['unit'][0], 10);
- let dest_loc_y = offset(this.metadata.coord[dest_loc]['unit'][1], 10);
-
- // Adjusting destination
- const delta_x = parseFloat(dest_loc_x) - parseFloat(src_loc_x);
- const delta_y = parseFloat(dest_loc_y) - parseFloat(src_loc_y);
- const vector_length = Math.sqrt(delta_x * delta_x + delta_y * delta_y);
- dest_loc_x = '' + Math.round((parseFloat(src_loc_x) + (vector_length - 30.) / vector_length * delta_x) * 100.) / 100.;
- dest_loc_y = '' + Math.round((parseFloat(src_loc_y) + (vector_length - 30.) / vector_length * delta_y) * 100.) / 100.;
-
- // Creating nodes.
- const g_node = document.createElementNS("http://www.w3.org/2000/svg", 'g');
- const line_with_shadow = document.createElementNS("http://www.w3.org/2000/svg", 'line');
- const line_with_arrow = document.createElementNS("http://www.w3.org/2000/svg", 'line');
- line_with_shadow.setAttribute('x1', src_loc_x);
- line_with_shadow.setAttribute('y1', src_loc_y);
- line_with_shadow.setAttribute('x2', dest_loc_x);
- line_with_shadow.setAttribute('y2', dest_loc_y);
- line_with_shadow.setAttribute('class', 'varwidthshadow');
- line_with_shadow.setAttribute('stroke-width', '10');
- line_with_arrow.setAttribute('x1', src_loc_x);
- line_with_arrow.setAttribute('y1', src_loc_y);
- line_with_arrow.setAttribute('x2', dest_loc_x);
- line_with_arrow.setAttribute('y2', dest_loc_y);
- line_with_arrow.setAttribute('class', 'varwidthorder');
- line_with_arrow.setAttribute('marker-end', 'url(#' + this.__hashed_id('arrow') + ')');
- line_with_arrow.setAttribute('stroke', this.metadata.color[power_name]);
- line_with_arrow.setAttribute('stroke-width', '6');
- g_node.appendChild(line_with_shadow);
- g_node.appendChild(line_with_arrow);
- const orderLayer = this.__svg_element_from_id('Layer1');
- if (!orderLayer)
- throw new Error(`Unable to find svg order layer.`);
- orderLayer.appendChild(g_node);
- }
-
- issueSupportMoveOrder(loc, src_loc, dest_loc, power_name) {
- const loc_x = offset(this.metadata['coord'][loc]['unit'][0], 10);
- const loc_y = offset(this.metadata['coord'][loc]['unit'][1], 10);
- const src_loc_x = offset(this.metadata['coord'][src_loc]['unit'][0], 10);
- const src_loc_y = offset(this.metadata['coord'][src_loc]['unit'][1], 10);
- let dest_loc_x = offset(this.metadata['coord'][dest_loc]['unit'][0], 10);
- let dest_loc_y = offset(this.metadata['coord'][dest_loc]['unit'][1], 10);
-
- // Adjusting destination
- const delta_x = parseFloat(dest_loc_x) - parseFloat(src_loc_x);
- const delta_y = parseFloat(dest_loc_y) - parseFloat(src_loc_y);
- const vector_length = Math.sqrt(delta_x * delta_x + delta_y * delta_y);
- dest_loc_x = '' + Math.round((parseFloat(src_loc_x) + (vector_length - 30.) / vector_length * delta_x) * 100.) / 100.;
- dest_loc_y = '' + Math.round((parseFloat(src_loc_y) + (vector_length - 30.) / vector_length * delta_y) * 100.) / 100.;
-
- const g_node = document.createElementNS("http://www.w3.org/2000/svg", 'g');
- const path_with_shadow = document.createElementNS("http://www.w3.org/2000/svg", 'path');
- const path_with_arrow = document.createElementNS("http://www.w3.org/2000/svg", 'path');
- path_with_shadow.setAttribute('class', 'shadowdash');
- path_with_shadow.setAttribute('d', `M ${loc_x},${loc_y} C ${src_loc_x},${src_loc_y} ${src_loc_x},${src_loc_y} ${dest_loc_x},${dest_loc_y}`);
- path_with_arrow.setAttribute('class', 'supportorder');
- path_with_arrow.setAttribute('marker-end', 'url(#' + this.__hashed_id('arrow') + ')');
- path_with_arrow.setAttribute('stroke', this.metadata['color'][power_name]);
- path_with_arrow.setAttribute('d', `M ${loc_x},${loc_y} C ${src_loc_x},${src_loc_y} ${src_loc_x},${src_loc_y} ${dest_loc_x},${dest_loc_y}`);
- g_node.appendChild(path_with_shadow);
- g_node.appendChild(path_with_arrow);
- const orderLayer = this.__svg_element_from_id('Layer2');
- if (!orderLayer)
- throw new Error(`Unable to find svg order layer.`);
- orderLayer.appendChild(g_node);
- }
-
- issueSupportHoldOrder(loc, dest_loc, power_name) {
- const loc_x = offset(this.metadata['coord'][loc]['unit'][0], 10);
- const loc_y = offset(this.metadata['coord'][loc]['unit'][1], 10);
- let dest_loc_x = offset(this.metadata['coord'][dest_loc]['unit'][0], 10);
- let dest_loc_y = offset(this.metadata['coord'][dest_loc]['unit'][1], 10);
-
- const delta_x = parseFloat(dest_loc_x) - parseFloat(loc_x);
- const delta_y = parseFloat(dest_loc_y) - parseFloat(loc_y);
- const vector_length = Math.sqrt(delta_x * delta_x + delta_y * delta_y);
- dest_loc_x = '' + Math.round((parseFloat(loc_x) + (vector_length - 35.) / vector_length * delta_x) * 100.) / 100.;
- dest_loc_y = '' + Math.round((parseFloat(loc_y) + (vector_length - 35.) / vector_length * delta_y) * 100.) / 100.;
-
- const polygon_coord = [];
- const poly_loc_x = offset(this.metadata['coord'][dest_loc]['unit'][0], 8.5);
- const poly_loc_y = offset(this.metadata['coord'][dest_loc]['unit'][1], 9.5);
- for (let ofs of [
- [15.9, -38.3], [38.3, -15.9], [38.3, 15.9], [15.9, 38.3], [-15.9, 38.3], [-38.3, 15.9],
- [-38.3, -15.9], [-15.9, -38.3]
- ]) {
- polygon_coord.push(offset(poly_loc_x, ofs[0]) + ',' + offset(poly_loc_y, ofs[1]));
- }
- const g_node = document.createElementNS("http://www.w3.org/2000/svg", 'g');
- const shadow_line = document.createElementNS("http://www.w3.org/2000/svg", 'line');
- const support_line = document.createElementNS("http://www.w3.org/2000/svg", 'line');
- const shadow_poly = document.createElementNS("http://www.w3.org/2000/svg", 'polygon');
- const support_poly = document.createElementNS("http://www.w3.org/2000/svg", 'polygon');
- shadow_line.setAttribute('x1', loc_x);
- shadow_line.setAttribute('y1', loc_y);
- shadow_line.setAttribute('x2', dest_loc_x);
- shadow_line.setAttribute('y2', dest_loc_y);
- shadow_line.setAttribute('class', 'shadowdash');
- support_line.setAttribute('x1', loc_x);
- support_line.setAttribute('y1', loc_y);
- support_line.setAttribute('x2', dest_loc_x);
- support_line.setAttribute('y2', dest_loc_y);
- support_line.setAttribute('class', 'supportorder');
- support_line.setAttribute('stroke', this.metadata['color'][power_name]);
- shadow_poly.setAttribute('class', 'shadowdash');
- shadow_poly.setAttribute('points', polygon_coord.join(' '));
- support_poly.setAttribute('class', 'supportorder');
- support_poly.setAttribute('points', polygon_coord.join(' '));
- support_poly.setAttribute('stroke', this.metadata['color'][power_name]);
- g_node.appendChild(shadow_line);
- g_node.appendChild(support_line);
- g_node.appendChild(shadow_poly);
- g_node.appendChild(support_poly);
- const orderLayer = this.__svg_element_from_id('Layer2');
- if (!orderLayer)
- throw new Error(`Unable to find svg order layer.`);
- orderLayer.appendChild(g_node);
- }
-
- issueConvoyOrder(loc, src_loc, dest_loc, power_name) {
- const loc_x = offset(this.metadata['coord'][loc]['unit'][0], 10);
- const loc_y = offset(this.metadata['coord'][loc]['unit'][1], 10);
- const src_loc_x = offset(this.metadata['coord'][src_loc]['unit'][0], 10);
- const src_loc_y = offset(this.metadata['coord'][src_loc]['unit'][1], 10);
- let dest_loc_x = offset(this.metadata['coord'][dest_loc]['unit'][0], 10);
- let dest_loc_y = offset(this.metadata['coord'][dest_loc]['unit'][1], 10);
-
- const src_delta_x = parseFloat(src_loc_x) - parseFloat(loc_x);
- const src_delta_y = parseFloat(src_loc_y) - parseFloat(loc_y);
- const src_vector_length = Math.sqrt(src_delta_x * src_delta_x + src_delta_y * src_delta_y);
- const src_loc_x_1 = '' + Math.round((parseFloat(loc_x) + (src_vector_length - 30.) / src_vector_length * src_delta_x) * 100.) / 100.;
- const src_loc_y_1 = '' + Math.round((parseFloat(loc_y) + (src_vector_length - 30.) / src_vector_length * src_delta_y) * 100.) / 100.;
-
- let dest_delta_x = parseFloat(src_loc_x) - parseFloat(dest_loc_x);
- let dest_delta_y = parseFloat(src_loc_y) - parseFloat(dest_loc_y);
- let dest_vector_length = Math.sqrt(dest_delta_x * dest_delta_x + dest_delta_y * dest_delta_y);
- const src_loc_x_2 = '' + Math.round((parseFloat(dest_loc_x) + (dest_vector_length - 30.) / dest_vector_length * dest_delta_x) * 100.) / 100.;
- const src_loc_y_2 = '' + Math.round((parseFloat(dest_loc_y) + (dest_vector_length - 30.) / dest_vector_length * dest_delta_y) * 100.) / 100.;
-
- dest_delta_x = parseFloat(dest_loc_x) - parseFloat(src_loc_x);
- dest_delta_y = parseFloat(dest_loc_y) - parseFloat(src_loc_y);
- dest_vector_length = Math.sqrt(dest_delta_x * dest_delta_x + dest_delta_y * dest_delta_y);
- dest_loc_x = '' + Math.round((parseFloat(src_loc_x) + (dest_vector_length - 30.) / dest_vector_length * dest_delta_x) * 100.) / 100.;
- dest_loc_y = '' + Math.round((parseFloat(src_loc_y) + (dest_vector_length - 30.) / dest_vector_length * dest_delta_y) * 100.) / 100.;
-
- const triangle_coord = [];
- const triangle_loc_x = offset(this.metadata['coord'][src_loc]['unit'][0], 10);
- const triangle_loc_y = offset(this.metadata['coord'][src_loc]['unit'][1], 10);
- for (let ofs of [[0, -38.3], [33.2, 19.1], [-33.2, 19.1]]) {
- triangle_coord.push(offset(triangle_loc_x, ofs[0]) + ',' + offset(triangle_loc_y, ofs[1]));
- }
-
- const g_node = document.createElementNS("http://www.w3.org/2000/svg", 'g');
- const src_shadow_line = document.createElementNS("http://www.w3.org/2000/svg", 'line');
- const dest_shadow_line = document.createElementNS("http://www.w3.org/2000/svg", 'line');
- const src_convoy_line = document.createElementNS("http://www.w3.org/2000/svg", 'line');
- const dest_convoy_line = document.createElementNS("http://www.w3.org/2000/svg", 'line');
- const shadow_poly = document.createElementNS("http://www.w3.org/2000/svg", 'polygon');
- const convoy_poly = document.createElementNS("http://www.w3.org/2000/svg", 'polygon');
- src_shadow_line.setAttribute('x1', loc_x);
- src_shadow_line.setAttribute('y1', loc_y);
- src_shadow_line.setAttribute('x2', src_loc_x_1);
- src_shadow_line.setAttribute('y2', src_loc_y_1);
- src_shadow_line.setAttribute('class', 'shadowdash');
-
- dest_shadow_line.setAttribute('x1', src_loc_x_2);
- dest_shadow_line.setAttribute('y1', src_loc_y_2);
- dest_shadow_line.setAttribute('x2', dest_loc_x);
- dest_shadow_line.setAttribute('y2', dest_loc_y);
- dest_shadow_line.setAttribute('class', 'shadowdash');
-
- src_convoy_line.setAttribute('x1', loc_x);
- src_convoy_line.setAttribute('y1', loc_y);
- src_convoy_line.setAttribute('x2', src_loc_x_1);
- src_convoy_line.setAttribute('y2', src_loc_y_1);
- src_convoy_line.setAttribute('class', 'convoyorder');
- src_convoy_line.setAttribute('stroke', this.metadata['color'][power_name]);
-
- dest_convoy_line.setAttribute('x1', src_loc_x_2);
- dest_convoy_line.setAttribute('y1', src_loc_y_2);
- dest_convoy_line.setAttribute('x2', dest_loc_x);
- dest_convoy_line.setAttribute('y2', dest_loc_y);
- dest_convoy_line.setAttribute('class', 'convoyorder');
- dest_convoy_line.setAttribute('marker-end', 'url(#' + this.__hashed_id('arrow') + ')');
-
- dest_convoy_line.setAttribute('stroke', this.metadata['color'][power_name]);
-
- shadow_poly.setAttribute('class', 'shadowdash');
- shadow_poly.setAttribute('points', triangle_coord.join(' '));
-
- convoy_poly.setAttribute('class', 'convoyorder');
- convoy_poly.setAttribute('points', triangle_coord.join(' '));
- convoy_poly.setAttribute('stroke', this.metadata['color'][power_name]);
-
- g_node.appendChild(src_shadow_line);
- g_node.appendChild(dest_shadow_line);
- g_node.appendChild(src_convoy_line);
- g_node.appendChild(dest_convoy_line);
- g_node.appendChild(shadow_poly);
- g_node.appendChild(convoy_poly);
-
- const orderLayer = this.__svg_element_from_id('Layer2');
- if (!orderLayer)
- throw new Error(`Unable to find svg order layer.`);
- orderLayer.appendChild(g_node);
- }
-
- issueBuildOrder(unit_type, loc, power_name) {
- const loc_x = offset(this.metadata['coord'][loc]['unit'][0], -11.5);
- const loc_y = offset(this.metadata['coord'][loc]['unit'][1], -10.);
- const build_loc_x = offset(this.metadata['coord'][loc]['unit'][0], -20.5);
- const build_loc_y = offset(this.metadata['coord'][loc]['unit'][1], -20.5);
- const symbol = unit_type === 'A' ? ARMY : FLEET;
- const build_symbol = 'BuildUnit';
- const g_node = document.createElementNS("http://www.w3.org/2000/svg", 'g');
- const symbol_node = document.createElementNS("http://www.w3.org/2000/svg", 'use');
- const build_node = document.createElementNS("http://www.w3.org/2000/svg", 'use');
- symbol_node.setAttribute('x', loc_x);
- symbol_node.setAttribute('y', loc_y);
- symbol_node.setAttribute('height', this.metadata['symbol_size'][symbol][0]);
- symbol_node.setAttribute('width', this.metadata['symbol_size'][symbol][1]);
- symbol_node.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#' + this.__hashed_id(symbol));
- symbol_node.setAttribute('class', `unit${power_name.toLowerCase()}`);
- build_node.setAttribute('x', build_loc_x);
- build_node.setAttribute('y', build_loc_y);
- build_node.setAttribute('height', this.metadata['symbol_size'][build_symbol][0]);
- build_node.setAttribute('width', this.metadata['symbol_size'][build_symbol][1]);
- build_node.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#' + this.__hashed_id(build_symbol));
- g_node.appendChild(build_node);
- g_node.appendChild(symbol_node);
- const orderLayer = this.__svg_element_from_id('HighestOrderLayer');
- if (!orderLayer)
- throw new Error(`Unable to find svg order layer.`);
- orderLayer.appendChild(g_node);
- }
-
- issueDisbandOrder(loc) {
- const phaseType = this.game.getPhaseType();
- let loc_x = 0;
- let loc_y = 0;
- if (phaseType === 'R') {
- loc_x = offset(this.metadata['coord'][loc]['unit'][0], -29.);
- loc_y = offset(this.metadata['coord'][loc]['unit'][1], -27.5);
- } else {
- loc_x = offset(this.metadata['coord'][loc]['unit'][0], -16.5);
- loc_y = offset(this.metadata['coord'][loc]['unit'][1], -15.);
- }
- const symbol = 'RemoveUnit';
- const g_node = document.createElementNS("http://www.w3.org/2000/svg", 'g');
- const symbol_node = document.createElementNS("http://www.w3.org/2000/svg", 'use');
- symbol_node.setAttribute('x', loc_x);
- symbol_node.setAttribute('y', loc_y);
- symbol_node.setAttribute('height', this.metadata['symbol_size'][symbol][0]);
- symbol_node.setAttribute('width', this.metadata['symbol_size'][symbol][1]);
- symbol_node.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#' + this.__hashed_id(symbol));
- g_node.appendChild(symbol_node);
- const orderLayer = this.__svg_element_from_id('HighestOrderLayer');
- if (!orderLayer)
- throw new Error(`Unable to find svg order layer.`);
- orderLayer.appendChild(g_node);
- }
-
- clear() {
- this.__set_note('', '');
- $(`#${this.__hashed_id('DislodgedUnitLayer')} use`).remove();
- $(`#${this.__hashed_id('UnitLayer')} use`).remove();
- $(`#${this.__hashed_id('SupplyCenterLayer')} use`).remove();
- $(`#${this.__hashed_id('Layer1')} g`).remove();
- $(`#${this.__hashed_id('Layer2')} g`).remove();
- $(`#${this.__hashed_id('HighestOrderLayer')} g`).remove();
- this.__restore_initial_influences();
- }
-
- render(includeOrders, orders) {
- // Setting phase and note.
- const nb_centers = [];
- for (let power of Object.values(this.game.powers)) {
- if (!power.isEliminated())
- nb_centers.push([power.name.substr(0, 3), power.centers.length]);
- }
- // Sort nb_centers by descending number of centers.
- nb_centers.sort((a, b) => {
- return -(a[1] - b[1]) || a[0].localeCompare(b[0]);
- });
- const nb_centers_per_power = nb_centers.map((couple) => (couple[0] + ': ' + couple[1])).join(' ');
- this.__set_current_phase();
- this.__set_note(nb_centers_per_power, this.game.note);
-
- // Adding units, supply centers, influence and orders.
- const scs = new Set(this.mapData.supplyCenters);
- for (let power of Object.values(this.game.powers)) {
- for (let unit of power.units)
- this.__add_unit(unit, power.name, false);
- for (let unit of Object.keys(power.retreats))
- this.__add_unit(unit, power.name, true);
- for (let center of power.centers) {
- this.__add_supply_center(center, power.name);
- this.__set_influence(center, power.name);
- scs.delete(center);
- }
- if (!power.isEliminated()) {
- for (let loc of power.influence) {
- if (!this.mapData.supplyCenters.has(loc))
- this.__set_influence(loc, power.name);
- }
- }
-
- if (includeOrders) {
- const powerOrders = (orders && orders.hasOwnProperty(power.name) && orders[power.name]) || [];
- for (let order of powerOrders) {
- const tokens = order.split(/ +/);
- if (!tokens || tokens.length < 3)
- continue;
- const unit_loc = tokens[1];
- if (tokens[2] === 'H')
- this.issueHoldOrder(unit_loc, power.name);
- else if (tokens[2] === '-') {
- const destLoc = tokens[tokens.length - (tokens[tokens.length - 1] === 'VIA' ? 2 : 1)];
- this.issueMoveOrder(unit_loc, destLoc, power.name);
- } else if (tokens[2] === 'S') {
- const destLoc = tokens[tokens.length - 1];
- if (tokens.includes('-')) {
- const srcLoc = tokens[4];
- this.issueSupportMoveOrder(unit_loc, srcLoc, destLoc, power.name);
- } else {
- this.issueSupportHoldOrder(unit_loc, destLoc, power.name);
- }
- } else if (tokens[2] === 'C') {
- const srcLoc = tokens[4];
- const destLoc = tokens[tokens.length - 1];
- if ((srcLoc !== destLoc) && (tokens.includes('-'))) {
- this.issueConvoyOrder(unit_loc, srcLoc, destLoc, power.name);
- }
- } else if (tokens[2] === 'B') {
- this.issueBuildOrder(tokens[0], unit_loc, power.name);
- } else if (tokens[2] === 'D') {
- this.issueDisbandOrder(unit_loc);
- } else if (tokens[2] === 'R') {
- const srcLoc = tokens[1];
- const destLoc = tokens[3];
- this.issueMoveOrder(srcLoc, destLoc, power.name);
- } else {
- throw new Error(`Unknown error to render (${order}).`);
- }
- }
- }
- }
- // Adding remaining supply centers.
- for (let remainingCenter of scs)
- this.__add_supply_center(remainingCenter, null);
- }
-
- update(game, mapData, showOrders, orders) {
- this.game = game;
- this.mapData = mapData;
- this.clear();
- this.render(showOrders, orders);
- }
-}