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/ancmed/SvgAncMed.css | 19 + diplomacy/web/src/gui/maps/ancmed/SvgAncMed.js | 20 + .../web/src/gui/maps/ancmed/SvgAncMedMetadata.js | 21 + diplomacy/web/src/gui/maps/common/build.js | 57 + diplomacy/web/src/gui/maps/common/common.js | 83 ++ diplomacy/web/src/gui/maps/common/convoy.js | 103 ++ diplomacy/web/src/gui/maps/common/disband.js | 47 + .../web/src/gui/maps/common/equilateralTriangle.js | 122 ++ diplomacy/web/src/gui/maps/common/hold.js | 47 + diplomacy/web/src/gui/maps/common/move.js | 67 + diplomacy/web/src/gui/maps/common/supportHold.js | 72 ++ diplomacy/web/src/gui/maps/common/supportMove.js | 61 + diplomacy/web/src/gui/maps/common/unit.js | 50 + diplomacy/web/src/gui/maps/modern/SvgModern.css | 19 + diplomacy/web/src/gui/maps/modern/SvgModern.js | 20 + .../web/src/gui/maps/modern/SvgModernMetadata.js | 21 + diplomacy/web/src/gui/maps/pure/SvgPure.css | 19 + diplomacy/web/src/gui/maps/pure/SvgPure.js | 20 + diplomacy/web/src/gui/maps/pure/SvgPureMetadata.js | 21 + .../web/src/gui/maps/standard/SvgStandard.css | 125 +- diplomacy/web/src/gui/maps/standard/SvgStandard.js | 761 +----------- .../web/src/gui/maps/standard/SvgStandardExtra.js | 1279 -------------------- .../src/gui/maps/standard/SvgStandardMetadata.js | 21 + diplomacy/web/src/gui/maps/standard/build.js | 53 - diplomacy/web/src/gui/maps/standard/common.js | 75 -- diplomacy/web/src/gui/maps/standard/convoy.js | 98 -- diplomacy/web/src/gui/maps/standard/disband.js | 51 - diplomacy/web/src/gui/maps/standard/hold.js | 45 - diplomacy/web/src/gui/maps/standard/move.js | 69 -- .../web/src/gui/maps/standard/supplyCenter.js | 40 - diplomacy/web/src/gui/maps/standard/supportHold.js | 73 -- diplomacy/web/src/gui/maps/standard/supportMove.js | 57 - diplomacy/web/src/gui/maps/standard/unit.js | 45 - 33 files changed, 948 insertions(+), 2733 deletions(-) create mode 100644 diplomacy/web/src/gui/maps/ancmed/SvgAncMed.css create mode 100644 diplomacy/web/src/gui/maps/ancmed/SvgAncMed.js create mode 100644 diplomacy/web/src/gui/maps/ancmed/SvgAncMedMetadata.js create mode 100644 diplomacy/web/src/gui/maps/common/build.js create mode 100644 diplomacy/web/src/gui/maps/common/common.js create mode 100644 diplomacy/web/src/gui/maps/common/convoy.js create mode 100644 diplomacy/web/src/gui/maps/common/disband.js create mode 100644 diplomacy/web/src/gui/maps/common/equilateralTriangle.js create mode 100644 diplomacy/web/src/gui/maps/common/hold.js create mode 100644 diplomacy/web/src/gui/maps/common/move.js create mode 100644 diplomacy/web/src/gui/maps/common/supportHold.js create mode 100644 diplomacy/web/src/gui/maps/common/supportMove.js create mode 100644 diplomacy/web/src/gui/maps/common/unit.js create mode 100644 diplomacy/web/src/gui/maps/modern/SvgModern.css create mode 100644 diplomacy/web/src/gui/maps/modern/SvgModern.js create mode 100644 diplomacy/web/src/gui/maps/modern/SvgModernMetadata.js create mode 100644 diplomacy/web/src/gui/maps/pure/SvgPure.css create mode 100644 diplomacy/web/src/gui/maps/pure/SvgPure.js create mode 100644 diplomacy/web/src/gui/maps/pure/SvgPureMetadata.js delete mode 100644 diplomacy/web/src/gui/maps/standard/SvgStandardExtra.js create mode 100644 diplomacy/web/src/gui/maps/standard/SvgStandardMetadata.js delete mode 100644 diplomacy/web/src/gui/maps/standard/build.js delete mode 100644 diplomacy/web/src/gui/maps/standard/common.js delete mode 100644 diplomacy/web/src/gui/maps/standard/convoy.js delete mode 100644 diplomacy/web/src/gui/maps/standard/disband.js delete mode 100644 diplomacy/web/src/gui/maps/standard/hold.js delete mode 100644 diplomacy/web/src/gui/maps/standard/move.js delete mode 100644 diplomacy/web/src/gui/maps/standard/supplyCenter.js delete mode 100644 diplomacy/web/src/gui/maps/standard/supportHold.js delete mode 100644 diplomacy/web/src/gui/maps/standard/supportMove.js delete mode 100644 diplomacy/web/src/gui/maps/standard/unit.js (limited to 'diplomacy/web/src/gui/maps') diff --git a/diplomacy/web/src/gui/maps/ancmed/SvgAncMed.css b/diplomacy/web/src/gui/maps/ancmed/SvgAncMed.css new file mode 100644 index 0000000..0a39460 --- /dev/null +++ b/diplomacy/web/src/gui/maps/ancmed/SvgAncMed.css @@ -0,0 +1,19 @@ +/** +============================================================================== +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 . +============================================================================== +**/ +/* text */ .SvgAncMed .smalllabeltext {text-anchor:middle;stroke-width:0.1;stroke:black;fill:black;font-family:serif;font-style:italic;font-size:14px;} .SvgAncMed .currentnoterect {fill:#c5dfea; stroke-width:0; stroke:black;} .SvgAncMed .currentnotetext {font-family:serif,sans-serif; font-size:12px; fill:black; stroke:black;} .SvgAncMed .currentphasetext {font-family:serif,sans-serif; font-size:18px; fill:black; stroke:black;} /* style class for invisible regions */ .SvgAncMed .invisibleContent {stroke:white;fill:white;fill-opacity:0.0;opacity:0.0} /* default region coloring, by power (nopower if region not owned) */ .SvgAncMed .provinceRed {fill:url(#patternRed); stroke: black; stroke-width:2} .SvgAncMed .provinceBrown {fill:url(#patternBrown); stroke: black; stroke-width:2} .SvgAncMed .provinceGreen {fill:url(#patternGreen); stroke: black; stroke-width:2} .SvgAncMed .provinceBlack {fill:url(#patternBlack); stroke: black; stroke-width:2} .SvgAncMed .provinceBlue {fill:url(#patternBlue); stroke: black; stroke-width:2} .SvgAncMed .nopower {fill:none;stroke:black;stroke-width:2} .SvgAncMed .water {fill:lightblue;stroke:black;stroke-width:2} .SvgAncMed .rome {fill:#c48f85;stroke:black;stroke-width:2} .SvgAncMed .carthage {fill:royalblue;stroke:black;stroke-width:2} .SvgAncMed .persia {fill:gray;stroke:black;stroke-width:2} .SvgAncMed .greece {fill:forestgreen;stroke:black;stroke-width:2} .SvgAncMed .egypt {fill:#b9a61c;stroke:black;stroke-width:2} /* unit colors fills, by power (units always have a power) */ .SvgAncMed .unitrome {fill:red;} .SvgAncMed .unitcarthage {fill:deepskyblue;} .SvgAncMed .unitpersia {fill:white;} .SvgAncMed .unitgreece {fill:#8db600;} .SvgAncMed .unitegypt {fill:yellow;} /* map accents */ .SvgAncMed .thickdash {fill:none;stroke:black;stroke-width:6;stroke-dasharray:2,1.5;} /* order drawing styles, stroke and fill colors should not be specified */ .SvgAncMed .supportorder {stroke-width:3; fill:none; stroke-dasharray:5,5;} .SvgAncMed .convoyorder {stroke-dasharray:15,5; stroke-width:3; fill:none;} .SvgAncMed .shadowdash {stroke-width:5; fill:none; stroke:black; opacity:0.45;} .SvgAncMed .varwidthorder {fill:none;} .SvgAncMed .varwidthshadow {fill:none; stroke:black;} .SvgAncMed .style1 {fill:none;stroke:#17A1F8;stroke-width:5;} .SvgAncMed .style2 {fill:none;stroke:black;stroke-width:2} \ No newline at end of file diff --git a/diplomacy/web/src/gui/maps/ancmed/SvgAncMed.js b/diplomacy/web/src/gui/maps/ancmed/SvgAncMed.js new file mode 100644 index 0000000..d726a67 --- /dev/null +++ b/diplomacy/web/src/gui/maps/ancmed/SvgAncMed.js @@ -0,0 +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 with parameters: Namespace(input='src/diplomacy/maps/svg/ancmed.svg', name='SvgAncMed', output='src/gui/maps/ancmed/') **/ + import React from 'react'; import PropTypes from 'prop-types'; import './SvgAncMed.css'; import {Coordinates, SymbolSizes, Colors} from "./SvgAncMedMetadata"; 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 SvgAncMed 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 = {"_adr":"water","_aeg":"water","_ale":"nopower","_ant":"nopower","_apu":"nopower","_ara":"nopower","_arm":"nopower","_ath":"nopower","_aus":"water","_bal":"nopower","_bay":"nopower","_ber":"water","_bit":"nopower","_bla":"water","_byz":"nopower","_cap":"nopower","_car":"nopower","_che":"nopower","_cil":"water","_cir":"nopower","_cor":"nopower","_cre":"nopower","_cyp":"nopower","_cyr":"nopower","_dac":"nopower","_dal":"nopower","_dam":"nopower","_egy":"water","_epi":"nopower","_etr":"nopower","_gal":"nopower","_gau":"nopower","_gop":"water","_gos":"water","_got":"water","_ibe":"water","_ill":"nopower","_ion":"water","_isa":"nopower","_jer":"nopower","_lep":"nopower","_lib":"water","_lig":"water","_lus":"nopower","_mac":"nopower","_mar":"nopower","_mas":"nopower","_mau":"nopower","_mem":"nopower","_mes":"water","_mil":"nopower","_min":"water","_nab":"nopower","_nea":"nopower","_num":"nopower","_pet":"nopower","_pha":"nopower","_pun":"water","_rav":"nopower","_ree":"water","_rha":"nopower","_rom":"nopower","_sag":"nopower","_sah":"nopower","_sad":"nopower","_sam":"nopower","_sic":"nopower","_sid":"nopower","_sin":"nopower","_sip":"nopower","_spa":"nopower","_syr":"water","_tar":"nopower","_tha":"nopower","_thb":"nopower","_tye":"nopower","_tyn":"water","_ven":"nopower","_vin":"nopower","water":"water","BriefLabelLayer":"smalllabeltext","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 ( Ancient Med Map {renderedOrders2} {renderedOrders} {renderedUnits} {renderedDislodgedUnits} {renderedHighestOrders} adr aeg ale ant apu ara arm ath aus bal bay ber bit bla byz cap car che cil cir cor cre cyp cyr dac dal dam egy epi etr gal gau gop gos got ibe ill ion isa jer lep lib lig lus mac mar mas mau mem mes mil min nab nea num pet pha pun rav ree rha rom sag sah sad sam sic sid sin sip spa syr tar tha thb tye tyn ven vin {nb_centers_per_power ? nb_centers_per_power : ''} {note ? note : ''} {current_phase} ); } } SvgAncMed.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 diff --git a/diplomacy/web/src/gui/maps/ancmed/SvgAncMedMetadata.js b/diplomacy/web/src/gui/maps/ancmed/SvgAncMedMetadata.js new file mode 100644 index 0000000..c01e4dd --- /dev/null +++ b/diplomacy/web/src/gui/maps/ancmed/SvgAncMedMetadata.js @@ -0,0 +1,21 @@ +/** +============================================================================== +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 . +============================================================================== +**/ +export const Coordinates = {"ADR":{"unit":["472.5","201.0"],"disl":["479.5","194.0"]},"AEG":{"unit":["657.5","335.0"],"disl":["664.5","328.0"]},"ALE":{"unit":["705.5","504.0"],"disl":["712.5","497.0"]},"ANT":{"unit":["911.5","304.0"],"disl":["918.5","297.0"]},"APU":{"unit":["443.5","222.0"],"disl":["450.5","215.0"]},"ARA":{"unit":["971.5","416.0"],"disl":["978.5","409.0"]},"ARM":{"unit":["977.5","214.0"],"disl":["984.5","207.0"]},"ATH":{"unit":["581.5","300.0"],"disl":["588.5","293.0"]},"AUS":{"unit":["485.5","382.0"],"disl":["492.5","375.0"]},"BAL":{"unit":["153.5","240.0"],"disl":["160.5","233.0"]},"BAY":{"unit":["682.5","617.0"],"disl":["689.5","610.0"]},"BER":{"unit":["205.5","315.0"],"disl":["212.5","308.0"]},"BIT":{"unit":["759.5","209.0"],"disl":["766.5","202.0"]},"BLA":{"unit":["770.5","143.0"],"disl":["777.5","136.0"]},"BYZ":{"unit":["682.5","242.0"],"disl":["689.5","235.0"]},"CAP":{"unit":["865.5","269.0"],"disl":["872.5","262.0"]},"CAR":{"unit":["303.5","372.0"],"disl":["310.5","365.0"]},"CHE":{"unit":["881.5","59.0"],"disl":["888.5","52.0"]},"CIL":{"unit":["785.5","353.0"],"disl":["792.5","346.0"]},"CIR":{"unit":["236.5","442.0"],"disl":["243.5","435.0"]},"COR":{"unit":["307.5","215.0"],"disl":["314.5","208.0"]},"CRE":{"unit":["650.5","382.0"],"disl":["657.5","375.0"]},"CYP":{"unit":["816.5","374.0"],"disl":["823.5","367.0"]},"CYR":{"unit":["625.5","508.0"],"disl":["632.5","501.0"]},"DAC":{"unit":["621.5","138.0"],"disl":["628.5","131.0"]},"DAL":{"unit":["502.5","178.0"],"disl":["509.5","171.0"]},"DAM":{"unit":["973.5","308.0"],"disl":["980.5","301.0"]},"EGY":{"unit":["728.5","441.0"],"disl":["735.5","434.0"]},"EPI":{"unit":["544.5","267.0"],"disl":["551.5","260.0"]},"ETR":{"unit":["313.5","129.0"],"disl":["320.5","122.0"]},"GAL":{"unit":["774.5","264.0"],"disl":["781.5","257.0"]},"GAU":{"unit":["197.5","83.0"],"disl":["204.5","76.0"]},"GOP":{"unit":["843.5","446.0"],"disl":["850.5","439.0"]},"GOS":{"unit":["509.5","498.0"],"disl":["516.5","491.0"]},"GOT":{"unit":["475.5","428.0"],"disl":["482.5","421.0"]},"IBE":{"unit":["82.5","356.0"],"disl":["89.5","349.0"]},"ILL":{"unit":["536.5","157.0"],"disl":["543.5","150.0"]},"ION":{"unit":["508.5","306.0"],"disl":["515.5","299.0"]},"ISA":{"unit":["806.5","313.0"],"disl":["813.5","306.0"]},"JER":{"unit":["899.5","451.0"],"disl":["906.5","444.0"]},"LEP":{"unit":["468.5","533.0"],"disl":["475.5","526.0"]},"LIB":{"unit":["544.5","428.0"],"disl":["551.5","421.0"]},"LIG":{"unit":["256.5","215.0"],"disl":["263.5","208.0"]},"LUS":{"unit":["18.5","227.0"],"disl":["25.5","220.0"]},"MAC":{"unit":["611.5","231.0"],"disl":["618.5","224.0"]},"MAR":{"unit":["601.5","561.0"],"disl":["608.5","554.0"]},"MAS":{"unit":["253.5","127.0"],"disl":["260.5","120.0"]},"MAU":{"unit":["112.5","410.0"],"disl":["119.5","403.0"]},"MEM":{"unit":["783.5","554.0"],"disl":["790.5","547.0"]},"MES":{"unit":["535.5","378.0"],"disl":["542.5","371.0"]},"MIL":{"unit":["730.5","313.0"],"disl":["737.5","306.0"]},"MIN":{"unit":["709.5","370.0"],"disl":["716.5","363.0"]},"NAB":{"unit":["976.5","528.0"],"disl":["983.5","521.0"]},"NEA":{"unit":["457.5","274.0"],"disl":["464.5","267.0"]},"NUM":{"unit":["343.5","471.0"],"disl":["350.5","464.0"]},"PET":{"unit":["917.5","508.0"],"disl":["924.5","501.0"]},"PHA":{"unit":["400.5","553.0"],"disl":["407.5","546.0"]},"PUN":{"unit":["358.5","338.0"],"disl":["365.5","331.0"]},"RAV":{"unit":["391.5","169.0"],"disl":["398.5","162.0"]},"REE":{"unit":["950.5","594.0"],"disl":["957.5","587.0"]},"RHA":{"unit":["339.5","59.0"],"disl":["346.5","52.0"]},"ROM":{"unit":["368.5","188.0"],"disl":["375.5","181.0"]},"SAD":{"unit":["304.5","264.0"],"disl":["311.5","257.0"]},"SAG":{"unit":["58.5","302.0"],"disl":["65.5","295.0"]},"SAH":{"unit":["269.5","588.0"],"disl":["276.5","581.0"]},"SAM":{"unit":["517.5","56.0"],"disl":["524.5","49.0"]},"SIC":{"unit":["421.5","333.0"],"disl":["428.5","326.0"]},"SID":{"unit":["919.5","355.0"],"disl":["926.5","348.0"]},"SIN":{"unit":["871.5","490.0"],"disl":["878.5","483.0"]},"SIP":{"unit":["865.5","196.0"],"disl":["872.5","189.0"]},"SPA":{"unit":["583.5","322.0"],"disl":["590.5","315.0"]},"SYR":{"unit":["864.5","402.0"],"disl":["871.5","395.0"]},"TAR":{"unit":["128.5","221.0"],"disl":["135.5","214.0"]},"THA":{"unit":["307.5","419.0"],"disl":["314.5","412.0"]},"THB":{"unit":["879.5","591.0"],"disl":["886.5","584.0"]},"TYE":{"unit":["914.5","383.0"],"disl":["921.5","376.0"]},"TYN":{"unit":["395.5","268.0"],"disl":["402.5","261.0"]},"VEN":{"unit":["346.5","100.0"],"disl":["353.5","93.0"]},"VIN":{"unit":["410.5","71.0"],"disl":["417.5","64.0"]}}; +export const SymbolSizes = {"Fleet":{"width":20.0,"height":20.0},"Army":{"width":20.0,"height":20.0},"Wing":{"width":20.0,"height":20.0},"DislodgedFleet":{"width":20.0,"height":20.0},"DislodgedArmy":{"width":20.0,"height":20.0},"DislodgedWing":{"width":20.0,"height":20.0},"FailedOrder":{"width":20.0,"height":20.0},"SupplyCenter":{"width":10.0,"height":10.0},"BuildUnit":{"width":30.0,"height":30.0},"RemoveUnit":{"width":30.0,"height":30.0},"WaivedBuild":{"width":25.0,"height":25.0},"HoldUnit":{"width":40.0,"height":40.0},"SupportHoldUnit":{"width":46.0,"height":46.0},"ConvoyTriangle":{"width":50.0,"height":43.2},"Stroke":{"width":3.0,"height":5.0}}; +export const Colors = {"ROME":"#c48f85","CARTHAGE":"royalblue","PERSIA":"gray","GREECE":"forestgreen","EGYPT":"#b9a61c"}; diff --git a/diplomacy/web/src/gui/maps/common/build.js b/diplomacy/web/src/gui/maps/common/build.js new file mode 100644 index 0000000..765dbad --- /dev/null +++ b/diplomacy/web/src/gui/maps/common/build.js @@ -0,0 +1,57 @@ +// ============================================================================== +// 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 {ARMY, centerSymbolAroundUnit, FLEET} from "./common"; +import PropTypes from "prop-types"; + +export class Build extends React.Component { + render() { + const Coordinates = this.props.coordinates; + const SymbolSizes = this.props.symbolSizes; + const loc = this.props.loc; + const unit_type = this.props.unitType; + const build_symbol = 'BuildUnit'; + const loc_x = Coordinates[loc].unit[0]; + const loc_y = Coordinates[loc].unit[1]; + const [build_loc_x, build_loc_y] = centerSymbolAroundUnit(Coordinates, SymbolSizes, loc, false, build_symbol); + + const symbol = unit_type === 'A' ? ARMY : FLEET; + return ( + + + + + ); + } +} + +Build.propTypes = { + unitType: PropTypes.string.isRequired, + loc: PropTypes.string.isRequired, + powerName: PropTypes.string.isRequired, + coordinates: PropTypes.object.isRequired, + symbolSizes: PropTypes.object.isRequired +}; diff --git a/diplomacy/web/src/gui/maps/common/common.js b/diplomacy/web/src/gui/maps/common/common.js new file mode 100644 index 0000000..750f786 --- /dev/null +++ b/diplomacy/web/src/gui/maps/common/common.js @@ -0,0 +1,83 @@ +// ============================================================================== +// 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 . +// ============================================================================== + +export const ARMY = 'Army'; +export const FLEET = 'Fleet'; + +export function offset(floatString, offset) { + return "" + (parseFloat(floatString) + offset); +} + +export function setInfluence(classes, mapData, loc, power_name) { + const province = mapData.getProvince(loc); + if (!province) + throw new Error(`Unable to find province ${loc}`); + if (!['LAND', 'COAST'].includes(province.type)) + return; + const id = province.getID(classes); + if (!id) + throw new Error(`Unable to find SVG path for loc ${id}`); + classes[id] = power_name ? power_name.toLowerCase() : 'nopower'; +} + +export 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; +} + +export function parseLocation(txt) { + if (txt.length > 2 && txt[1] === ' ' && ['A', 'F'].includes(txt[0])) + return txt.substr(2); + return txt; +} + +export function centerSymbolAroundUnit(coordinates, symbolSizes, loc, isDislodged, symbol) { + const key = isDislodged ? 'disl' : 'unit'; + const unitKey = ARMY; + const [unit_x, unit_y] = coordinates[loc][key]; + const unit_height = symbolSizes[unitKey].height; + const unit_width = symbolSizes[unitKey].width; + const symbol_height = symbolSizes[symbol].height; + const symbol_width = symbolSizes[symbol].width; + return [ + `${(parseFloat(unit_x) + parseFloat(unit_width) / 2 - parseFloat(symbol_width) / 2)}`, + `${(parseFloat(unit_y) + parseFloat(unit_height) / 2 - parseFloat(symbol_height) / 2)}` + ]; +} + +export function getUnitCenter(coordinates, symbolSizes, loc, isDislodged) { + const key = isDislodged ? 'disl' : 'unit'; + const unitKey = ARMY; + const [unit_x, unit_y] = coordinates[loc][key]; + const unit_height = symbolSizes[unitKey].height; + const unit_width = symbolSizes[unitKey].width; + return [ + `${parseFloat(unit_x) + parseFloat(unit_width) / 2}`, + `${parseFloat(unit_y) + parseFloat(unit_height) / 2}` + ]; +} + +export function plainStrokeWidth(symbolSizes) { + return parseFloat(symbolSizes.Stroke.height); +} + +export function coloredStrokeWidth(symbolSizes) { + return parseFloat(symbolSizes.Stroke.width); +} diff --git a/diplomacy/web/src/gui/maps/common/convoy.js b/diplomacy/web/src/gui/maps/common/convoy.js new file mode 100644 index 0000000..c966161 --- /dev/null +++ b/diplomacy/web/src/gui/maps/common/convoy.js @@ -0,0 +1,103 @@ +// ============================================================================== +// 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 {ARMY, centerSymbolAroundUnit, coloredStrokeWidth, getUnitCenter} from "./common"; +import {EquilateralTriangle} from "./equilateralTriangle"; +import PropTypes from "prop-types"; + +export class Convoy extends React.Component { + render() { + const Coordinates = this.props.coordinates; + const SymbolSizes = this.props.symbolSizes; + const Colors = this.props.colors; + const loc = this.props.loc; + const src_loc = this.props.srcLoc; + const dest_loc = this.props.dstLoc; + + const symbol = 'ConvoyTriangle'; + let [symbol_loc_x, symbol_loc_y] = centerSymbolAroundUnit(Coordinates, SymbolSizes, src_loc, false, symbol); + const symbol_height = parseFloat(SymbolSizes[symbol].height); + const symbol_width = parseFloat(SymbolSizes[symbol].width); + const triangle = new EquilateralTriangle( + parseFloat(symbol_loc_x) + symbol_width / 2, + parseFloat(symbol_loc_y), + parseFloat(symbol_loc_x) + symbol_width, + parseFloat(symbol_loc_y) + symbol_height, + parseFloat(symbol_loc_x), + parseFloat(symbol_loc_y) + symbol_height + ); + symbol_loc_y = '' + (parseFloat(symbol_loc_y) - symbol_height / 6); + const [loc_x, loc_y] = getUnitCenter(Coordinates, SymbolSizes, loc, false); + const [src_loc_x, src_loc_y] = getUnitCenter(Coordinates, SymbolSizes, src_loc, false); + let [dest_loc_x, dest_loc_y] = getUnitCenter(Coordinates, SymbolSizes, dest_loc, false); + + const [src_loc_x_1, src_loc_y_1] = triangle.intersection(loc_x, loc_y); + const [src_loc_x_2, src_loc_y_2] = triangle.intersection(dest_loc_x, dest_loc_y); + + const dest_delta_x = dest_loc_x - src_loc_x; + const dest_delta_y = dest_loc_y - src_loc_y; + const dest_vector_length = Math.sqrt(dest_delta_x * dest_delta_x + dest_delta_y * dest_delta_y); + const delta_dec = parseFloat(SymbolSizes[ARMY].width) / 2 + 2 * coloredStrokeWidth(SymbolSizes); + dest_loc_x = '' + Math.round((parseFloat(src_loc_x) + (dest_vector_length - delta_dec) / dest_vector_length * dest_delta_x) * 100.) / 100.; + dest_loc_y = '' + Math.round((parseFloat(src_loc_y) + (dest_vector_length - delta_dec) / dest_vector_length * dest_delta_y) * 100.) / 100.; + + return ( + + + + + + + + ); + } +} + +Convoy.propTypes = { + loc: PropTypes.string.isRequired, + srcLoc: PropTypes.string.isRequired, + dstLoc: PropTypes.string.isRequired, + powerName: PropTypes.string.isRequired, + coordinates: PropTypes.object.isRequired, + symbolSizes: PropTypes.object.isRequired, + colors: PropTypes.object.isRequired +}; diff --git a/diplomacy/web/src/gui/maps/common/disband.js b/diplomacy/web/src/gui/maps/common/disband.js new file mode 100644 index 0000000..97d5c04 --- /dev/null +++ b/diplomacy/web/src/gui/maps/common/disband.js @@ -0,0 +1,47 @@ +// ============================================================================== +// 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 {centerSymbolAroundUnit} from "./common"; +import PropTypes from "prop-types"; + +export class Disband extends React.Component { + render() { + const Coordinates = this.props.coordinates; + const SymbolSizes = this.props.symbolSizes; + const loc = this.props.loc; + const phaseType = this.props.phaseType; + const symbol = 'RemoveUnit'; + const [loc_x, loc_y] = centerSymbolAroundUnit(Coordinates, SymbolSizes, loc, phaseType === 'R', symbol); + return ( + + + + ); + } +} + +Disband.propTypes = { + loc: PropTypes.string.isRequired, + phaseType: PropTypes.string.isRequired, + coordinates: PropTypes.object.isRequired, + symbolSizes: PropTypes.object.isRequired +}; diff --git a/diplomacy/web/src/gui/maps/common/equilateralTriangle.js b/diplomacy/web/src/gui/maps/common/equilateralTriangle.js new file mode 100644 index 0000000..8c433ea --- /dev/null +++ b/diplomacy/web/src/gui/maps/common/equilateralTriangle.js @@ -0,0 +1,122 @@ +export class EquilateralTriangle { + /** Helper class that represent an equilateral triangle.; + Used to compute intersection of a line with a side of convoy symbol, which is an equilateral triangle. **/ + constructor(x_top, y_top, x_right, y_right, x_left, y_left) { + this.x_A = x_top; + this.y_A = y_top; + this.x_B = x_right; + this.y_B = y_right; + this.x_C = x_left; + this.y_C = y_left; + this.h = this.y_B - this.y_A; + this.x_O = this.x_A; + this.y_O = this.y_A + 2 * this.h / 3; + this.line_AB_a = (this.y_B - this.y_A) / (this.x_B - this.x_A); + this.line_AB_b = this.y_B - this.x_B * this.line_AB_a; + this.line_AC_a = (this.y_C - this.y_A) / (this.x_C - this.x_A); + this.line_AC_b = this.y_C - this.x_C * this.line_AC_a; + } + + __line_OM(x_M, y_M) { + const a = (y_M - this.y_O) / (x_M - this.x_O); + const b = y_M - a * x_M; + return [a, b]; + } + + __intersection_with_AB(x_M, y_M) { + const [a, b] = [this.line_AB_a, this.line_AB_b]; + let x = null; + if (x_M === this.x_O) { + x = x_M; + } else { + const [u, v] = this.__line_OM(x_M, y_M); + if (a === u) + return [null, null]; + x = (v - b) / (a - u); + } + const y = a * x + b; + if (this.x_A <= x && x <= this.x_B && this.y_A <= y && y <= this.y_B) + return [x, y]; + return [null, null]; + } + + __intersection_with_AC(x_M, y_M) { + const [a, b] = [this.line_AC_a, this.line_AC_b]; + let x = null; + if (x_M === this.x_O) { + x = x_M; + } else { + const [u, v] = this.__line_OM(x_M, y_M); + if (a === u) + return [null, null]; + x = (v - b) / (a - u); + } + const y = a * x + b; + if (this.x_C <= x && x <= this.x_A && this.y_A <= y && y <= this.y_C) + return [x, y]; + return [null, null]; + } + + __intersection_with_BC(x_M, y_M) { + const y = this.y_C; + let x = null; + if (x_M === this.x_O) { + x = x_M; + } else { + const [a, b] = this.__line_OM(x_M, y_M); + if (a === 0) + return [null, null]; + x = (y - b) / a; + } + if (this.x_C <= x && x <= this.x_A) + return [x, y]; + return [null, null]; + } + + intersection(x_M, y_M) { + if (this.x_O === x_M && this.y_O === y_M) + return [x_M, y_M]; + if (this.x_O === x_M) { + if (y_M < this.y_O) + return [x_M, this.y_A]; + else { + // vertical line intersects BC; + return [x_M, this.y_C]; + } + } else if (this.y_O === y_M) { + let a = null; + let b = null; + if (x_M < this.x_O) { + // horizontal line intersects AC; + [a, b] = [this.line_AC_a, this.line_AC_b]; + } else { + // horizontal line intersects AB; + [a, b] = [this.line_AB_a, this.line_AB_b]; + } + const x = (y_M - b) / a; + return [x, y_M]; + } else { + // get nearest point in intersections with AB, AC, BC; + const [p1_x, p1_y] = this.__intersection_with_AB(x_M, y_M); + const [p2_x, p2_y] = this.__intersection_with_AC(x_M, y_M); + const [p3_x, p3_y] = this.__intersection_with_BC(x_M, y_M); + const distances = []; + if (p1_x !== null) { + const d1 = Math.sqrt((p1_x - x_M) * (p1_x - x_M) + (p1_y - y_M) * (p1_y - y_M)); + distances.push([d1, p1_x, p1_y]); + } + if (p2_x !== null) { + const d2 = Math.sqrt((p2_x - x_M) * (p2_x - x_M) + (p2_y - y_M) * (p2_y - y_M)); + distances.push([d2, p2_x, p2_y]); + } + if (p3_x !== null) { + const d3 = Math.sqrt((p3_x - x_M) * (p3_x - x_M) + (p3_y - y_M) * (p3_y - y_M)); + distances.push([d3, p3_x, p3_y]); + } + distances.sort(); + const output = distances[0]; + output.shift(); + return output; + } + } +} diff --git a/diplomacy/web/src/gui/maps/common/hold.js b/diplomacy/web/src/gui/maps/common/hold.js new file mode 100644 index 0000000..ce77ec5 --- /dev/null +++ b/diplomacy/web/src/gui/maps/common/hold.js @@ -0,0 +1,47 @@ +// ============================================================================== +// 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 {centerSymbolAroundUnit} from "./common"; +import PropTypes from "prop-types"; + +export class Hold extends React.Component { + render() { + const Coordinates = this.props.coordinates; + const Colors = this.props.colors; + const SymbolSizes = this.props.symbolSizes; + const symbol = 'HoldUnit'; + const [loc_x, loc_y] = centerSymbolAroundUnit(Coordinates, SymbolSizes, this.props.loc, false, symbol); + return ( + + + + ); + } +} + +Hold.propTypes = { + loc: PropTypes.string.isRequired, + powerName: PropTypes.string.isRequired, + coordinates: PropTypes.object.isRequired, + symbolSizes: PropTypes.object.isRequired, + colors: PropTypes.object.isRequired +}; diff --git a/diplomacy/web/src/gui/maps/common/move.js b/diplomacy/web/src/gui/maps/common/move.js new file mode 100644 index 0000000..cefb6de --- /dev/null +++ b/diplomacy/web/src/gui/maps/common/move.js @@ -0,0 +1,67 @@ +// ============================================================================== +// 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 {ARMY, coloredStrokeWidth, getUnitCenter, plainStrokeWidth} from "./common"; +import PropTypes from "prop-types"; + +export class Move extends React.Component { + render() { + const Coordinates = this.props.coordinates; + const SymbolSizes = this.props.symbolSizes; + const Colors = this.props.colors; + const src_loc = this.props.srcLoc; + const dest_loc = this.props.dstLoc; + const is_dislodged = this.props.phaseType === 'R'; + const [src_loc_x, src_loc_y] = getUnitCenter(Coordinates, SymbolSizes, src_loc, is_dislodged); + let [dest_loc_x, dest_loc_y] = getUnitCenter(Coordinates, SymbolSizes, dest_loc, is_dislodged); + // Adjusting destination + const delta_x = dest_loc_x - src_loc_x; + const delta_y = dest_loc_y - src_loc_y; + const vector_length = Math.sqrt(delta_x * delta_x + delta_y * delta_y); + const delta_dec = parseFloat(SymbolSizes[ARMY].width) / 2 + 2 * coloredStrokeWidth(SymbolSizes); + dest_loc_x = '' + Math.round((parseFloat(src_loc_x) + (vector_length - delta_dec) / vector_length * delta_x) * 100.) / 100.; + dest_loc_y = '' + Math.round((parseFloat(src_loc_y) + (vector_length - delta_dec) / vector_length * delta_y) * 100.) / 100.; + return ( + + + + + ); + } +} + +Move.propTypes = { + srcLoc: PropTypes.string.isRequired, + dstLoc: PropTypes.string.isRequired, + powerName: PropTypes.string.isRequired, + phaseType: PropTypes.string.isRequired, + coordinates: PropTypes.object.isRequired, + symbolSizes: PropTypes.object.isRequired, + colors: PropTypes.object.isRequired +}; diff --git a/diplomacy/web/src/gui/maps/common/supportHold.js b/diplomacy/web/src/gui/maps/common/supportHold.js new file mode 100644 index 0000000..9b350d2 --- /dev/null +++ b/diplomacy/web/src/gui/maps/common/supportHold.js @@ -0,0 +1,72 @@ +// ============================================================================== +// 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 {centerSymbolAroundUnit, getUnitCenter} from "./common"; +import PropTypes from "prop-types"; + +export class SupportHold extends React.Component { + render() { + const Coordinates = this.props.coordinates; + const SymbolSizes = this.props.symbolSizes; + const Colors = this.props.colors; + const loc = this.props.loc; + const dest_loc = this.props.dstLoc; + const symbol = 'SupportHoldUnit'; + const [symbol_loc_x, symbol_loc_y] = centerSymbolAroundUnit(Coordinates, SymbolSizes, dest_loc, false, symbol); + const [loc_x, loc_y] = getUnitCenter(Coordinates, SymbolSizes, loc, false); + let [dest_loc_x, dest_loc_y] = getUnitCenter(Coordinates, SymbolSizes, dest_loc, false); + + const delta_x = dest_loc_x - loc_x; + const delta_y = dest_loc_y - loc_y; + const vector_length = Math.sqrt(delta_x * delta_x + delta_y * delta_y); + const delta_dec = parseFloat(SymbolSizes[symbol].height) / 2; + dest_loc_x = '' + Math.round((parseFloat(loc_x) + (vector_length - delta_dec) / vector_length * delta_x) * 100.) / 100.; + dest_loc_y = '' + Math.round((parseFloat(loc_y) + (vector_length - delta_dec) / vector_length * delta_y) * 100.) / 100.; + + return ( + + + + + + ); + } +} + +SupportHold.propTypes = { + loc: PropTypes.string.isRequired, + dstLoc: PropTypes.string.isRequired, + powerName: PropTypes.string.isRequired, + coordinates: PropTypes.object.isRequired, + symbolSizes: PropTypes.object.isRequired, + colors: PropTypes.object.isRequired +}; diff --git a/diplomacy/web/src/gui/maps/common/supportMove.js b/diplomacy/web/src/gui/maps/common/supportMove.js new file mode 100644 index 0000000..e52e37f --- /dev/null +++ b/diplomacy/web/src/gui/maps/common/supportMove.js @@ -0,0 +1,61 @@ +// ============================================================================== +// 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 {ARMY, coloredStrokeWidth, getUnitCenter} from "./common"; +import PropTypes from "prop-types"; + +export class SupportMove extends React.Component { + render() { + const Coordinates = this.props.coordinates; + const SymbolSizes = this.props.symbolSizes; + const Colors = this.props.colors; + const loc = this.props.loc; + const src_loc = this.props.srcLoc; + const dest_loc = this.props.dstLoc; + const [loc_x, loc_y] = getUnitCenter(Coordinates, SymbolSizes, loc, false); + const [src_loc_x, src_loc_y] = getUnitCenter(Coordinates, SymbolSizes, src_loc, false); + let [dest_loc_x, dest_loc_y] = getUnitCenter(Coordinates, SymbolSizes, dest_loc, false); + + // Adjusting destination + const delta_x = dest_loc_x - src_loc_x; + const delta_y = dest_loc_y - src_loc_y; + const vector_length = Math.sqrt(delta_x * delta_x + delta_y * delta_y); + const delta_dec = parseFloat(SymbolSizes[ARMY].width) / 2 + 2 * coloredStrokeWidth(SymbolSizes); + dest_loc_x = '' + Math.round((parseFloat(src_loc_x) + (vector_length - delta_dec) / vector_length * delta_x) * 100.) / 100.; + dest_loc_y = '' + Math.round((parseFloat(src_loc_y) + (vector_length - delta_dec) / vector_length * delta_y) * 100.) / 100.; + return ( + + + + + ); + } +} + +SupportMove.propTypes = { + loc: PropTypes.string.isRequired, + srcLoc: PropTypes.string.isRequired, + dstLoc: PropTypes.string.isRequired, + powerName: PropTypes.string.isRequired, + coordinates: PropTypes.object.isRequired, + symbolSizes: PropTypes.object.isRequired, + colors: PropTypes.object.isRequired +}; diff --git a/diplomacy/web/src/gui/maps/common/unit.js b/diplomacy/web/src/gui/maps/common/unit.js new file mode 100644 index 0000000..277a591 --- /dev/null +++ b/diplomacy/web/src/gui/maps/common/unit.js @@ -0,0 +1,50 @@ +// ============================================================================== +// 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 {ARMY, FLEET} from "./common"; +import PropTypes from "prop-types"; + +export class Unit extends React.Component { + render() { + const Coordinates = this.props.coordinates; + const SymbolSizes = this.props.symbolSizes; + const split_unit = this.props.unit.split(/ +/); + const unit_type = split_unit[0]; + const loc = split_unit[1]; + const dislogged_type = this.props.isDislodged ? 'disl' : 'unit'; + const symbol = unit_type === 'F' ? FLEET : ARMY; + const loc_x = Coordinates[loc][dislogged_type][0]; + const loc_y = Coordinates[loc][dislogged_type][1]; + return ( + + ); + } +} + +Unit.propTypes = { + unit: PropTypes.string.isRequired, + powerName: PropTypes.string.isRequired, + isDislodged: PropTypes.bool.isRequired, + coordinates: PropTypes.object.isRequired, + symbolSizes: PropTypes.object.isRequired +}; diff --git a/diplomacy/web/src/gui/maps/modern/SvgModern.css b/diplomacy/web/src/gui/maps/modern/SvgModern.css new file mode 100644 index 0000000..13cccc0 --- /dev/null +++ b/diplomacy/web/src/gui/maps/modern/SvgModern.css @@ -0,0 +1,19 @@ +/** +============================================================================== +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 . +============================================================================== +**/ +/* Default Text */ .SvgModern text {font-size:10pt;fill:black;font-family:Arial;} /* Text */ .SvgModern /* .credits {font-size:8pt;font-family:Arial;} */ .SvgModern /* .titletext {font-size:14px;font-weight:bolder;font-family:Arial;} */ .SvgModern .labeltext {font-size:12px;fill:black;font-family:Arial;} .SvgModern .currentnoterect {fill:#c5dfea; stroke-width:0; stroke:black;} .SvgModern .currentnotetext {font-family:serif,sans-serif; font-size:12px; fill:black; stroke:black;} .SvgModern .currentphasetext {font-family:serif,sans-serif; font-size:14px; fill:black; stroke:black;} /* Mouse Layer */ .SvgModern .invisibleContent {stroke:#000000;fill:#000000;fill-opacity:0.0;opacity:0.0} .SvgModern .provinceRed {fill:url(#patternRed); stroke:black; stroke-width: 2} .SvgModern .provinceBrown {fill:url(#patternBrown); stroke:black; stroke-width: 2} .SvgModern .provinceGreen {fill:url(#patternGreen); stroke:black; stroke-width: 2} .SvgModern .provinceBlack {fill:url(#patternBlack); stroke:black; stroke-width: 2} .SvgModern .provinceBlue {fill:url(#patternBlue); stroke:black; stroke-width: 2} /* Nations */ .SvgModern .nopower {fill:#FFEEEE; stroke:black; stroke-linejoin:round; stroke-width: 2} .SvgModern .water {fill:#DDDDFF; stroke:black; stroke-linejoin:round; stroke-width: 2} .SvgModern .britain {fill:royalblue;stroke:black;; stroke-width: 2} .SvgModern .egypt {fill:#808000;stroke:black;; stroke-width: 2} .SvgModern .france {fill:#00FFFF;stroke:black;; stroke-width: 2} .SvgModern .germany {fill:darkgrey;stroke:black;; stroke-width: 2} .SvgModern .italy {fill:#80FF80;stroke:black;; stroke-width: 2} .SvgModern .poland {fill:#FF0000;stroke:black;; stroke-width: 2} .SvgModern .russia {fill:#008000;stroke:black;; stroke-width: 2} .SvgModern .spain {fill:#FF8080;stroke:black;; stroke-width: 2} .SvgModern .turkey {fill:#FFFF00;stroke:black;; stroke-width: 2} .SvgModern .ukraine {fill:#FF00FF;stroke:black;; stroke-width: 2} /* Unit Colors */ .SvgModern .unitbritain {fill:deepskyblue;stroke:black;fill-opacity:0.90;} .SvgModern .unitegypt {fill:#808000;stroke:black;fill-opacity:0.90;} .SvgModern .unitfrance {fill:#00FFFF;stroke:black;fill-opacity:0.90;} .SvgModern .unitgermany {fill:darkgrey;stroke:black;fill-opacity:0.90;} .SvgModern .unititaly {fill:#80FF80;stroke:black;fill-opacity:0.90;} .SvgModern .unitpoland {fill:#FF0000;stroke:black;fill-opacity:0.90;} .SvgModern .unitrussia {fill:#008000;stroke:black;fill-opacity:0.90;} .SvgModern .unitspain {fill:#FF8080;stroke:black;fill-opacity:0.90;} .SvgModern .unitturkey {fill:#FFFF00;stroke:black;fill-opacity:0.90;} .SvgModern .unitukraine {fill:#FF00FF;stroke:black;fill-opacity:0.90;} /* order drawing styles, stroke and fill colors should not be specified */ .SvgModern .supportorder {stroke-width:2; fill:none; stroke-dasharray:5,5;} .SvgModern .convoyorder {stroke-dasharray:15,5; stroke-width:2; fill:none;} .SvgModern .shadowdash {stroke-width:4; fill:none; stroke:black; opacity:0.45;} .SvgModern .varwidthorder {fill:none;} .SvgModern .varwidthshadow {fill:none; stroke:black;} .SvgModern .style1 {fill:darkGray} \ No newline at end of file diff --git a/diplomacy/web/src/gui/maps/modern/SvgModern.js b/diplomacy/web/src/gui/maps/modern/SvgModern.js new file mode 100644 index 0000000..32fd9fd --- /dev/null +++ b/diplomacy/web/src/gui/maps/modern/SvgModern.js @@ -0,0 +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 with parameters: Namespace(input='src/diplomacy/maps/svg/modern.svg', name='SvgModern', output='src/gui/maps/modern/') **/ + import React from 'react'; import PropTypes from 'prop-types'; import './SvgModern.css'; import {Coordinates, SymbolSizes, Colors} from "./SvgModernMetadata"; 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 SvgModern 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 = {"_ada":"nopower","_adr":"water","_aeg":"water","_alb":"nopower","_ale":"nopower","_alg":"nopower","_als":"nopower","_ana":"nopower","_adl":"nopower","_ank":"nopower","_apu":"nopower","_ara":"water","_arc":"water","_arm":"nopower","_asw":"nopower","_aus":"nopower","_auv":"nopower","_aze":"nopower","_bal":"water","_bar":"nopower","_bel":"nopower","_ber":"nopower","_bhm":"water","_bie":"nopower","_bis":"water","_bor":"nopower","_bos":"nopower","_bri":"nopower","_brn":"water","_bul":"nopower","_cai":"nopower","_cas":"water","_cau":"nopower","_crp":"nopower","_cly":"nopower","_cro":"nopower","_cze":"nopower","_den":"nopower","_don":"nopower","_ebs":"water","_edi":"nopower","_eme":"water","_eng":"water","_esa":"nopower","_est":"nopower","_fin":"nopower","_fra":"nopower","_gda":"nopower","_geo":"nopower","_gib":"nopower","_gob":"water","_gol":"water","_gor":"nopower","_gre":"nopower","_ham":"nopower","_hel":"water","_hol":"nopower","_hun":"nopower","_ice":"nopower","_ion":"water","_ire":"nopower","_iri":"water","_irk":"nopower","_irn":"nopower","_isr":"nopower","_ist":"nopower","_izm":"nopower","_jor":"nopower","_kaz":"nopower","_kha":"nopower","_kie":"nopower","_kra":"nopower","_lap":"nopower","_lat":"nopower","_lbn":"water","_lib":"nopower","_lig":"nopower","_lit":"nopower","_lpl":"nopower","_lon":"nopower","_lyo":"nopower","_mac":"nopower","_mad":"nopower","_mal":"water","_mar":"nopower","_mat":"water","_mil":"nopower","_mol":"nopower","_mon":"nopower","_mor":"nopower","_mos":"nopower","_mun":"nopower","_mur":"nopower","_nap":"nopower","_nat":"water","_nav":"nopower","_nwy":"nopower","_nth":"water","_nwg":"water","_ode":"nopower","_par":"nopower","_per":"water","_pic":"nopower","_pie":"nopower","_pod":"nopower","_por":"nopower","_pru":"nopower","_red":"water","_rom":"nopower","_ros":"nopower","_ruh":"nopower","_rum":"nopower","_sat":"water","_sau":"nopower","_sax":"nopower","_ser":"nopower","_sev":"nopower","_sib":"nopower","_sil":"nopower","_sin":"nopower","_ska":"water","_slk":"nopower","_stp":"nopower","_sog":"water","_svl":"nopower","_swe":"nopower","_swi":"nopower","_syr":"nopower","_tun":"nopower","_tus":"nopower","_tyr":"water","_ura":"nopower","_ven":"nopower","_vol":"nopower","_wal":"nopower","_war":"nopower","_wbs":"water","_wme":"water","_wsa":"nopower","_whi":"water","_yor":"nopower","BriefLabelLayer":"labeltext","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 ( MODERN nc sc {renderedOrders2} {renderedOrders} {renderedUnits} {renderedDislodgedUnits} {renderedHighestOrders} ada adr aeg alb ale alg als ana adl ank apu ara arc arm asw aus auv aze bal bar bel ber bhm bie bis bor bos bri brn bul cai cas cau crp cly cro cze den don ebs edi eme eng esa est fin fra gda geo gib gob gol gor gre ham hel hol hun ice ion ire iri irk irn isr ist izm jor kaz kha kie kra lap lat lbn lib lig lit lpl lon lyo mac mad mal mar mat mil mol mon mor mos mun mur nap nat nav nwy nth nwg ode par per pic pie pod por pru red rom ros ruh rum sat sau sax ser sev sib sil sin ska slk stp sog svl swe swi syr tun tus tyr ura ven vol wal war wbs wme wsa whi yor {nb_centers_per_power ? nb_centers_per_power : ''} {note ? note : ''} {current_phase} ); } } SvgModern.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 diff --git a/diplomacy/web/src/gui/maps/modern/SvgModernMetadata.js b/diplomacy/web/src/gui/maps/modern/SvgModernMetadata.js new file mode 100644 index 0000000..29b4a20 --- /dev/null +++ b/diplomacy/web/src/gui/maps/modern/SvgModernMetadata.js @@ -0,0 +1,21 @@ +/** +============================================================================== +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 . +============================================================================== +**/ +export const Coordinates = {"ADA":{"unit":["527.9","356.9"],"disl":["531.9","352.9"]},"ADL":{"unit":["83.1","359.8"],"disl":["87.1","355.8"]},"ADR":{"unit":["276.8","332.9"],"disl":["280.8","328.9"]},"AEG":{"unit":["371.2","385.3"],"disl":["375.2","381.3"]},"ALB":{"unit":["314.4","350.6"],"disl":["318.4","346.6"]},"ALE":{"unit":["404.8","502.3"],"disl":["408.8","498.3"]},"ALG":{"unit":["130.4","444.2"],"disl":["134.4","440.2"]},"ALS":{"unit":["187.8","238.0"],"disl":["191.8","234.0"]},"ANA":{"unit":["455.3","379.0"],"disl":["459.3","375.0"]},"ANK":{"unit":["455.3","339.1"],"disl":["459.3","335.1"]},"APU":{"unit":["269.5","345.5"],"disl":["273.5","341.5"]},"ARA":{"unit":["674.0","520.6"],"disl":["678.0","516.6"]},"ARC":{"unit":["196.3","5.8"],"disl":["200.3","1.8"]},"ARM":{"unit":["562.4","322.9"],"disl":["566.4","318.9"]},"ASW":{"unit":["446.2","539.4"],"disl":["450.2","535.4"]},"AUS":{"unit":["268.9","268.5"],"disl":["272.9","264.5"]},"AUV":{"unit":["146.4","300.5"],"disl":["150.4","296.5"]},"AZE":{"unit":["591.6","312.5"],"disl":["595.6","308.5"]},"BAL":{"unit":["310.0","136.4"],"disl":["314.0","132.4"]},"BAR":{"unit":["113.6","322.2"],"disl":["117.6","318.2"]},"BEL":{"unit":["177.8","206.8"],"disl":["181.8","202.8"]},"BER":{"unit":["260.8","188.9"],"disl":["264.8","184.9"]},"BHM":{"unit":["264.1","165.6"],"disl":["268.1","161.6"]},"BIE":{"unit":["366.0","189.8"],"disl":["370.0","185.8"]},"BIS":{"unit":["86.2","239.3"],"disl":["90.2","235.3"]},"BOR":{"unit":["133.6","278.1"],"disl":["137.6","274.1"]},"BOS":{"unit":["294.7","307.0"],"disl":["298.7","303.0"]},"BRI":{"unit":["126.2","232.9"],"disl":["130.2","228.9"]},"BRN":{"unit":["287.1","4.4"],"disl":["291.1","0.4"]},"BUL":{"unit":["380.7","328.2"],"disl":["384.7","324.2"]},"CAI":{"unit":["475.3","503.1"],"disl":["479.3","499.1"]},"CAS":{"unit":["626.7","311.7"],"disl":["630.7","307.7"]},"CAU":{"unit":["552.9","273.7"],"disl":["556.9","269.7"]},"CLY":{"unit":["144.0","94.6"],"disl":["148.0","90.6"]},"CRO":{"unit":["280.7","287.1"],"disl":["284.7","283.1"]},"CRP":{"unit":["434.3","183.5"],"disl":["438.3","179.5"]},"CZE":{"unit":["277.5","240.0"],"disl":["281.5","236.0"]},"DEN":{"unit":["242.2","147.7"],"disl":["246.2","143.7"]},"DON":{"unit":["476.3","245.3"],"disl":["480.3","241.3"]},"EBS":{"unit":["475.2","306.9"],"disl":["479.2","302.9"]},"EDI":{"unit":["159.9","111.9"],"disl":["163.9","107.9"]},"EME":{"unit":["412.3","434.5"],"disl":["416.3","430.5"]},"ENG":{"unit":["71.6","206.8"],"disl":["75.6","202.8"]},"ESA":{"unit":["355.4","475.7"],"disl":["359.4","471.7"]},"EST":{"unit":["359.7","111.2"],"disl":["363.7","107.2"]},"FIN":{"unit":["356.5","62.5"],"disl":["360.5","58.5"]},"FRA":{"unit":["233.6","212.8"],"disl":["237.6","208.8"]},"GDA":{"unit":["325.9","173.6"],"disl":["329.9","169.6"]},"GEO":{"unit":["534.2","302.1"],"disl":["538.2","298.1"]},"GIB":{"unit":["50.5","366.1"],"disl":["54.5","362.1"]},"GOB":{"unit":["316.6","97.9"],"disl":["320.6","93.9"]},"GOL":{"unit":["135.7","346.4"],"disl":["139.7","342.4"]},"GOR":{"unit":["522.6","93.0"],"disl":["526.6","89.0"]},"GRE":{"unit":["335.5","367.5"],"disl":["339.5","363.5"]},"HAM":{"unit":["227.6","190.2"],"disl":["231.6","186.2"]},"HEL":{"unit":["214.3","163.0"],"disl":["218.3","159.0"]},"HOL":{"unit":["196.4","188.2"],"disl":["200.4","184.2"]},"HUN":{"unit":["309.3","275.2"],"disl":["313.3","271.2"]},"ICE":{"unit":["113.6","22.6"],"disl":["117.6","18.6"]},"ION":{"unit":["302.9","391.6"],"disl":["306.9","387.6"]},"IRE":{"unit":["96.2","139.8"],"disl":["100.2","135.8"]},"IRI":{"unit":["96.8","172.3"],"disl":["100.8","168.3"]},"IRK":{"unit":["569.9","387.4"],"disl":["573.9","383.4"]},"IRN":{"unit":["624.6","385.3"],"disl":["628.6","381.3"]},"IRN/NC":{"unit":["639.2","357.5"],"disl":["643.2","353.5"]},"IRN/SC":{"unit":["679.2","446.8"],"disl":["683.2","442.8"]},"ISR":{"unit":["494.2","424.0"],"disl":["498.2","420.0"]},"IST":{"unit":["422.7","355.9"],"disl":["426.7","351.9"]},"IZM":{"unit":["398.5","381.1"],"disl":["402.5","377.1"]},"JOR":{"unit":["512.1","453.3"],"disl":["516.1","449.3"]},"KAZ":{"unit":["644.6","198.2"],"disl":["648.6","194.2"]},"KHA":{"unit":["478.5","224.4"],"disl":["482.5","220.4"]},"KIE":{"unit":["428.0","214.6"],"disl":["432.0","210.6"]},"KRA":{"unit":["334.4","221.3"],"disl":["338.4","217.3"]},"LAP":{"unit":["332.3","7.1"],"disl":["336.3","3.1"]},"LAT":{"unit":["361.2","137.7"],"disl":["365.2","133.7"]},"LBN":{"unit":["306.5","450.5"],"disl":["310.5","446.5"]},"LIB":{"unit":["301.8","501.0"],"disl":["305.8","497.0"]},"LIG":{"unit":["194.5","323.0"],"disl":["198.5","319.0"]},"LIT":{"unit":["347.1","161.0"],"disl":["351.1","157.0"]},"LIV":{"unit":["134.7","137.8"],"disl":["138.7","133.8"]},"LON":{"unit":["160.6","182.9"],"disl":["164.6","178.9"]},"LYO":{"unit":["164.5","264.0"],"disl":["168.5","260.0"]},"MAC":{"unit":["335.3","344.0"],"disl":["339.3","340.0"]},"MAD":{"unit":["66.9","318.0"],"disl":["70.9","314.0"]},"MAL":{"unit":["255.6","440.0"],"disl":["259.6","436.0"]},"MAR":{"unit":["171.2","292.4"],"disl":["175.2","288.4"]},"MID":{"unit":["13.7","211.8"],"disl":["17.7","207.8"]},"MIL":{"unit":["227.0","283.8"],"disl":["231.0","279.8"]},"MOL":{"unit":["391.1","262.2"],"disl":["395.1","258.2"]},"MON":{"unit":["187.1","301.7"],"disl":["191.1","297.7"]},"MOR":{"unit":["45.3","411.6"],"disl":["49.3","407.6"]},"MOS":{"unit":["434.8","151.0"],"disl":["438.8","147.0"]},"MUN":{"unit":["224.5","248.0"],"disl":["228.5","244.0"]},"MUR":{"unit":["451.5","51.8"],"disl":["455.5","47.8"]},"NAO":{"unit":["52.6","107.8"],"disl":["56.6","103.8"]},"NAP":{"unit":["270.1","365.4"],"disl":["274.1","361.4"]},"NAV":{"unit":["99.9","298.1"],"disl":["103.9","294.1"]},"NTH":{"unit":["186.5","127.8"],"disl":["190.5","123.8"]},"NWG":{"unit":["188.5","74.7"],"disl":["192.5","70.7"]},"NWY":{"unit":["232.3","101.2"],"disl":["236.3","97.2"]},"ODE":{"unit":["406.9","241.2"],"disl":["410.9","237.2"]},"PAR":{"unit":["149.4","243.9"],"disl":["153.4","239.9"]},"PER":{"unit":["662.4","463.1"],"disl":["666.4","459.1"]},"PIC":{"unit":["159.3","220.8"],"disl":["163.3","216.8"]},"PIE":{"unit":["205.1","291.1"],"disl":["209.1","287.1"]},"POD":{"unit":["370.2","232.4"],"disl":["374.2","228.4"]},"POR":{"unit":["30.5","315.9"],"disl":["34.5","311.9"]},"PRU":{"unit":["294.7","181.6"],"disl":["298.7","177.6"]},"RED":{"unit":["522.6","521.0"],"disl":["526.6","517.0"]},"ROM":{"unit":["244.9","333.6"],"disl":["248.9","329.6"]},"ROS":{"unit":["493.2","270.3"],"disl":["497.2","266.3"]},"RUH":{"unit":["206.4","210.1"],"disl":["210.4","206.1"]},"RUM":{"unit":["359.1","285.8"],"disl":["363.1","281.8"]},"SAO":{"unit":["4.3","389.5"],"disl":["8.3","385.5"]},"SAU":{"unit":["569.9","505.2"],"disl":["573.9","501.2"]},"SAX":{"unit":["245.6","232.7"],"disl":["249.6","228.7"]},"SER":{"unit":["326.5","315.0"],"disl":["330.5","311.0"]},"SEV":{"unit":["443.8","270.7"],"disl":["447.8","266.7"]},"SIB":{"unit":["635.1","87.8"],"disl":["639.1","83.8"]},"SIL":{"unit":["293.5","214.0"],"disl":["297.5","210.0"]},"SIN":{"unit":["485.1","468.4"],"disl":["489.1","464.4"]},"SKA":{"unit":["248.9","119.8"],"disl":["252.9","115.8"]},"SLK":{"unit":["313.3","251.9"],"disl":["317.3","247.9"]},"SOG":{"unit":["64.5","387.0"],"disl":["68.5","383.0"]},"STP":{"unit":["390.1","110.9"],"disl":["394.1","106.9"]},"SVE":{"unit":["50.5","339.0"],"disl":["54.5","335.0"]},"SWE":{"unit":["276.6","124.6"],"disl":["280.6","120.6"]},"SWI":{"unit":["206.5","268.0"],"disl":["210.5","264.0"]},"SYR":{"unit":["528.2","395.3"],"disl":["532.2","391.3"]},"TUN":{"unit":["204.0","446.3"],"disl":["208.0","442.3"]},"TUS":{"unit":["225.6","311.7"],"disl":["229.6","307.7"]},"TYR":{"unit":["234.2","374.7"],"disl":["238.2","370.7"]},"URA":{"unit":["526.8","16.3"],"disl":["530.8","12.3"]},"VEN":{"unit":["249.6","309.7"],"disl":["253.6","305.7"]},"VOL":{"unit":["514.2","192.9"],"disl":["518.2","188.9"]},"WAL":{"unit":["130.0","188.9"],"disl":["134.0","184.9"]},"WAR":{"unit":["316.6","203.5"],"disl":["320.6","199.5"]},"WBS":{"unit":["423.6","309.6"],"disl":["427.6","305.6"]},"WHI":{"unit":["422.7","9.9"],"disl":["426.7","5.9"]},"WME":{"unit":["143.0","380.1"],"disl":["147.0","376.1"]},"WSA":{"unit":["47.4","511.5"],"disl":["51.4","507.5"]},"YOR":{"unit":["154.6","153.7"],"disl":["158.6","149.7"]}}; +export const SymbolSizes = {"Fleet":{"width":16.0,"height":16.0},"Army":{"width":16.0,"height":16.0},"Wing":{"width":20.0,"height":20.0},"DislodgedFleet":{"width":20.0,"height":20.0},"DislodgedArmy":{"width":20.0,"height":20.0},"DislodgedWing":{"width":20.0,"height":20.0},"FailedOrder":{"width":17.0,"height":17.0},"SupplyCenter":{"width":5.0,"height":5.0},"BuildUnit":{"width":24.0,"height":24.0},"RemoveUnit":{"width":24.0,"height":24.0},"WaivedBuild":{"width":25.0,"height":25.0},"HoldUnit":{"width":30.0,"height":30.0},"SupportHoldUnit":{"width":34.5,"height":34.5},"ConvoyTriangle":{"width":40.0,"height":34.5},"Stroke":{"width":2.0,"height":4.0}}; +export const Colors = {"BRITAIN":"royalblue","EGYPT":"#808000","FRANCE":"#00FFFF","GERMANY":"darkgrey","ITALY":"#80FF80","POLAND":"#FF0000","RUSSIA":"#008000","SPAIN":"#FF8080","TURKEY":"#FFFF00","UKRAINE":"#FF00FF"}; diff --git a/diplomacy/web/src/gui/maps/pure/SvgPure.css b/diplomacy/web/src/gui/maps/pure/SvgPure.css new file mode 100644 index 0000000..2aa9fda --- /dev/null +++ b/diplomacy/web/src/gui/maps/pure/SvgPure.css @@ -0,0 +1,19 @@ +/** +============================================================================== +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 . +============================================================================== +**/ +/* text */ .SvgPure svg { font-size: 100% } .SvgPure .labeltext {stroke-width:0.1; stroke:black; fill:black;} .SvgPure .currentnotetext {font-family:serif,sans-serif; font-size:1.5em; fill:black; stroke:black;} .SvgPure .currentphasetext {font-family:serif,sans-serif; fill:black; stroke:black;} /* invisible click rects fill:none does not work */ .SvgPure .invisibleContent {stroke:#000000; fill:#000000; fill-opacity:0.0; opacity:0.0} /* default region coloring, by power */ .SvgPure .provinceRed {fill:url(#patternRed); stroke: black; stroke-width: 2} .SvgPure .provinceBrown {fill:url(#patternBrown); stroke: black; stroke-width: 2} .SvgPure .provinceGreen {fill:url(#patternGreen); stroke: black; stroke-width: 2} .SvgPure .provinceBlack {fill:url(#patternBlack); stroke: black; stroke-width: 2} .SvgPure .provinceBlue {fill:url(#patternBlue); stroke: black; stroke-width: 2} .SvgPure .nopower {fill:antiquewhite; stroke:#000000; stroke-width:2} .SvgPure .water {fill:#c5dfea; stroke:#000000; stroke-width:2} .SvgPure .austria {fill:#c48f85; stroke:#000000; stroke-width:2} .SvgPure .england {fill:darkviolet; stroke:#000000; stroke-width:2} .SvgPure .france {fill:royalblue; stroke:#000000; stroke-width:2} .SvgPure .germany {fill:#a08a75; stroke:#000000; stroke-width:2} .SvgPure .italy {fill:forestgreen; stroke:#000000; stroke-width:2} .SvgPure .russia {fill:#757d91; stroke:#000000; stroke-width:2} .SvgPure .turkey {fill:#b9a61c; stroke:#000000; stroke-width:2} /* unit colors, by power note that underscores are not supported */ .SvgPure .unitaustria {fill:red; fill-opacity:0.85} .SvgPure .unitengland {fill:mediumpurple; fill-opacity:0.85} .SvgPure .unitfrance {fill:deepskyblue; fill-opacity:0.85} .SvgPure .unitgermany {fill:dimgray; fill-opacity:0.85} .SvgPure .unititaly {fill:olive; fill-opacity:0.85} .SvgPure .unitrussia {fill:white; fill-opacity:1.0} .SvgPure .unitturkey {fill:yellow; fill-opacity:0.85} /* order drawing styles, stroke and fill colors should not be specified */ .SvgPure .supportorder {stroke-width:6; fill:none; stroke-dasharray:5,5;} .SvgPure .convoyorder {stroke-dasharray:15,5; stroke-width:6; fill:none;} .SvgPure .shadowdash {stroke-width:10; fill:none; stroke:black; opacity:0.45;} .SvgPure .varwidthorder {fill:none;} .SvgPure .varwidthshadow {fill:none; stroke:black;} \ No newline at end of file diff --git a/diplomacy/web/src/gui/maps/pure/SvgPure.js b/diplomacy/web/src/gui/maps/pure/SvgPure.js new file mode 100644 index 0000000..9407348 --- /dev/null +++ b/diplomacy/web/src/gui/maps/pure/SvgPure.js @@ -0,0 +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 with parameters: Namespace(input='src/diplomacy/maps/svg/pure.svg', name='SvgPure', output='src/gui/maps/pure/') **/ + import React from 'react'; import PropTypes from 'prop-types'; import './SvgPure.css'; import {Coordinates, SymbolSizes, Colors} from "./SvgPureMetadata"; 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 SvgPure 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 = {"_vie":"nopower","_lon":"nopower","_par":"nopower","_ber":"nopower","_rom":"nopower","_mos":"nopower","_con":"nopower","CurrentNote":"currentnotetext","CurrentNote2":"currentnotetext","CurrentPhase":"currentphasetext","BriefLabelLayer":"labeltext","FullLabelLayer":"labeltext","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 ( Pure Paris London Vienna Berlin Constantinople Moscow Rome {nb_centers_per_power ? nb_centers_per_power : ''} {note ? note : ''} {current_phase} {renderedOrders2} {renderedOrders} {renderedUnits} {renderedDislodgedUnits} {renderedHighestOrders} ); } } SvgPure.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 diff --git a/diplomacy/web/src/gui/maps/pure/SvgPureMetadata.js b/diplomacy/web/src/gui/maps/pure/SvgPureMetadata.js new file mode 100644 index 0000000..51b5594 --- /dev/null +++ b/diplomacy/web/src/gui/maps/pure/SvgPureMetadata.js @@ -0,0 +1,21 @@ +/** +============================================================================== +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 . +============================================================================== +**/ +export const Coordinates = {"BER":{"unit":["362.5","864.0"],"disl":["374.5","852.0"]},"CON":{"unit":["412.5","98.0"],"disl":["424.5","86.0"]},"LON":{"unit":["878.5","514.0"],"disl":["890.5","502.0"]},"MOS":{"unit":["140.5","289.0"],"disl":["152.5","277.0"]},"PAR":{"unit":["707.5","815.0"],"disl":["719.5","803.0"]},"ROM":{"unit":["116.5","628.0"],"disl":["128.5","616.0"]},"VIE":{"unit":["750.5","195.0"],"disl":["762.5","183.0"]}}; +export const SymbolSizes = {"Fleet":{"width":40.0,"height":40.0},"Army":{"width":40.0,"height":40.0},"Wing":{"width":40.0,"height":40.0},"DislodgedFleet":{"width":40.0,"height":40.0},"DislodgedArmy":{"width":40.0,"height":40.0},"DislodgedWing":{"width":40.0,"height":40.0},"FailedOrder":{"width":30.0,"height":30.0},"SupplyCenter":{"width":20.0,"height":20.0},"BuildUnit":{"width":60.0,"height":60.0},"RemoveUnit":{"width":50.0,"height":50.0},"WaivedBuild":{"width":40.0,"height":40.0},"HoldUnit":{"width":66.6,"height":66.6},"SupportHoldUnit":{"width":76.6,"height":76.6},"ConvoyTriangle":{"width":66.4,"height":57.4},"Stroke":{"width":6.0,"height":10.0}}; +export const Colors = {"AUSTRIA":"#DA251D","ENGLAND":"#2D77B2","FRANCE":"#8E85B7","GERMANY":"#666666","ITALY":"#40A340","RUSSIA":"#EEF0E9","TURKEY":"#E9F507"}; diff --git a/diplomacy/web/src/gui/maps/standard/SvgStandard.css b/diplomacy/web/src/gui/maps/standard/SvgStandard.css index 3aeebaa..f1da6c3 100644 --- a/diplomacy/web/src/gui/maps/standard/SvgStandard.css +++ b/diplomacy/web/src/gui/maps/standard/SvgStandard.css @@ -1,106 +1,19 @@ -/* text */ - svg { font-size: 100% } - .titletext {text-anchor:middle; stroke-width:0.3; font-family:sans-serif; font-size:0.7em; stroke:black; fill:black;} - .provtext {text-anchor:middle; stroke-width:0.3; font-family:sans-serif; font-size:0.7em; stroke:black; fill:black;} - .labeltext {stroke-width:0.1; stroke:black; fill:black;} - .unordered {fill:red; stroke:black; stroke-width:1; fill-opacity:0.90;} - .labeltext24 {text-anchor:middle; stroke-width:0.1; stroke:black; fill:black; font-family:serif,sans-serif; font-style:italic; font-size:1.4em;} - .labeltext18 {text-anchor:middle; stroke-width:0.1; stroke:black; fill:black; font-family:serif,sans-serif; font-style:italic; font-size:1.1em;} - .fulllabeltext {font-family:serif,sans-serif; font-style:italic; font-size:1.2em; fill:black; stroke:black;} - .currentnotetext {font-family:serif,sans-serif; font-size:1.5em; fill:black; stroke:black;} - .currentnoterect {fill:#c5dfea;} - .currentphasetext {font-family:serif,sans-serif; font-size:2.5em; fill:black; stroke:black;} - - .labeltext24 text {cursor:default;} - - /* NB: this style is not yet used. */ - .labeltext24 text.allowed { - font-weight:bold; - fill:blue; - font-size: 1.5em; - stroke: red; - stroke-width:2; - text-decoration: underline; - background-color: green; - } - - /* map and object features */ - - .seapoly {stroke:#000000; stroke-width:1; fill:#B5DEF8} - .dashline {stroke:darkslateblue; stroke-width:3; stroke-linecap:round; stroke-dasharray:5,6;} - .impassable {fill:#353433; stroke:#000000; stroke-width:1} - .sealine {stroke:#B5DEFF; stroke-width:3;} - - /* invisible click rects fill:none does not work */ - - .invisibleContent {stroke:#000000; fill:#000000; fill-opacity:0.0; opacity:0.0} - - /* default region coloring, by power */ - - .provinceRed {fill:url(#patternRed)} - .provinceBrown {fill:url(#patternBrown)} - .provinceGreen {fill:url(#patternGreen)} - .provinceBlack {fill:url(#patternBlack)} - .provinceBlue {fill:url(#patternBlue)} - - .nopower {fill:antiquewhite; stroke:#000000; stroke-width:1} - .water {fill:#c5dfea; stroke:#000000; stroke-width:1} - - .neutral {fill:lightgray; stroke:#000000; stroke-width:1} - - .austria {fill:#c48f85; stroke:#000000; stroke-width:1} - .england {fill:darkviolet; stroke:#000000; stroke-width:1} - .france {fill:royalblue; stroke:#000000; stroke-width:1} - .germany {fill:#a08a75; stroke:#000000; stroke-width:1} - .italy {fill:forestgreen; stroke:#000000; stroke-width:1} - .russia {fill:#757d91; stroke:#000000; stroke-width:1} - .turkey {fill:#b9a61c; stroke:#000000; stroke-width:1} - - /* unit colors, by power note that underscores are not supported */ - - .unitaustria {fill:red; fill-opacity:0.85} - .unitengland {fill:mediumpurple; fill-opacity:0.85} - .unitfrance {fill:deepskyblue; fill-opacity:0.85} - .unitgermany {fill:dimgray; fill-opacity:0.85} - .unititaly {fill:olive; fill-opacity:0.85} - .unitrussia {fill:white; fill-opacity:1.0} - .unitturkey {fill:yellow; fill-opacity:0.85} - - /* supply center styles */ - - .scnopower {fill:black; stroke:black;} - .scaustria {fill:black; stroke:black;} - .scengland {fill:black; stroke:black;} - .scfrance {fill:black; stroke:black;} - .scgermany {fill:black; stroke:black;} - .scitaly {fill:black; stroke:black;} - .scrussia {fill:black; stroke:black;} - .scturkey {fill:black; stroke:black;} - - /* order drawing styles, stroke and fill colors should not be specified */ - - .defaultorder {stroke-width:6; fill:none;} - .supportorder {stroke-width:6; fill:none; stroke-dasharray:5,5;} - .convoyorder {stroke-dasharray:15,5; stroke-width:6; fill:none;} - - .shadoworder {stroke-width:10; fill:none; stroke:black;} - .shadowdash {stroke-width:10; fill:none; stroke:black; opacity:0.45;} - - .varwidthorder {fill:none;} - .varwidthshadow {fill:none; stroke:black;} - - /* Symbol private styles. Always start with "sym" to avoid name collisions! */ - - .symBuildShadow {fill:none;stroke:black;opacity:0.5;stroke-width:7;} - .symBuild {stroke:yellow;stroke-width:7;fill:none;} - .symRemove {stroke:red;stroke-width:1;fill:none;} - - .symShadow {stroke:black;fill:black;stroke-width:1;opacity:0.40;} - .symDislodgedShadow {stroke:red;fill:red;stroke-width:1;opacity:0.50;} - .symDislodgedBorder {stroke:red;stroke-width:3%;} - - .symDarkener {fill:black;opacity:0.45;fill-opacity:0.45;} - .symCenterHub {fill:black; stroke:black; opacity:0.60; stroke-width:0.5px;} - .symBorder {stroke:black;stroke-width:3%;} - .symThinBorder {stroke:black;stroke-width:0.4;} - .symSilhouette {stroke:black;fill:black;stroke-width:1;} +/** +============================================================================== +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 . +============================================================================== +**/ +/* text */ .SvgStandard svg { font-size: 100% } .SvgStandard .labeltext24 {text-anchor:middle; stroke-width:0.1; stroke:black; fill:black; font-family:serif,sans-serif; font-style:italic; font-size:1.4em;} .SvgStandard .labeltext18 {text-anchor:middle; stroke-width:0.1; stroke:black; fill:black; font-family:serif,sans-serif; font-style:italic; font-size:1.1em;} .SvgStandard .currentnotetext {font-family:serif,sans-serif; font-size:1.5em; fill:black; stroke:black;} .SvgStandard .currentnoterect {fill:#c5dfea;} .SvgStandard .currentphasetext {font-family:serif,sans-serif; font-size:2.5em; fill:black; stroke:black;} .SvgStandard .labeltext24 text {cursor:default;} /* map and object features */ .SvgStandard .impassable {fill:#353433; stroke:#000000; stroke-width:1} /* invisible click rects fill:none does not work */ .SvgStandard .invisibleContent {stroke:#000000; fill:#000000; fill-opacity:0.0; opacity:0.0} /* default region coloring, by power */ .SvgStandard .provinceRed {fill:url(#patternRed)} .SvgStandard .provinceBrown {fill:url(#patternBrown)} .SvgStandard .provinceGreen {fill:url(#patternGreen)} .SvgStandard .provinceBlack {fill:url(#patternBlack)} .SvgStandard .provinceBlue {fill:url(#patternBlue)} .SvgStandard .nopower {fill:antiquewhite; stroke:#000000; stroke-width:1} .SvgStandard .water {fill:#c5dfea; stroke:#000000; stroke-width:1} .SvgStandard .neutral {fill:lightgray; stroke:#000000; stroke-width:1} .SvgStandard .austria {fill:#c48f85; stroke:#000000; stroke-width:1} .SvgStandard .england {fill:darkviolet; stroke:#000000; stroke-width:1} .SvgStandard .france {fill:royalblue; stroke:#000000; stroke-width:1} .SvgStandard .germany {fill:#a08a75; stroke:#000000; stroke-width:1} .SvgStandard .italy {fill:forestgreen; stroke:#000000; stroke-width:1} .SvgStandard .russia {fill:#757d91; stroke:#000000; stroke-width:1} .SvgStandard .turkey {fill:#b9a61c; stroke:#000000; stroke-width:1} /* unit colors, by power note that underscores are not supported */ .SvgStandard .unitaustria {fill:red; fill-opacity:0.85} .SvgStandard .unitengland {fill:mediumpurple; fill-opacity:0.85} .SvgStandard .unitfrance {fill:deepskyblue; fill-opacity:0.85} .SvgStandard .unitgermany {fill:dimgray; fill-opacity:0.85} .SvgStandard .unititaly {fill:olive; fill-opacity:0.85} .SvgStandard .unitrussia {fill:white; fill-opacity:1.0} .SvgStandard .unitturkey {fill:yellow; fill-opacity:0.85} /* order drawing styles, stroke and fill colors should not be specified */ .SvgStandard .supportorder {stroke-width:6; fill:none; stroke-dasharray:5,5;} .SvgStandard .convoyorder {stroke-dasharray:15,5; stroke-width:6; fill:none;} .SvgStandard .shadowdash {stroke-width:10; fill:none; stroke:black; opacity:0.45;} .SvgStandard .varwidthorder {fill:none;} .SvgStandard .varwidthshadow {fill:none; stroke:black;} \ No newline at end of file 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 diff --git a/diplomacy/web/src/gui/maps/standard/SvgStandardExtra.js b/diplomacy/web/src/gui/maps/standard/SvgStandardExtra.js deleted file mode 100644 index be4e02e..0000000 --- a/diplomacy/web/src/gui/maps/standard/SvgStandardExtra.js +++ /dev/null @@ -1,1279 +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 . -// ============================================================================== -export const SvgStandardExtra = { - "jdipNS:DISPLAY": { - "jdipNS:ZOOM": { - "min": "5", - "max": "2200", - "factor": "1.2" - }, - "jdipNS:LABELS": { - "brief": "true", - "full": "true" - } - }, - "jdipNS:ORDERDRAWING": { - "jdipNS:POWERCOLORS": { - "jdipNS:POWERCOLOR": [ - { - "power": "austria", - "color": "#c48f85" - }, - { - "power": "england", - "color": "darkviolet" - }, - { - "power": "france", - "color": "royalblue" - }, - { - "power": "germany", - "color": "#a08a75" - }, - { - "power": "italy", - "color": "forestgreen" - }, - { - "power": "russia", - "color": "#757d91" - }, - { - "power": "turkey", - "color": "#b9a61c" - } - ] - }, - "jdipNS:SYMBOLSIZE": [ - { - "name": "Fleet", - "width": "40", - "height": "40" - }, - { - "name": "Army", - "width": "40", - "height": "40" - }, - { - "name": "Wing", - "width": "40", - "height": "40" - }, - { - "name": "DislodgedFleet", - "width": "40", - "height": "40" - }, - { - "name": "DislodgedArmy", - "width": "40", - "height": "40" - }, - { - "name": "DislodgedWing", - "width": "40", - "height": "40" - }, - { - "name": "FailedOrder", - "width": "30", - "height": "30" - }, - { - "name": "SupplyCenter", - "width": "20", - "height": "20" - }, - { - "name": "BuildUnit", - "width": "60", - "height": "60" - }, - { - "name": "RemoveUnit", - "width": "50", - "height": "50" - }, - { - "name": "WaivedBuild", - "width": "40", - "height": "40" - } - ], - "jdipNS:BUILD": { - "deltaRadius": "0" - }, - "jdipNS:REMOVE": { - "deltaRadius": "5" - }, - "jdipNS:DISBAND": { - "deltaRadius": "5" - }, - "jdipNS:WAIVE": { - "deltaRadius": "0" - }, - "jdipNS:HOLD": { - "deltaRadius": "5", - "strokeCSSStyle": "varwidthorder", - "highlightOffset": "0", - "highlightCSSClass": "varwidthshadow", - "widths": "6,9,12,18", - "shadowWidths": "10,15,20,25" - }, - "jdipNS:MOVE": { - "deltaRadius": "5", - "strokeCSSStyle": "varwidthorder", - "markerID": "arrow", - "highlightOffset": "0", - "highlightCSSClass": "varwidthshadow", - "widths": "6,9,12,18", - "shadowWidths": "10,15,20,25" - }, - "jdipNS:RETREAT": { - "deltaRadius": "5", - "strokeCSSStyle": "defaultorder", - "markerID": "arrow", - "highlightOffset": "0", - "highlightCSSClass": "shadoworder" - }, - "jdipNS:SUPPORT": { - "deltaRadius": "10", - "strokeCSSStyle": "supportorder", - "markerID": "arrow", - "highlightOffset": "0", - "highlightCSSClass": "shadowdash" - }, - "jdipNS:CONVOY": { - "deltaRadius": "10", - "strokeCSSStyle": "convoyorder", - "markerID": "arrow", - "highlightOffset": "0", - "highlightCSSClass": "shadowdash" - } - }, - "jdipNS:PROVINCE_DATA": { - "jdipNS:PROVINCE": [ - { - "jdipNS:UNIT": { - "x": "805", - "y": "1058" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "792.5", - "y": "1045.5" - }, - "name": "adr" - }, - { - "jdipNS:UNIT": { - "x": "1055", - "y": "1240" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1042.5", - "y": "1227.5" - }, - "name": "aeg" - }, - { - "jdipNS:UNIT": { - "x": "918", - "y": "1123" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "905.5", - "y": "1110.5" - }, - "name": "alb" - }, - { - "jdipNS:UNIT": { - "x": "1313", - "y": "1120" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1300.5", - "y": "1107.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "1271", - "y": "1144" - }, - "name": "ank" - }, - { - "jdipNS:UNIT": { - "x": "803", - "y": "1116" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "790.5", - "y": "1103.5" - }, - "name": "apu" - }, - { - "jdipNS:UNIT": { - "x": "1496", - "y": "1100" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1483.5", - "y": "1087.5" - }, - "name": "arm" - }, - { - "jdipNS:UNIT": { - "x": "890", - "y": "620" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "877.5", - "y": "607.5" - }, - "name": "bal" - }, - { - "jdipNS:UNIT": { - "x": "1174", - "y": "83" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1161.5", - "y": "70.5" - }, - "name": "bar" - }, - { - "jdipNS:UNIT": { - "x": "573", - "y": "763" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "560.5", - "y": "750.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "575", - "y": "755" - }, - "name": "bel" - }, - { - "jdipNS:UNIT": { - "x": "783", - "y": "700" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "770.5", - "y": "687.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "783", - "y": "736" - }, - "name": "ber" - }, - { - "jdipNS:UNIT": { - "x": "1245", - "y": "1010" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1232.5", - "y": "997.5" - }, - "name": "bla" - }, - { - "jdipNS:UNIT": { - "x": "818", - "y": "824" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "805.5", - "y": "811.5" - }, - "name": "boh" - }, - { - "jdipNS:UNIT": { - "x": "953", - "y": "495" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "940.5", - "y": "482.5" - }, - "name": "bot" - }, - { - "jdipNS:UNIT": { - "x": "416", - "y": "829" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "403.5", - "y": "816.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "369", - "y": "799" - }, - "name": "bre" - }, - { - "jdipNS:UNIT": { - "x": "962", - "y": "914" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "949.5", - "y": "901.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "900", - "y": "916" - }, - "name": "bud" - }, - { - "jdipNS:UNIT": { - "x": "1060", - "y": "1078" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1047.5", - "y": "1065.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "1013", - "y": "1078" - }, - "name": "bul" - }, - { - "jdipNS:UNIT": { - "x": "571", - "y": "881" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "558.5", - "y": "868.5" - }, - "name": "bur" - }, - { - "jdipNS:UNIT": { - "x": "448", - "y": "502" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "435.5", - "y": "489.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "446", - "y": "480" - }, - "name": "cly" - }, - { - "jdipNS:UNIT": { - "x": "1157", - "y": "1147" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1144.5", - "y": "1134.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "1141", - "y": "1119" - }, - "name": "con" - }, - { - "jdipNS:UNIT": { - "x": "715", - "y": "597" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "702.5", - "y": "584.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "767", - "y": "626" - }, - "name": "den" - }, - { - "jdipNS:UNIT": { - "x": "1230", - "y": "1321" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1217.5", - "y": "1308.5" - }, - "name": "eas" - }, - { - "jdipNS:UNIT": { - "x": "485", - "y": "524" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "472.5", - "y": "511.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "489", - "y": "565" - }, - "name": "edi" - }, - { - "jdipNS:UNIT": { - "x": "406", - "y": "761" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "393.5", - "y": "748.5" - }, - "name": "eng" - }, - { - "jdipNS:UNIT": { - "x": "1000", - "y": "390" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "987.5", - "y": "377.5" - }, - "name": "fin" - }, - { - "jdipNS:UNIT": { - "x": "1011", - "y": "841" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "998.5", - "y": "828.5" - }, - "name": "gal" - }, - { - "jdipNS:UNIT": { - "x": "434", - "y": "922" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "421.5", - "y": "909.5" - }, - "name": "gas" - }, - { - "jdipNS:UNIT": { - "x": "556", - "y": "1060" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "543.5", - "y": "1047.5" - }, - "name": "gol" - }, - { - "jdipNS:UNIT": { - "x": "978", - "y": "1200" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "965.5", - "y": "1187.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "1023", - "y": "1237" - }, - "name": "gre" - }, - { - "jdipNS:UNIT": { - "x": "663", - "y": "641" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "650.5", - "y": "628.5" - }, - "name": "hel" - }, - { - "jdipNS:UNIT": { - "x": "608", - "y": "721" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "595.5", - "y": "708.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "630", - "y": "692" - }, - "name": "hol" - }, - { - "jdipNS:UNIT": { - "x": "858", - "y": "1296" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "845.5", - "y": "1283.5" - }, - "name": "ion" - }, - { - "jdipNS:UNIT": { - "x": "347", - "y": "671" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "334.5", - "y": "658.5" - }, - "name": "iri" - }, - { - "jdipNS:UNIT": { - "x": "695", - "y": "711" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "682.5", - "y": "698.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "724", - "y": "685" - }, - "name": "kie" - }, - { - "jdipNS:UNIT": { - "x": "500", - "y": "685" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "487.5", - "y": "672.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "489", - "y": "717" - }, - "name": "lon" - }, - { - "jdipNS:UNIT": { - "x": "1037", - "y": "577" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1024.5", - "y": "564.5" - }, - "name": "lvn" - }, - { - "jdipNS:UNIT": { - "x": "462", - "y": "586" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "449.5", - "y": "573.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "458", - "y": "638" - }, - "name": "lvp" - }, - { - "jdipNS:UNIT": { - "x": "525.8", - "y": "1065" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "513.3", - "y": "1052.5" - }, - "name": "lyo" - }, - { - "jdipNS:UNIT": { - "x": "536", - "y": "985" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "523.5", - "y": "972.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "562", - "y": "1018" - }, - "name": "mar" - }, - { - "jdipNS:UNIT": { - "x": "153.3", - "y": "845.3" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "140.8", - "y": "832.8" - }, - "name": "mao" - }, - { - "jdipNS:UNIT": { - "x": "126", - "y": "902" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "113.5", - "y": "889.5" - }, - "name": "mid" - }, - { - "jdipNS:UNIT": { - "x": "1212", - "y": "600" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1199.5", - "y": "587.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "1267", - "y": "584" - }, - "name": "mos" - }, - { - "jdipNS:UNIT": { - "x": "705", - "y": "838" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "692.5", - "y": "825.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "730", - "y": "878" - }, - "name": "mun" - }, - { - "jdipNS:UNIT": { - "x": "337", - "y": "1291" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "324.5", - "y": "1278.5" - }, - "name": "naf" - }, - { - "jdipNS:UNIT": { - "x": "191.6", - "y": "298.2" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "179.1", - "y": "285.7" - }, - "name": "nao" - }, - { - "jdipNS:UNIT": { - "x": "818", - "y": "1180" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "815.5", - "y": "1167.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "778", - "y": "1143" - }, - "name": "nap" - }, - { - "jdipNS:UNIT": { - "x": "238", - "y": "427" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "225.5", - "y": "414.5" - }, - "name": "nat" - }, - { - "jdipNS:UNIT": { - "x": "605", - "y": "250" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "592.5", - "y": "237.5" - }, - "name": "nrg" - }, - { - "jdipNS:UNIT": { - "x": "565", - "y": "570" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "552.5", - "y": "557.5" - }, - "name": "nth" - }, - { - "jdipNS:UNIT": { - "x": "664.2", - "y": "191.8" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "651.7", - "y": "179.3" - }, - "name": "nwg" - }, - { - "jdipNS:UNIT": { - "x": "715", - "y": "420" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "702.5", - "y": "407.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "761", - "y": "463" - }, - "name": "nwy" - }, - { - "jdipNS:UNIT": { - "x": "500", - "y": "855" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "487.5", - "y": "842.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "518", - "y": "819" - }, - "name": "par" - }, - { - "jdipNS:UNIT": { - "x": "535", - "y": "791" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "522.5", - "y": "778.5" - }, - "name": "pic" - }, - { - "jdipNS:UNIT": { - "x": "642", - "y": "978" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "629.5", - "y": "965.5" - }, - "name": "pie" - }, - { - "jdipNS:UNIT": { - "x": "193", - "y": "1023" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "180.5", - "y": "1010.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "151", - "y": "1060" - }, - "name": "por" - }, - { - "jdipNS:UNIT": { - "x": "877", - "y": "700" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "864.5", - "y": "687.5" - }, - "name": "pru" - }, - { - "jdipNS:UNIT": { - "x": "743", - "y": "1112" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "730.5", - "y": "1099.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "719", - "y": "1087" - }, - "name": "rom" - }, - { - "jdipNS:UNIT": { - "x": "648", - "y": "789" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "635.5", - "y": "776.5" - }, - "name": "ruh" - }, - { - "jdipNS:UNIT": { - "x": "1108", - "y": "977" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1095.5", - "y": "964.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "1083", - "y": "1014" - }, - "name": "rum" - }, - { - "jdipNS:UNIT": { - "x": "945", - "y": "1060" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "932.5", - "y": "1047.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "936", - "y": "1021" - }, - "name": "ser" - }, - { - "jdipNS:UNIT": { - "x": "1296", - "y": "855" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1283.5", - "y": "842.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "1267", - "y": "973" - }, - "name": "sev" - }, - { - "jdipNS:UNIT": { - "x": "844", - "y": "779" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "831.5", - "y": "766.5" - }, - "name": "sil" - }, - { - "jdipNS:UNIT": { - "x": "747", - "y": "528" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "734.5", - "y": "515.5" - }, - "name": "ska" - }, - { - "jdipNS:UNIT": { - "x": "1265", - "y": "1220" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1252.5", - "y": "1207.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "1132", - "y": "1222" - }, - "name": "smy" - }, - { - "jdipNS:UNIT": { - "x": "347", - "y": "1049" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "334.5", - "y": "1036.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "302", - "y": "1056" - }, - "name": "spa" - }, - { - "jdipNS:UNIT": { - "x": "1178", - "y": "415" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1165.5", - "y": "402.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "1113", - "y": "469" - }, - "name": "stp" - }, - { - "jdipNS:UNIT": { - "x": "841", - "y": "469" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "828.5", - "y": "456.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "890", - "y": "489" - }, - "name": "swe" - }, - { - "jdipNS:UNIT": { - "x": "642", - "y": "928" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "629", - "y": "915.5" - }, - "name": "swi" - }, - { - "jdipNS:UNIT": { - "x": "1464", - "y": "1216" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1451.5", - "y": "1203.5" - }, - "name": "syr" - }, - { - "jdipNS:UNIT": { - "x": "837", - "y": "1006" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "824.5", - "y": "993.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "794", - "y": "975" - }, - "name": "tri" - }, - { - "jdipNS:UNIT": { - "x": "634", - "y": "1310" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "621.5", - "y": "1297.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "647", - "y": "1282" - }, - "name": "tun" - }, - { - "jdipNS:UNIT": { - "x": "698", - "y": "1044" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "685.5", - "y": "1031.5" - }, - "name": "tus" - }, - { - "jdipNS:UNIT": { - "x": "720", - "y": "1160" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "707.5", - "y": "1147.5" - }, - "name": "tyn" - }, - { - "jdipNS:UNIT": { - "x": "754", - "y": "914" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "741.5", - "y": "901.5" - }, - "name": "tyr" - }, - { - "jdipNS:UNIT": { - "x": "710.0", - "y": "1159.1" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "697.5", - "y": "1146.6" - }, - "name": "tys" - }, - { - "jdipNS:UNIT": { - "x": "1136", - "y": "810" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1123.5", - "y": "797.5" - }, - "name": "ukr" - }, - { - "jdipNS:UNIT": { - "x": "719", - "y": "1004" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "706.5", - "y": "991.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "733", - "y": "971" - }, - "name": "ven" - }, - { - "jdipNS:UNIT": { - "x": "867", - "y": "874" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "854.5", - "y": "861.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "835", - "y": "887" - }, - "name": "vie" - }, - { - "jdipNS:UNIT": { - "x": "440", - "y": "668" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "427.5", - "y": "655.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "440", - "y": "712" - }, - "name": "wal" - }, - { - "jdipNS:UNIT": { - "x": "995", - "y": "750" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "982.5", - "y": "737.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "937", - "y": "748" - }, - "name": "war" - }, - { - "jdipNS:UNIT": { - "x": "474", - "y": "1173" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "461.5", - "y": "1160.5" - }, - "name": "wes" - }, - { - "jdipNS:UNIT": { - "x": "504", - "y": "626" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "491.5", - "y": "613.5" - }, - "jdipNS:SUPPLY_CENTER": { - "x": "506", - "y": "647" - }, - "name": "yor" - }, - { - "jdipNS:UNIT": { - "x": "1218", - "y": "222" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1205.5", - "y": "209.5" - }, - "name": "stp-nc" - }, - { - "jdipNS:UNIT": { - "x": "1066", - "y": "487" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1053.5", - "y": "474.5" - }, - "name": "stp-sc" - }, - { - "jdipNS:UNIT": { - "x": "1127", - "y": "1067" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1114.5", - "y": "1054.5" - }, - "name": "bul-ec" - }, - { - "jdipNS:UNIT": { - "x": "1070", - "y": "1140" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "1057.5", - "y": "1127.5" - }, - "name": "bul-sc" - }, - { - "jdipNS:UNIT": { - "x": "289", - "y": "965" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "276.5", - "y": "952.5" - }, - "name": "spa-nc" - }, - { - "jdipNS:UNIT": { - "x": "291", - "y": "1166" - }, - "jdipNS:DISLODGED_UNIT": { - "x": "278.5", - "y": "1153.5" - }, - "name": "spa-sc" - } - ] - } -}; diff --git a/diplomacy/web/src/gui/maps/standard/SvgStandardMetadata.js b/diplomacy/web/src/gui/maps/standard/SvgStandardMetadata.js new file mode 100644 index 0000000..7d8233c --- /dev/null +++ b/diplomacy/web/src/gui/maps/standard/SvgStandardMetadata.js @@ -0,0 +1,21 @@ +/** +============================================================================== +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 . +============================================================================== +**/ +export const Coordinates = {"ADR":{"unit":["793.5","1048.0"],"disl":["782.0","1038.0"]},"AEG":{"unit":["1043.5","1230.0"],"disl":["1032.0","1220.0"]},"ALB":{"unit":["906.5","1113.0"],"disl":["895.0","1103.0"]},"ANK":{"unit":["1301.5","1110.0"],"disl":["1290.0","1100.0"]},"APU":{"unit":["791.5","1106.0"],"disl":["780.0","1096.0"]},"ARM":{"unit":["1484.5","1090.0"],"disl":["1473.0","1080.0"]},"BAL":{"unit":["878.5","610.0"],"disl":["867.0","600.0"]},"BAR":{"unit":["1162.5","73.0"],"disl":["1151.0","63.0"]},"BEL":{"unit":["561.5","753.0"],"disl":["550.0","743.0"]},"BER":{"unit":["771.5","690.0"],"disl":["760.0","680.0"]},"BLA":{"unit":["1233.5","1000.0"],"disl":["1222.0","990.0"]},"BOH":{"unit":["806.5","814.0"],"disl":["795.0","804.0"]},"BOT":{"unit":["941.5","485.0"],"disl":["930.0","475.0"]},"BRE":{"unit":["404.5","819.0"],"disl":["393.0","809.0"]},"BUD":{"unit":["950.5","904.0"],"disl":["939.0","894.0"]},"BUL":{"unit":["1048.5","1068.0"],"disl":["1037.0","1058.0"]},"BUL/EC":{"unit":["1127.0","1067.0"],"disl":["1115.5","1057.0"]},"BUL/SC":{"unit":["1070.0","1140.0"],"disl":["1058.5","1130.0"]},"BUR":{"unit":["559.5","871.0"],"disl":["548.0","861.0"]},"CLY":{"unit":["436.5","492.0"],"disl":["425.0","482.0"]},"CON":{"unit":["1145.5","1137.0"],"disl":["1134.0","1127.0"]},"DEN":{"unit":["703.5","587.0"],"disl":["692.0","577.0"]},"EAS":{"unit":["1218.5","1311.0"],"disl":["1207.0","1301.0"]},"EDI":{"unit":["473.5","514.0"],"disl":["462.0","504.0"]},"ENG":{"unit":["394.5","751.0"],"disl":["383.0","741.0"]},"FIN":{"unit":["988.5","380.0"],"disl":["977.0","370.0"]},"GAL":{"unit":["999.5","831.0"],"disl":["988.0","821.0"]},"GAS":{"unit":["422.5","912.0"],"disl":["411.0","902.0"]},"GOL":{"unit":["556.0","1060.0"],"disl":["544.5","1050.0"]},"GRE":{"unit":["966.5","1190.0"],"disl":["955.0","1180.0"]},"HEL":{"unit":["651.5","631.0"],"disl":["640.0","621.0"]},"HOL":{"unit":["596.5","711.0"],"disl":["585.0","701.0"]},"ION":{"unit":["846.5","1286.0"],"disl":["835.0","1276.0"]},"IRI":{"unit":["335.5","661.0"],"disl":["324.0","651.0"]},"KIE":{"unit":["683.5","701.0"],"disl":["672.0","691.0"]},"LON":{"unit":["488.5","675.0"],"disl":["477.0","665.0"]},"LVN":{"unit":["1025.5","567.0"],"disl":["1014.0","557.0"]},"LVP":{"unit":["450.5","576.0"],"disl":["439.0","566.0"]},"LYO":{"unit":["514.3","1055.0"],"disl":["502.8","1045.0"]},"MAO":{"unit":["141.8","835.3"],"disl":["130.3","825.3"]},"MAR":{"unit":["524.5","975.0"],"disl":["513.0","965.0"]},"MID":{"unit":["126.0","902.0"],"disl":["114.5","892.0"]},"MOS":{"unit":["1200.5","590.0"],"disl":["1189.0","580.0"]},"MUN":{"unit":["693.5","828.0"],"disl":["682.0","818.0"]},"NAF":{"unit":["325.5","1281.0"],"disl":["314.0","1271.0"]},"NAO":{"unit":["180.1","288.2"],"disl":["168.6","278.2"]},"NAP":{"unit":["806.5","1170.0"],"disl":["795.0","1160.0"]},"NAT":{"unit":["238.0","427.0"],"disl":["226.5","417.0"]},"NRG":{"unit":["605.0","250.0"],"disl":["593.5","240.0"]},"NTH":{"unit":["553.5","560.0"],"disl":["542.0","550.0"]},"NWG":{"unit":["652.7","181.8"],"disl":["641.2","171.8"]},"NWY":{"unit":["703.5","410.0"],"disl":["692.0","400.0"]},"PAR":{"unit":["488.5","845.0"],"disl":["477.0","835.0"]},"PIC":{"unit":["523.5","781.0"],"disl":["512.0","771.0"]},"PIE":{"unit":["630.5","968.0"],"disl":["619.0","958.0"]},"POR":{"unit":["181.5","1013.0"],"disl":["170.0","1003.0"]},"PRU":{"unit":["865.5","690.0"],"disl":["854.0","680.0"]},"ROM":{"unit":["731.5","1102.0"],"disl":["720.0","1092.0"]},"RUH":{"unit":["636.5","779.0"],"disl":["625.0","769.0"]},"RUM":{"unit":["1096.5","967.0"],"disl":["1085.0","957.0"]},"SER":{"unit":["933.5","1050.0"],"disl":["922.0","1040.0"]},"SEV":{"unit":["1284.5","845.0"],"disl":["1273.0","835.0"]},"SIL":{"unit":["832.5","769.0"],"disl":["821.0","759.0"]},"SKA":{"unit":["735.5","518.0"],"disl":["724.0","508.0"]},"SMY":{"unit":["1253.5","1210.0"],"disl":["1242.0","1200.0"]},"SPA":{"unit":["335.5","1039.0"],"disl":["324.0","1029.0"]},"SPA/NC":{"unit":["289.0","965.0"],"disl":["277.5","955.0"]},"SPA/SC":{"unit":["291.0","1166.0"],"disl":["279.5","1156.0"]},"STP":{"unit":["1166.5","405.0"],"disl":["1155.0","395.0"]},"STP/NC":{"unit":["1218.0","222.0"],"disl":["1206.5","212.0"]},"STP/SC":{"unit":["1066.0","487.0"],"disl":["1054.5","477.0"]},"SWE":{"unit":["829.5","459.0"],"disl":["818.0","449.0"]},"SWI":{"unit":["642.0","928.0"],"disl":["630.5","918.0"]},"SYR":{"unit":["1452.5","1206.0"],"disl":["1441.0","1196.0"]},"TRI":{"unit":["825.5","996.0"],"disl":["814.0","986.0"]},"TUN":{"unit":["622.5","1300.0"],"disl":["611.0","1290.0"]},"TUS":{"unit":["686.5","1034.0"],"disl":["675.0","1024.0"]},"TYN":{"unit":["720.0","1160.0"],"disl":["708.5","1150.0"]},"TYR":{"unit":["742.5","904.0"],"disl":["731.0","894.0"]},"TYS":{"unit":["698.5","1149.1"],"disl":["687.0","1139.1"]},"UKR":{"unit":["1124.5","800.0"],"disl":["1113.0","790.0"]},"VEN":{"unit":["707.5","994.0"],"disl":["696.0","984.0"]},"VIE":{"unit":["855.5","864.0"],"disl":["844.0","854.0"]},"WAL":{"unit":["428.5","658.0"],"disl":["417.0","648.0"]},"WAR":{"unit":["983.5","740.0"],"disl":["972.0","730.0"]},"WES":{"unit":["462.5","1163.0"],"disl":["451.0","1153.0"]},"YOR":{"unit":["492.5","616.0"],"disl":["481.0","606.0"]}}; +export const SymbolSizes = {"Fleet":{"width":40.0,"height":40.0},"Army":{"width":40.0,"height":40.0},"Wing":{"width":40.0,"height":40.0},"DislodgedFleet":{"width":40.0,"height":40.0},"DislodgedArmy":{"width":40.0,"height":40.0},"DislodgedWing":{"width":40.0,"height":40.0},"FailedOrder":{"width":30.0,"height":30.0},"SupplyCenter":{"width":20.0,"height":20.0},"BuildUnit":{"width":60.0,"height":60.0},"RemoveUnit":{"width":50.0,"height":50.0},"WaivedBuild":{"width":40.0,"height":40.0},"HoldUnit":{"width":66.6,"height":66.6},"SupportHoldUnit":{"width":76.6,"height":76.6},"ConvoyTriangle":{"width":66.4,"height":57.4},"Stroke":{"width":6.0,"height":10.0}}; +export const Colors = {"AUSTRIA":"#c48f85","ENGLAND":"darkviolet","FRANCE":"royalblue","GERMANY":"#a08a75","ITALY":"forestgreen","RUSSIA":"#757d91","TURKEY":"#b9a61c"}; diff --git a/diplomacy/web/src/gui/maps/standard/build.js b/diplomacy/web/src/gui/maps/standard/build.js deleted file mode 100644 index cf28f19..0000000 --- a/diplomacy/web/src/gui/maps/standard/build.js +++ /dev/null @@ -1,53 +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 . -// ============================================================================== -import React from "react"; -import {ARMY, Coordinates, FLEET, offset, SymbolSizes} from "./common"; -import PropTypes from "prop-types"; - -export class Build extends React.Component { - render() { - const loc = this.props.loc; - const unit_type = this.props.unitType; - const loc_x = offset(Coordinates[loc].unit[0], -11.5); - const loc_y = offset(Coordinates[loc].unit[1], -10.); - const build_loc_x = offset(Coordinates[loc].unit[0], -20.5); - const build_loc_y = offset(Coordinates[loc].unit[1], -20.5); - const symbol = unit_type === 'A' ? ARMY : FLEET; - const build_symbol = 'BuildUnit'; - return ( - - - - - ); - } -} - -Build.propTypes = { - unitType: PropTypes.string.isRequired, - loc: PropTypes.string.isRequired, - powerName: PropTypes.string.isRequired -}; diff --git a/diplomacy/web/src/gui/maps/standard/common.js b/diplomacy/web/src/gui/maps/standard/common.js deleted file mode 100644 index cb768c2..0000000 --- a/diplomacy/web/src/gui/maps/standard/common.js +++ /dev/null @@ -1,75 +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 . -// ============================================================================== -import {SvgStandardExtra} from "./SvgStandardExtra"; - -const TAG_ORDERDRAWING = 'jdipNS:ORDERDRAWING'; -const TAG_POWERCOLORS = 'jdipNS:POWERCOLORS'; -const TAG_POWERCOLOR = 'jdipNS:POWERCOLOR'; -const TAG_SYMBOLSIZE = 'jdipNS:SYMBOLSIZE'; -const TAG_PROVINCE_DATA = 'jdipNS:PROVINCE_DATA'; -const TAG_PROVINCE = 'jdipNS:PROVINCE'; -const TAG_UNIT = 'jdipNS:UNIT'; -const TAG_DISLODGED_UNIT = 'jdipNS:DISLODGED_UNIT'; -const TAG_SUPPLY_CENTER = 'jdipNS:SUPPLY_CENTER'; - -export const ARMY = 'Army'; -export const FLEET = 'Fleet'; - -function getCoordinates() { - const coordinates = {}; - for (let provinceDefiniton of SvgStandardExtra[TAG_PROVINCE_DATA][TAG_PROVINCE]) { - const name = provinceDefiniton.name.toUpperCase().replace('-', '/'); - coordinates[name] = {}; - if (provinceDefiniton.hasOwnProperty(TAG_UNIT)) { - coordinates[name].unit = [provinceDefiniton[TAG_UNIT]['x'], provinceDefiniton[TAG_UNIT]['y']]; - } - if (provinceDefiniton.hasOwnProperty(TAG_DISLODGED_UNIT)) { - coordinates[name].disl = [provinceDefiniton[TAG_DISLODGED_UNIT]['x'], provinceDefiniton[TAG_DISLODGED_UNIT]['y']]; - } - if (provinceDefiniton.hasOwnProperty(TAG_SUPPLY_CENTER)) { - coordinates[name].sc = [provinceDefiniton[TAG_SUPPLY_CENTER]['x'], provinceDefiniton[TAG_SUPPLY_CENTER]['y']]; - } - } - return coordinates; -} - -function getSymbolSizes() { - const sizes = {}; - for (let definition of SvgStandardExtra[TAG_ORDERDRAWING][TAG_SYMBOLSIZE]) { - sizes[definition.name] = { - width: parseInt(definition.width), - height: parseInt(definition.height) - }; - } - return sizes; -} - -function getColors() { - const colors = {}; - for (let definition of SvgStandardExtra[TAG_ORDERDRAWING][TAG_POWERCOLORS][TAG_POWERCOLOR]) { - colors[definition.power.toUpperCase()] = definition.color; - } - return colors; -} - -export const Coordinates = getCoordinates(); -export const SymbolSizes = getSymbolSizes(); -export const Colors = getColors(); - -export function offset(floatString, offset) { - return "" + (parseFloat(floatString) + offset); -} diff --git a/diplomacy/web/src/gui/maps/standard/convoy.js b/diplomacy/web/src/gui/maps/standard/convoy.js deleted file mode 100644 index 03b4749..0000000 --- a/diplomacy/web/src/gui/maps/standard/convoy.js +++ /dev/null @@ -1,98 +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 . -// ============================================================================== -import React from "react"; -import {Colors, Coordinates, offset} from "./common"; -import PropTypes from "prop-types"; - -export class Convoy extends React.Component { - render() { - const loc = this.props.loc; - const src_loc = this.props.srcLoc; - const dest_loc = this.props.dstLoc; - const loc_x = offset(Coordinates[loc].unit[0], 10); - const loc_y = offset(Coordinates[loc].unit[1], 10); - const src_loc_x = offset(Coordinates[src_loc].unit[0], 10); - const src_loc_y = offset(Coordinates[src_loc].unit[1], 10); - let dest_loc_x = offset(Coordinates[dest_loc].unit[0], 10); - let dest_loc_y = offset(Coordinates[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(Coordinates[src_loc].unit[0], 10); - const triangle_loc_y = offset(Coordinates[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])); - } - - return ( - - - - - - - - - ); - } -} - -Convoy.propTypes = { - loc: PropTypes.string.isRequired, - srcLoc: PropTypes.string.isRequired, - dstLoc: PropTypes.string.isRequired, - powerName: PropTypes.string.isRequired -}; diff --git a/diplomacy/web/src/gui/maps/standard/disband.js b/diplomacy/web/src/gui/maps/standard/disband.js deleted file mode 100644 index 857ba70..0000000 --- a/diplomacy/web/src/gui/maps/standard/disband.js +++ /dev/null @@ -1,51 +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 . -// ============================================================================== -import React from "react"; -import {Coordinates, offset, SymbolSizes} from "./common"; -import PropTypes from "prop-types"; - -export class Disband extends React.Component { - render() { - const loc = this.props.loc; - const phaseType = this.props.phaseType; - let loc_x = 0; - let loc_y = 0; - if (phaseType === 'R') { - loc_x = offset(Coordinates[loc].unit[0], -29.); - loc_y = offset(Coordinates[loc].unit[1], -27.5); - } else { - loc_x = offset(Coordinates[loc].unit[0], -16.5); - loc_y = offset(Coordinates[loc].unit[1], -15.); - } - const symbol = 'RemoveUnit'; - return ( - - - - ); - } -} - -Disband.propTypes = { - loc: PropTypes.string.isRequired, - phaseType: PropTypes.string.isRequired -}; diff --git a/diplomacy/web/src/gui/maps/standard/hold.js b/diplomacy/web/src/gui/maps/standard/hold.js deleted file mode 100644 index 4a79deb..0000000 --- a/diplomacy/web/src/gui/maps/standard/hold.js +++ /dev/null @@ -1,45 +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 . -// ============================================================================== -import React from "react"; -import {Colors, Coordinates, offset} from "./common"; -import PropTypes from "prop-types"; - -export class Hold extends React.Component { - render() { - const polygon_coord = []; - const loc_x = offset(Coordinates[this.props.loc].unit[0], 8.5); - const loc_y = offset(Coordinates[this.props.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])); - } - return ( - - - - - ); - } -} - -Hold.propTypes = { - loc: PropTypes.string.isRequired, - powerName: PropTypes.string.isRequired -}; diff --git a/diplomacy/web/src/gui/maps/standard/move.js b/diplomacy/web/src/gui/maps/standard/move.js deleted file mode 100644 index 8351a96..0000000 --- a/diplomacy/web/src/gui/maps/standard/move.js +++ /dev/null @@ -1,69 +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 . -// ============================================================================== -import React from "react"; -import {Colors, Coordinates, offset} from "./common"; -import PropTypes from "prop-types"; - -export class Move extends React.Component { - render() { - const src_loc = this.props.srcLoc; - const dest_loc = this.props.dstLoc; - let src_loc_x = 0; - let src_loc_y = 0; - if (this.props.phaseType === 'R') { - src_loc_x = offset(Coordinates[src_loc].unit[0], -2.5); - src_loc_y = offset(Coordinates[src_loc].unit[1], -2.5); - } else { - src_loc_x = offset(Coordinates[src_loc].unit[0], 10); - src_loc_y = offset(Coordinates[src_loc].unit[1], 10); - } - let dest_loc_x = offset(Coordinates[dest_loc].unit[0], 10); - let dest_loc_y = offset(Coordinates[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.; - return ( - - - - - ); - } -} - -Move.propTypes = { - srcLoc: PropTypes.string.isRequired, - dstLoc: PropTypes.string.isRequired, - powerName: PropTypes.string.isRequired, - phaseType: PropTypes.string.isRequired -}; diff --git a/diplomacy/web/src/gui/maps/standard/supplyCenter.js b/diplomacy/web/src/gui/maps/standard/supplyCenter.js deleted file mode 100644 index 0663ede..0000000 --- a/diplomacy/web/src/gui/maps/standard/supplyCenter.js +++ /dev/null @@ -1,40 +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 . -// ============================================================================== -import React from "react"; -import {Coordinates, offset, SymbolSizes} from "./common"; -import PropTypes from "prop-types"; - -export class SupplyCenter extends React.Component { - render() { - const symbol = 'SupplyCenter'; - const loc_x = offset(Coordinates[this.props.loc].sc[0], -8.5); - const loc_y = offset(Coordinates[this.props.loc].sc[1], -11.0); - return ( - - ); - } -} - -SupplyCenter.propTypes = { - loc: PropTypes.string.isRequired, - powerName: PropTypes.string -}; diff --git a/diplomacy/web/src/gui/maps/standard/supportHold.js b/diplomacy/web/src/gui/maps/standard/supportHold.js deleted file mode 100644 index bfa2656..0000000 --- a/diplomacy/web/src/gui/maps/standard/supportHold.js +++ /dev/null @@ -1,73 +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 . -// ============================================================================== -import React from "react"; -import {Colors, Coordinates, offset} from "./common"; -import PropTypes from "prop-types"; - -export class SupportHold extends React.Component { - render() { - const loc = this.props.loc; - const dest_loc = this.props.dstLoc; - const loc_x = offset(Coordinates[loc].unit[0], 10); - const loc_y = offset(Coordinates[loc].unit[1], 10); - let dest_loc_x = offset(Coordinates[dest_loc].unit[0], 10); - let dest_loc_y = offset(Coordinates[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(Coordinates[dest_loc].unit[0], 8.5); - const poly_loc_y = offset(Coordinates[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])); - } - return ( - - - - - - - ); - } -} - -SupportHold.propTypes = { - loc: PropTypes.string.isRequired, - dstLoc: PropTypes.string.isRequired, - powerName: PropTypes.string.isRequired, -}; diff --git a/diplomacy/web/src/gui/maps/standard/supportMove.js b/diplomacy/web/src/gui/maps/standard/supportMove.js deleted file mode 100644 index e46abc3..0000000 --- a/diplomacy/web/src/gui/maps/standard/supportMove.js +++ /dev/null @@ -1,57 +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 . -// ============================================================================== -import React from "react"; -import {Colors, Coordinates, offset} from "./common"; -import PropTypes from "prop-types"; - -export class SupportMove extends React.Component { - render() { - const loc = this.props.loc; - const src_loc = this.props.srcLoc; - const dest_loc = this.props.dstLoc; - const loc_x = offset(Coordinates[loc].unit[0], 10); - const loc_y = offset(Coordinates[loc].unit[1], 10); - const src_loc_x = offset(Coordinates[src_loc].unit[0], 10); - const src_loc_y = offset(Coordinates[src_loc].unit[1], 10); - let dest_loc_x = offset(Coordinates[dest_loc].unit[0], 10); - let dest_loc_y = offset(Coordinates[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.; - return ( - - - - - ); - } -} - -SupportMove.propTypes = { - loc: PropTypes.string.isRequired, - srcLoc: PropTypes.string.isRequired, - dstLoc: PropTypes.string.isRequired, - powerName: PropTypes.string.isRequired, -}; diff --git a/diplomacy/web/src/gui/maps/standard/unit.js b/diplomacy/web/src/gui/maps/standard/unit.js deleted file mode 100644 index f32a678..0000000 --- a/diplomacy/web/src/gui/maps/standard/unit.js +++ /dev/null @@ -1,45 +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 . -// ============================================================================== -import React from "react"; -import {ARMY, Coordinates, FLEET, offset, SymbolSizes} from "./common"; -import PropTypes from "prop-types"; - -export class Unit extends React.Component { - render() { - const split_unit = this.props.unit.split(/ +/); - const unit_type = split_unit[0]; - const loc = split_unit[1]; - const dislogged_type = this.props.isDislodged ? 'disl' : 'unit'; - const symbol = unit_type === 'F' ? FLEET : ARMY; - const loc_x = offset(Coordinates[loc][dislogged_type][0], -11.5); - const loc_y = offset(Coordinates[loc][dislogged_type][1], -10.0); - return ( - - ); - } -} - -Unit.propTypes = { - unit: PropTypes.string.isRequired, - powerName: PropTypes.string.isRequired, - isDislodged: PropTypes.bool.isRequired, -}; -- cgit v1.2.3