aboutsummaryrefslogtreecommitdiff
path: root/diplomacy/web/src/gui/map/dom_order_builder.js
diff options
context:
space:
mode:
Diffstat (limited to 'diplomacy/web/src/gui/map/dom_order_builder.js')
-rw-r--r--diplomacy/web/src/gui/map/dom_order_builder.js278
1 files changed, 0 insertions, 278 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);
- }
-
-}