diff options
| author | notoraptor <stevenbocco@gmail.com> | 2019-08-14 12:22:22 -0400 | 
|---|---|---|
| committer | Philip Paquette <pcpaquette@gmail.com> | 2019-08-14 12:40:01 -0400 | 
| commit | 5c3bd9b3802e2001a7e77baf2911386135a03839 (patch) | |
| tree | e641744650b05cddc85bc60c2d7e2d6fe2d88b47 /diplomacy/web/src/gui/maps/common | |
| parent | 5acb4ff23be4757a49b234f93928f13c436b60c6 (diff) | |
[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.
Diffstat (limited to 'diplomacy/web/src/gui/maps/common')
| -rw-r--r-- | diplomacy/web/src/gui/maps/common/build.js | 57 | ||||
| -rw-r--r-- | diplomacy/web/src/gui/maps/common/common.js | 83 | ||||
| -rw-r--r-- | diplomacy/web/src/gui/maps/common/convoy.js | 103 | ||||
| -rw-r--r-- | diplomacy/web/src/gui/maps/common/disband.js | 47 | ||||
| -rw-r--r-- | diplomacy/web/src/gui/maps/common/equilateralTriangle.js | 122 | ||||
| -rw-r--r-- | diplomacy/web/src/gui/maps/common/hold.js | 47 | ||||
| -rw-r--r-- | diplomacy/web/src/gui/maps/common/move.js | 67 | ||||
| -rw-r--r-- | diplomacy/web/src/gui/maps/common/supportHold.js | 72 | ||||
| -rw-r--r-- | diplomacy/web/src/gui/maps/common/supportMove.js | 61 | ||||
| -rw-r--r-- | diplomacy/web/src/gui/maps/common/unit.js | 50 | 
10 files changed, 709 insertions, 0 deletions
| 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 <https://www.gnu.org/licenses/>. +// ============================================================================== +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 ( +            <g> +                <use x={build_loc_x} +                     y={build_loc_y} +                     height={SymbolSizes[build_symbol].height} +                     width={SymbolSizes[build_symbol].width} +                     href={`#${build_symbol}`}/> +                <use x={loc_x} +                     y={loc_y} +                     height={SymbolSizes[symbol].height} +                     width={SymbolSizes[symbol].width} +                     href={`#${symbol}`} +                     className={`unit${this.props.powerName.toLowerCase()}`}/> +            </g> +        ); +    } +} + +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 <https://www.gnu.org/licenses/>. +// ============================================================================== + +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 <https://www.gnu.org/licenses/>. +// ============================================================================== +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 ( +            <g stroke={Colors[this.props.powerName]}> +                <line x1={loc_x} +                      y1={loc_y} +                      x2={src_loc_x_1} +                      y2={src_loc_y_1} +                      className={'shadowdash'}/> +                <line x1={src_loc_x_2} +                      y1={src_loc_y_2} +                      x2={dest_loc_x} +                      y2={dest_loc_y} +                      className={'shadowdash'}/> +                <line x1={loc_x} +                      y1={loc_y} +                      x2={src_loc_x_1} +                      y2={src_loc_y_1} +                      className={'convoyorder'} +                      stroke={Colors[this.props.powerName]}/> +                <line x1={src_loc_x_2} +                      y1={src_loc_y_2} +                      x2={dest_loc_x} +                      y2={dest_loc_y} +                      className={'convoyorder'} +                      markerEnd={'url(#arrow)'} +                      stroke={Colors[this.props.powerName]}/> +                <use +                    x={symbol_loc_x} +                    y={symbol_loc_y} +                    width={'' + symbol_width} +                    height={'' + symbol_height} +                    href={`#${symbol}`} +                /> +            </g> +        ); +    } +} + +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 <https://www.gnu.org/licenses/>. +// ============================================================================== +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 ( +            <g> +                <use x={loc_x} +                     y={loc_y} +                     height={SymbolSizes[symbol].height} +                     width={SymbolSizes[symbol].width} +                     href={`#${symbol}`} +                /> +            </g> +        ); +    } +} + +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 <https://www.gnu.org/licenses/>. +// ============================================================================== +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 ( +            <g stroke={Colors[this.props.powerName]}> +                <use +                    x={loc_x} +                    y={loc_y} +                    width={SymbolSizes[symbol].width} +                    height={SymbolSizes[symbol].height} +                    href={`#${symbol}`}/> +            </g> +        ); +    } +} + +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 <https://www.gnu.org/licenses/>. +// ============================================================================== +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 ( +            <g> +                <line x1={src_loc_x} +                      y1={src_loc_y} +                      x2={dest_loc_x} +                      y2={dest_loc_y} +                      className={'varwidthshadow'} +                      strokeWidth={'' + plainStrokeWidth(SymbolSizes)}/> +                <line x1={src_loc_x} +                      y1={src_loc_y} +                      x2={dest_loc_x} +                      y2={dest_loc_y} +                      className={'varwidthorder'} +                      markerEnd={'url(#arrow)'} +                      stroke={Colors[this.props.powerName]} +                      strokeWidth={'' + coloredStrokeWidth(SymbolSizes)}/> +            </g> +        ); +    } +} + +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 <https://www.gnu.org/licenses/>. +// ============================================================================== +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 ( +            <g stroke={Colors[this.props.powerName]}> +                <line x1={loc_x} +                      y1={loc_y} +                      x2={dest_loc_x} +                      y2={dest_loc_y} +                      className={'shadowdash'}/> +                <line x1={loc_x} +                      y1={loc_y} +                      x2={dest_loc_x} +                      y2={dest_loc_y} +                      className={'supportorder'} +                      stroke={Colors[this.props.powerName]}/> +                <use +                    x={symbol_loc_x} +                    y={symbol_loc_y} +                    width={SymbolSizes[symbol].width} +                    height={SymbolSizes[symbol].height} +                    href={`#${symbol}`} +                /> +            </g> +        ); +    } +} + +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 <https://www.gnu.org/licenses/>. +// ============================================================================== +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 ( +            <g> +                <path className={'shadowdash'} +                      d={`M ${loc_x},${loc_y} C ${src_loc_x},${src_loc_y} ${src_loc_x},${src_loc_y} ${dest_loc_x},${dest_loc_y}`}/> +                <path className={'supportorder'} +                      markerEnd={'url(#arrow)'} +                      stroke={Colors[this.props.powerName]} +                      d={`M ${loc_x},${loc_y} C ${src_loc_x},${src_loc_y} ${src_loc_x},${src_loc_y} ${dest_loc_x},${dest_loc_y}`}/> +            </g> +        ); +    } +} + +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 <https://www.gnu.org/licenses/>. +// ============================================================================== +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 ( +            <use href={`#${this.props.isDislodged ? 'Dislodged' : ''}${symbol}`} +                 x={loc_x} +                 y={loc_y} +                 id={`${this.props.isDislodged ? 'dislodged_' : ''}unit_${loc}`} +                 width={SymbolSizes[symbol].width} +                 height={SymbolSizes[symbol].height} +                 className={`unit${this.props.powerName.toLowerCase()}`}/> +        ); +    } +} + +Unit.propTypes = { +    unit: PropTypes.string.isRequired, +    powerName: PropTypes.string.isRequired, +    isDislodged: PropTypes.bool.isRequired, +    coordinates: PropTypes.object.isRequired, +    symbolSizes: PropTypes.object.isRequired +}; | 
