From 5c3bd9b3802e2001a7e77baf2911386135a03839 Mon Sep 17 00:00:00 2001 From: notoraptor Date: Wed, 14 Aug 2019 12:22:22 -0400 Subject: [Web] Integrated new maps on the web interface - Fixed bug with incorrect dislodged unit on pure map - [python] Make sure dummy powers are registered only for standard maps. - Hardcoded supply centers into SVG files. - Removed supply centers CSS classes. - Update positions for units and dislodged units on all maps. - Converted SVGs to React. - Removed "sym" classes and hardcode related styles into symbol definitions. - Reordered map list (standard at top, then other ones in alphabetical order) - Displayed + button for all maps and disable it for maps without variants. - Minified generated code when converting SVG files to React. - [web] Added ability to hide/display map abbreviations. --- diplomacy/web/src/gui/maps/standard/SvgStandard.js | 761 +-------------------- 1 file changed, 19 insertions(+), 742 deletions(-) (limited to 'diplomacy/web/src/gui/maps/standard/SvgStandard.js') diff --git a/diplomacy/web/src/gui/maps/standard/SvgStandard.js b/diplomacy/web/src/gui/maps/standard/SvgStandard.js index 87c6217..eb4104e 100644 --- a/diplomacy/web/src/gui/maps/standard/SvgStandard.js +++ b/diplomacy/web/src/gui/maps/standard/SvgStandard.js @@ -1,743 +1,20 @@ -// ============================================================================== -// 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 . -// ============================================================================== -/** Generated using svg_to_react.py with parameters: -Namespace(actionable=['MouseLayer'], input='src/diplomacy/maps/svg/standard.svg', name='SvgStandard', output='src/gui/maps/', remove=None) +/** +============================================================================== +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 . +============================================================================== **/ -import React from 'react'; -import PropTypes from 'prop-types'; -import "./SvgStandard.css"; -import {Game} from "../../../diplomacy/engine/game"; -import {MapData} from "../../utils/map_data"; -import {Unit} from "./unit"; -import {SupplyCenter} from "./supplyCenter"; -import {Hold} from "./hold"; -import {Move} from "./move"; -import {SupportMove} from "./supportMove"; -import {SupportHold} from "./supportHold"; -import {Convoy} from "./convoy"; -import {Build} from "./build"; -import {Disband} from "./disband"; -import {UTILS} from "../../../diplomacy/utils/utils"; -import {Diplog} from "../../../diplomacy/utils/diplog"; -import {extendOrderBuilding} from "../../utils/order_building"; - -function setInfluence(classes, mapData, loc, power_name) { - loc = loc.toUpperCase().substr(0, 3); - if (!['LAND', 'COAST'].includes(mapData.getProvince(loc).type)) - return; - const id = '_' + loc.toLowerCase(); - if (!classes.hasOwnProperty(id)) - throw new Error(`Unable to find SVG path for loc ${id}`); - classes[id] = power_name ? power_name.toLowerCase() : 'nopower'; -} - -function getClickedID(event) { - let node = event.target; - if (!node.id && node.parentNode.id && node.parentNode.tagName === 'g') - node = node.parentNode; - let id = node.id; - return id ? id.substr(0, 3) : null; -} - -function parseLocation(txt) { - if (txt.length > 2 && txt[1] === ' ' && ['A', 'F'].includes(txt[0])) - return txt.substr(2); - return txt; -} - -export class SvgStandard extends React.Component { - constructor(props) { - super(props); - this.onClick = this.onClick.bind(this); - this.onHover = this.onHover.bind(this); - } - onClick(event) { - if (this.props.orderBuilding) - return this.handleClickedID(getClickedID(event)); - } - onHover(event) { - return this.handleHoverID(getClickedID(event)); - } - handleClickedID(id) { - const orderBuilding = this.props.orderBuilding; - if (!orderBuilding.builder) - return this.props.onError('No orderable locations.'); - const province = this.props.mapData.getProvince(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.props.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.props.onError(error); - } - } - if (!validLocations.length) - return this.props.onError('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.props.onSelectLocation) { - return this.props.onSelectLocation(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.props.game.ordersTree, moveOrderPath); - if (moveTypes !== null) { - if (moveTypes.length === 2 && this.props.onSelectVia) { - // This move can be done either regularly or VIA a fleet. Let user choose. - return this.props.onSelectVia(validLocations[0], orderBuilding.power, orderBuilding.path); - } else { - orderBuildingType = moveTypes[0]; - } - } - } - extendOrderBuilding( - orderBuilding.power, orderBuildingType, orderBuilding.path, validLocations[0], - this.props.onOrderBuilding, this.props.onOrderBuilt, this.props.onError - ); - } - handleHoverID(id) { - if (this.props.onHover) { - const province = this.props.mapData.getProvince(id); - if (province) { - this.props.onHover(province.name, this.getRelatedOrders(province.name)); - } - } - } - getRelatedOrders(name) { - const orders = []; - if (this.props.orders) { - for (let powerOrders of Object.values(this.props.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; - } - getNeighbors(extraLocation) { - const selectedPath = [this.props.orderBuilding.type].concat(this.props.orderBuilding.path); - if (extraLocation) - selectedPath.push(extraLocation); - const possibleNeighbors = UTILS.javascript.getTreeValue(this.props.game.ordersTree, selectedPath); - const neighbors = possibleNeighbors ? possibleNeighbors.map(neighbor => parseLocation(neighbor)) : []; - return neighbors.length ? neighbors: null; - } - render() { - const classes = {"_ank":"nopower","_arm":"nopower","_con":"nopower","_mos":"nopower","_sev":"nopower","_stp":"nopower","_syr":"nopower","_ukr":"nopower","_lvn":"nopower","_war":"nopower","_pru":"nopower","_sil":"nopower","_ber":"nopower","_kie":"nopower","_ruh":"nopower","_mun":"nopower","_rum":"nopower","_bul":"nopower","_gre":"nopower","_smy":"nopower","_alb":"nopower","_ser":"nopower","_bud":"nopower","_gal":"nopower","_vie":"nopower","_boh":"nopower","_tyr":"nopower","_tri":"nopower","_fin":"nopower","_swe":"nopower","_nwy":"nopower","_den":"nopower","_hol":"nopower","_bel":"nopower","_swi":"impassable","_ven":"nopower","_pie":"nopower","_tus":"nopower","_rom":"nopower","_apu":"nopower","_nap":"nopower","_bur":"nopower","_mar":"nopower","_gas":"nopower","_pic":"nopower","_par":"nopower","_bre":"nopower","_spa":"nopower","_por":"nopower","_naf":"nopower","_tun":"nopower","_lon":"nopower","_wal":"nopower","_lvp":"nopower","_yor":"nopower","_edi":"nopower","_cly":"nopower","unplayable":"neutral","unplayable_water":"water","_nat":"water","_nrg":"water","_bar":"water","_bot":"water","_bal":"water","denmark_water":"water","_ska":"water","_hel":"water","_nth":"water","_eng":"water","_iri":"water","_mid":"water","_wes":"water","_gol":"water","_tyn":"water","_adr":"water","_ion":"water","_aeg":"water","_eas":"water","constantinople_water":"water","_bla":"water","BriefLabelLayer":"labeltext24","CurrentNote":"currentnotetext","CurrentNote2":"currentnotetext","CurrentPhase":"currentphasetext","MouseLayer":"invisibleContent"}; - const game = this.props.game; - const mapData = this.props.mapData; - const orders = this.props.orders; - - //// Current phase. - const current_phase = (game.phase[0] === '?' || game.phase === 'COMPLETED') ? 'FINAL' : game.phase; - - //// Notes. - const nb_centers = []; - for (let power of Object.values(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(' '); - const note = game.note; - - //// Adding units, supply centers, influence and orders. - const scs = new Set(mapData.supplyCenters); - const renderedUnits = []; - const renderedDislodgedUnits = []; - const renderedSupplyCenters = []; - const renderedOrders = []; - const renderedOrders2 = []; - const renderedHighestOrders = []; - for (let power of Object.values(game.powers)) { - for (let unit of power.units) { - renderedUnits.push(); - } - for (let unit of Object.keys(power.retreats)) { - renderedDislodgedUnits.push(); - } - for (let center of power.centers) { - renderedSupplyCenters.push(); - setInfluence(classes, mapData, center, power.name); - scs.delete(center); - } - if (!power.isEliminated()) { - for (let loc of power.influence) { - if (!mapData.supplyCenters.has(loc)) - setInfluence(classes, mapData, loc, power.name); - } - } - - if (orders) { - 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') { - renderedOrders.push(); - } else if (tokens[2] === '-') { - const destLoc = tokens[tokens.length - (tokens[tokens.length - 1] === 'VIA' ? 2 : 1)]; - renderedOrders.push(); - } else if (tokens[2] === 'S') { - const destLoc = tokens[tokens.length - 1]; - if (tokens.includes('-')) { - const srcLoc = tokens[4]; - renderedOrders2.push(); - } else { - renderedOrders2.push(); - } - } else if (tokens[2] === 'C') { - const srcLoc = tokens[4]; - const destLoc = tokens[tokens.length - 1]; - if ((srcLoc !== destLoc) && (tokens.includes('-'))) { - renderedOrders2.push(); - } - } else if (tokens[2] === 'B') { - renderedHighestOrders.push(); - } else if (tokens[2] === 'D') { - renderedHighestOrders.push(); - } else if (tokens[2] === 'R') { - const srcLoc = tokens[1]; - const destLoc = tokens[3]; - renderedOrders.push(); - } else { - throw new Error(`Unknown error to render (${order}).`); - } - } - } - } - // Adding remaining supply centers. - for (let remainingCenter of scs) { - renderedSupplyCenters.push(); - } - - if (this.props.orderBuilding && this.props.orderBuilding.path.length) { - const clicked = parseLocation(this.props.orderBuilding.path[0]); - const province = this.props.mapData.getProvince(clicked); - if (!province) - throw new Error(('Unknown clicked province ' + clicked)); - const clickedID = province.getID(classes); - if (!clicked) - throw new Error(`Unknown path (${clickedID}) for province (${clicked}).`); - classes[clickedID] = 'provinceRed'; - const neighbors = this.getNeighbors(); - if (neighbors) { - for (let neighbor of neighbors) { - const neighborProvince = this.props.mapData.getProvince(neighbor); - if (!neighborProvince) - throw new Error('Unknown neighbor province ' + neighbor); - const neighborID = neighborProvince.getID(classes); - if (!neighborID) - throw new Error(`Unknown neoghbor path (${neighborID}) for province (${neighbor}).`); - classes[neighborID] = neighborProvince.isWater() ? 'provinceBlue' : 'provinceGreen'; - } - } - } - - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {renderedSupplyCenters} - - - - {renderedOrders2} - - - {renderedOrders} - - - - {renderedUnits} - - - {renderedDislodgedUnits} - - - {renderedHighestOrders} - - - SWI - ADR - AEG - ALB - ANK - APU - ARM - BAL - BAR - BEL - BER - BLA - BOH - BRE - BUD - BUL - BUR - CLY - CON - DEN - EAS - EDI - ENG - FIN - GAL - GAS - GRE - BOT - LYO - HEL - HOL - ION - IRI - KIE - LON - LVN - LVP - MAR - MAO - MOS - MUN - NAF - NAP - NAO - NTH - NWY - NWG - PAR - PIC - PIE - POR - PRU - ROM - RUH - RUM - SER - SEV - SIL - SKA - SMY - SPA - STP - SWE - SYR - TRI - TUN - TUS - TYR - TYS - UKR - VEN - VIE - WAL - WAR - WES - YOR - - - - {nb_centers_per_power ? nb_centers_per_power : ''} - - - {note ? note : ''} - - - {current_phase} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); - } -} -SvgStandard.propTypes = { - game: PropTypes.instanceOf(Game).isRequired, - mapData: PropTypes.instanceOf(MapData).isRequired, - orders: PropTypes.object, - onHover: PropTypes.func, - onError: PropTypes.func.isRequired, - onSelectLocation: PropTypes.func, - onSelectVia: PropTypes.func, - onOrderBuilding: PropTypes.func, - onOrderBuilt: PropTypes.func, - orderBuilding: PropTypes.object -}; +/** Generated with parameters: Namespace(input='src/diplomacy/maps/svg/standard.svg', name='SvgStandard', output='src/gui/maps/standard/') **/ + import React from 'react'; import PropTypes from 'prop-types'; import './SvgStandard.css'; import {Coordinates, SymbolSizes, Colors} from "./SvgStandardMetadata"; import {getClickedID, parseLocation, setInfluence} from "../common/common"; import {Game} from "../../../diplomacy/engine/game"; import {MapData} from "../../utils/map_data"; import {UTILS} from "../../../diplomacy/utils/utils"; import {Diplog} from "../../../diplomacy/utils/diplog"; import {extendOrderBuilding} from "../../utils/order_building"; import {Unit} from "../common/unit"; import {Hold} from "../common/hold"; import {Move} from "../common/move"; import {SupportMove} from "../common/supportMove"; import {SupportHold} from "../common/supportHold"; import {Convoy} from "../common/convoy"; import {Build} from "../common/build"; import {Disband} from "../common/disband"; export class SvgStandard extends React.Component { constructor(props) { super(props); this.onClick = this.onClick.bind(this); this.onHover = this.onHover.bind(this); } onClick(event) { if (this.props.orderBuilding) return this.handleClickedID(getClickedID(event)); } onHover(event) { return this.handleHoverID(getClickedID(event)); } handleClickedID(id) { const orderBuilding = this.props.orderBuilding; if (!orderBuilding.builder) return this.props.onError('No orderable locations.'); const province = this.props.mapData.getProvince(id); if (!province) throw new Error(`Cannot find a province named ${id}`); 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.props.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.props.onError(error); } } if (!validLocations.length) return this.props.onError('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.props.onSelectLocation) { return this.props.onSelectLocation(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.props.game.ordersTree, moveOrderPath); if (moveTypes !== null) { if (moveTypes.length === 2 && this.props.onSelectVia) { /* This move can be done either regularly or VIA a fleet. Let user choose. */ return this.props.onSelectVia(validLocations[0], orderBuilding.power, orderBuilding.path); } else { orderBuildingType = moveTypes[0]; } } } extendOrderBuilding( orderBuilding.power, orderBuildingType, orderBuilding.path, validLocations[0], this.props.onOrderBuilding, this.props.onOrderBuilt, this.props.onError ); } handleHoverID(id) { if (this.props.onHover) { const province = this.props.mapData.getProvince(id); if (province) { this.props.onHover(province.name, this.getRelatedOrders(province.name)); } } } getRelatedOrders(name) { const orders = []; if (this.props.orders) { for (let powerOrders of Object.values(this.props.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; } getNeighbors(extraLocation) { const selectedPath = [this.props.orderBuilding.type].concat(this.props.orderBuilding.path); if (extraLocation) selectedPath.push(extraLocation); const possibleNeighbors = UTILS.javascript.getTreeValue(this.props.game.ordersTree, selectedPath); const neighbors = possibleNeighbors ? possibleNeighbors.map(neighbor => parseLocation(neighbor)) : []; return neighbors.length ? neighbors: null; } render() { const classes = {"_ank":"nopower","_arm":"nopower","_con":"nopower","_mos":"nopower","_sev":"nopower","_stp":"nopower","_syr":"nopower","_ukr":"nopower","_lvn":"nopower","_war":"nopower","_pru":"nopower","_sil":"nopower","_ber":"nopower","_kie":"nopower","_ruh":"nopower","_mun":"nopower","_rum":"nopower","_bul":"nopower","_gre":"nopower","_smy":"nopower","_alb":"nopower","_ser":"nopower","_bud":"nopower","_gal":"nopower","_vie":"nopower","_boh":"nopower","_tyr":"nopower","_tri":"nopower","_fin":"nopower","_swe":"nopower","_nwy":"nopower","_den":"nopower","_hol":"nopower","_bel":"nopower","_swi":"impassable","_ven":"nopower","_pie":"nopower","_tus":"nopower","_rom":"nopower","_apu":"nopower","_nap":"nopower","_bur":"nopower","_mar":"nopower","_gas":"nopower","_pic":"nopower","_par":"nopower","_bre":"nopower","_spa":"nopower","_por":"nopower","_naf":"nopower","_tun":"nopower","_lon":"nopower","_wal":"nopower","_lvp":"nopower","_yor":"nopower","_edi":"nopower","_cly":"nopower","unplayable":"neutral","unplayable_water":"water","_nat":"water","_nrg":"water","_bar":"water","_bot":"water","_bal":"water","denmark_water":"water","_ska":"water","_hel":"water","_nth":"water","_eng":"water","_iri":"water","_mid":"water","_wes":"water","_gol":"water","_tyn":"water","_adr":"water","_ion":"water","_aeg":"water","_eas":"water","constantinople_water":"water","_bla":"water","BriefLabelLayer":"labeltext24","CurrentNote":"currentnotetext","CurrentNote2":"currentnotetext","CurrentPhase":"currentphasetext","MouseLayer":"invisibleContent"}; const game = this.props.game; const mapData = this.props.mapData; const orders = this.props.orders; /* Current phase. */ const current_phase = (game.phase[0] === '?' || game.phase === 'COMPLETED') ? 'FINAL' : game.phase; /* Notes. */ const nb_centers = []; for (let power of Object.values(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(' '); const note = game.note; /* Adding units, influence and orders. */ const renderedUnits = []; const renderedDislodgedUnits = []; const renderedOrders = []; const renderedOrders2 = []; const renderedHighestOrders = []; for (let power of Object.values(game.powers)) if (!power.isEliminated()) { for (let unit of power.units) { renderedUnits.push( ); } for (let unit of Object.keys(power.retreats)) { renderedDislodgedUnits.push( ); } for (let center of power.centers) { setInfluence(classes, mapData, center, power.name); } for (let loc of power.influence) { if (!mapData.supplyCenters.has(loc)) setInfluence(classes, mapData, loc, power.name); } if (orders) { 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') { renderedOrders.push( ); } else if (tokens[2] === '-') { const destLoc = tokens[tokens.length - (tokens[tokens.length - 1] === 'VIA' ? 2 : 1)]; renderedOrders.push( ); } else if (tokens[2] === 'S') { const destLoc = tokens[tokens.length - 1]; if (tokens.includes('-')) { const srcLoc = tokens[4]; renderedOrders2.push( ); } else { renderedOrders2.push( ); } } else if (tokens[2] === 'C') { const srcLoc = tokens[4]; const destLoc = tokens[tokens.length - 1]; if ((srcLoc !== destLoc) && (tokens.includes('-'))) { renderedOrders2.push( ); } } else if (tokens[2] === 'B') { renderedHighestOrders.push( ); } else if (tokens[2] === 'D') { renderedHighestOrders.push( ); } else if (tokens[2] === 'R') { const destLoc = tokens[3]; renderedOrders.push( ); } else { throw new Error(`Unknown error to render (${order}).`); } } } } if (this.props.orderBuilding && this.props.orderBuilding.path.length) { const clicked = parseLocation(this.props.orderBuilding.path[0]); const province = this.props.mapData.getProvince(clicked); if (!province) throw new Error(('Unknown clicked province ' + clicked)); const clickedID = province.getID(classes); if (!clicked) throw new Error(`Unknown path (${clickedID}) for province (${clicked}).`); classes[clickedID] = 'provinceRed'; const neighbors = this.getNeighbors(); if (neighbors) { for (let neighbor of neighbors) { const neighborProvince = this.props.mapData.getProvince(neighbor); if (!neighborProvince) throw new Error('Unknown neighbor province ' + neighbor); const neighborID = neighborProvince.getID(classes); if (!neighborID) throw new Error(`Unknown neoghbor path (${neighborID}) for province (${neighbor}).`); classes[neighborID] = neighborProvince.isWater() ? 'provinceBlue' : 'provinceGreen'; } } } if (this.props.showAbbreviations === false) { classes['BriefLabelLayer'] = 'visibilityHidden'; } return ( {renderedOrders2} {renderedOrders} {renderedUnits} {renderedDislodgedUnits} {renderedHighestOrders} SWI ADR AEG ALB ANK APU ARM BAL BAR BEL BER BLA BOH BRE BUD BUL BUR CLY CON DEN EAS EDI ENG FIN GAL GAS GRE BOT LYO HEL HOL ION IRI KIE LON LVN LVP MAR MAO MOS MUN NAF NAP NAO NTH NWY NWG PAR PIC PIE POR PRU ROM RUH RUM SER SEV SIL SKA SMY SPA STP SWE SYR TRI TUN TUS TYR TYS UKR VEN VIE WAL WAR WES YOR {nb_centers_per_power ? nb_centers_per_power : ''} {note ? note : ''} {current_phase} ); } } SvgStandard.propTypes = { game: PropTypes.instanceOf(Game).isRequired, mapData: PropTypes.instanceOf(MapData).isRequired, orders: PropTypes.object, onHover: PropTypes.func, onError: PropTypes.func.isRequired, onSelectLocation: PropTypes.func, onSelectVia: PropTypes.func, onOrderBuilding: PropTypes.func, onOrderBuilt: PropTypes.func, orderBuilding: PropTypes.object, showAbbreviations: PropTypes.bool }; // eslint-disable-line semi \ No newline at end of file -- cgit v1.2.3