diff options
author | notoraptor <stevenbocco@gmail.com> | 2019-08-01 15:53:23 -0400 |
---|---|---|
committer | Philip Paquette <pcpaquette@gmail.com> | 2019-08-01 16:32:55 -0400 |
commit | 891fb62a77b9a86f2bc71cc02a82089412982b2f (patch) | |
tree | 7152ec4ef8186741695a921d6cc7bac78102b0dd /diplomacy/web/src/gui/map | |
parent | 904ea5bcfab0ffe2b87d00fd0b938a8907c44842 (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.js | 278 | ||||
-rw-r--r-- | diplomacy/web/src/gui/map/dom_past_map.js | 114 | ||||
-rw-r--r-- | diplomacy/web/src/gui/map/map.jsx | 94 | ||||
-rw-r--r-- | diplomacy/web/src/gui/map/renderer.js | 615 |
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); - } -} |