From 891fb62a77b9a86f2bc71cc02a82089412982b2f Mon Sep 17 00:00:00 2001
From: notoraptor <stevenbocco@gmail.com>
Date: Thu, 1 Aug 2019 15:53:23 -0400
Subject: 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.
---
 diplomacy/web/src/gui/map/dom_order_builder.js | 278 -------------------------
 1 file changed, 278 deletions(-)
 delete mode 100644 diplomacy/web/src/gui/map/dom_order_builder.js

(limited to 'diplomacy/web/src/gui/map/dom_order_builder.js')

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);
-    }
-
-}
-- 
cgit v1.2.3