aboutsummaryrefslogtreecommitdiff
path: root/diplomacy/web/src/gui/wizards
diff options
context:
space:
mode:
Diffstat (limited to 'diplomacy/web/src/gui/wizards')
-rw-r--r--diplomacy/web/src/gui/wizards/gameCreation/gameCreationWizard.js109
-rw-r--r--diplomacy/web/src/gui/wizards/gameCreation/mapList.js41
-rw-r--r--diplomacy/web/src/gui/wizards/gameCreation/panelChooseMap.js94
-rw-r--r--diplomacy/web/src/gui/wizards/gameCreation/panelChoosePlayers.js61
-rw-r--r--diplomacy/web/src/gui/wizards/gameCreation/panelChoosePower.js62
-rw-r--r--diplomacy/web/src/gui/wizards/gameCreation/panelChooseSettings.js113
-rw-r--r--diplomacy/web/src/gui/wizards/gameCreation/panelList.js6
7 files changed, 486 insertions, 0 deletions
diff --git a/diplomacy/web/src/gui/wizards/gameCreation/gameCreationWizard.js b/diplomacy/web/src/gui/wizards/gameCreation/gameCreationWizard.js
new file mode 100644
index 0000000..daaa461
--- /dev/null
+++ b/diplomacy/web/src/gui/wizards/gameCreation/gameCreationWizard.js
@@ -0,0 +1,109 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import {Panels} from "./panelList";
+import {PanelChooseMap} from "./panelChooseMap";
+import {PanelChoosePlayers} from "./panelChoosePlayers";
+import {PanelChoosePower} from "./panelChoosePower";
+import {PanelChooseSettings} from "./panelChooseSettings";
+import {Maps} from "./mapList";
+import {UTILS} from "../../../diplomacy/utils/utils";
+
+export class GameCreationWizard extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ panel: Panels.CHOOSE_MAP,
+ game_id: UTILS.createGameID(this.props.username),
+ power_name: null,
+ n_controls: -1,
+ deadline: 0,
+ registration_password: '',
+
+ map: Maps[0],
+ no_press: false
+ };
+ this.backward = this.backward.bind(this);
+ this.forward = this.forward.bind(this);
+ this.updateParams = this.updateParams.bind(this);
+ }
+
+ updateParams(params) {
+ this.setState(params);
+ }
+
+ goToPanel(panelID) {
+ if (panelID < Panels.CHOOSE_MAP)
+ this.props.onCancel();
+ else if (panelID > Panels.CHOOSE_SETTINGS) {
+ const rules = ['POWER_CHOICE'];
+ if (this.state.no_press)
+ rules.push('NO_PRESS');
+ if (!this.state.deadline) {
+ rules.push('NO_DEADLINE');
+ rules.push('REAL_TIME');
+ }
+ this.props.onSubmit({
+ game_id: this.state.game_id,
+ map_name: this.state.map.name,
+ power_name: this.state.power_name,
+ n_controls: this.state.n_controls,
+ deadline: this.state.deadline,
+ registration_password: this.state.registration_password || null,
+ rules: rules
+ });
+ } else
+ this.setState({panel: panelID, registration_password: ''});
+ }
+
+ backward(step) {
+ this.goToPanel(this.state.panel - (step ? step : 1));
+ }
+
+ forward(step) {
+ this.goToPanel(this.state.panel + (step ? step : 1));
+ }
+
+ renderPanel() {
+ switch (this.state.panel) {
+ case Panels.CHOOSE_MAP:
+ return <PanelChooseMap forward={this.forward}
+ params={this.state}
+ onUpdateParams={this.updateParams}
+ cancel={this.props.onCancel}/>;
+ case Panels.CHOOSE_PLAYERS:
+ return <PanelChoosePlayers backward={this.backward}
+ forward={this.forward}
+ onUpdateParams={this.updateParams}
+ nbPowers={this.props.availableMaps[this.state.map.name].powers.length}
+ cancel={this.props.onCancel}/>;
+ case Panels.CHOOSE_POWER:
+ return <PanelChoosePower backward={this.backward}
+ forward={this.forward}
+ onUpdateParams={this.updateParams}
+ powers={this.props.availableMaps[this.state.map.name].powers}
+ cancel={this.props.onCancel}/>;
+ case Panels.CHOOSE_SETTINGS:
+ return <PanelChooseSettings backward={this.backward}
+ forward={this.forward}
+ onUpdateParams={this.updateParams}
+ username={this.props.username}
+ params={this.state}
+ cancel={this.props.onCancel}/>;
+ default:
+ return '';
+ }
+ }
+
+ render() {
+ return (
+ <div className="game-creation-wizard">{this.renderPanel()}</div>
+ );
+ }
+}
+
+GameCreationWizard.propTypes = {
+ onCancel: PropTypes.func.isRequired,
+ onSubmit: PropTypes.func.isRequired,
+ availableMaps: PropTypes.object.isRequired,
+ username: PropTypes.string.isRequired
+};
diff --git a/diplomacy/web/src/gui/wizards/gameCreation/mapList.js b/diplomacy/web/src/gui/wizards/gameCreation/mapList.js
new file mode 100644
index 0000000..5d2c00a
--- /dev/null
+++ b/diplomacy/web/src/gui/wizards/gameCreation/mapList.js
@@ -0,0 +1,41 @@
+class VariantInfo {
+ constructor(variantName, variantTitle) {
+ this.name = variantName;
+ this.title = variantTitle;
+ this.map = null;
+ }
+
+ svgName() {
+ return this.map.name;
+ }
+}
+
+class MapInfo {
+ constructor(mapName, mapTitle, variants) {
+ this.name = mapName;
+ this.title = mapTitle;
+ this.variants = null;
+ if (variants) {
+ this.variants = [];
+ for (let variant of variants) {
+ variant.map = this;
+ this.variants.push(variant);
+ }
+ }
+ }
+
+ svgName() {
+ return this.name;
+ }
+}
+
+export const Maps = [
+ new MapInfo('standard', 'Standard', [
+ new VariantInfo('standard', 'Default'),
+ new VariantInfo('standard_age_of_empires', 'Age of empires'),
+ new VariantInfo('standard_age_of_empires_2', 'Age of empires II'),
+ new VariantInfo('standard_fleet_rome', 'Fleet at Rome'),
+ new VariantInfo('standard_france_austria', 'France VS Austria'),
+ new VariantInfo('standard_germany_italy', 'Germany VS Italy')
+ ]),
+];
diff --git a/diplomacy/web/src/gui/wizards/gameCreation/panelChooseMap.js b/diplomacy/web/src/gui/wizards/gameCreation/panelChooseMap.js
new file mode 100644
index 0000000..5c40f1c
--- /dev/null
+++ b/diplomacy/web/src/gui/wizards/gameCreation/panelChooseMap.js
@@ -0,0 +1,94 @@
+import React from "react";
+import {Maps} from "./mapList";
+import {FancyBox} from "../../components/fancyBox";
+import PropTypes from "prop-types";
+
+export class PanelChooseMap extends React.Component {
+ render() {
+ const mapImg = require(`../../../maps/svg/${this.props.params.map.svgName()}.svg`);
+ const mapEntries = [];
+ let count = 0;
+ for (let mapInfo of Maps) {
+ ++count;
+ if (!mapInfo.variants) {
+ mapEntries.push(
+ <div key={count} className="mb-1">
+ <button type="button"
+ className="btn btn-secondary btn-sm btn-block"
+ onMouseOver={() => this.props.onUpdateParams({map: mapInfo})}
+ onClick={() => this.props.forward()}>
+ {mapInfo.title}
+ </button>
+ </div>
+ );
+ } else {
+ const dropDownID = `collapse-${count}-${mapInfo.name}`;
+ const variants = mapInfo.variants.slice();
+ const defaultVariant = variants[0];
+ mapEntries.push(
+ <div key={count}>
+ <div className="mb-1 d-flex flex-row justify-content-center">
+ <button type="button"
+ className="btn btn-secondary btn-sm flex-grow-1 mr-1"
+ onMouseOver={() => this.props.onUpdateParams({map: defaultVariant})}
+ onClick={() => this.props.forward()}>
+ {mapInfo.title} ({defaultVariant.title})
+ </button>
+ <button type="button"
+ className="btn btn-outline-secondary btn-sm collapsed"
+ data-toggle="collapse"
+ data-target={`#${dropDownID}`}
+ aria-expanded={false}
+ aria-controls={dropDownID}>
+ <span className="unroll"><strong>+</strong></span>
+ <span className="roll"><strong>-</strong></span>
+ </button>
+ </div>
+ <div className="collapse" id={dropDownID}>
+ <div>
+ {(() => {
+ const views = [];
+ for (let i = 1; i < variants.length; ++i) {
+ const variantInfo = variants[i];
+ views.push(
+ <div key={variantInfo.name} className="mb-1">
+ <button type="button"
+ className="btn btn-outline-secondary btn-sm btn-block"
+ onMouseOver={() => this.props.onUpdateParams({map: variantInfo})}
+ onClick={() => this.props.forward()}>
+ {variantInfo.title}
+ </button>
+ </div>
+ );
+ }
+ return views;
+ })()}
+ </div>
+ </div>
+ </div>
+ );
+ }
+ }
+ return (
+ <FancyBox title={'Choose a map'} onClose={this.props.cancel}>
+ <div className="row panel-choose-map">
+ <div className="col-md">
+ <div className="map-list p-1 ml-0 ml-sm-1">
+ {mapEntries}
+ </div>
+ </div>
+ <div className="col-md">
+ <img className="img-fluid" src={mapImg} alt={this.props.params.map.title}/>
+ </div>
+ </div>
+ </FancyBox>
+ );
+ }
+}
+
+PanelChooseMap.propTypes = {
+ forward: PropTypes.func.isRequired,
+ cancel: PropTypes.func.isRequired,
+ params: PropTypes.object.isRequired,
+ onUpdateParams: PropTypes.func.isRequired
+};
diff --git a/diplomacy/web/src/gui/wizards/gameCreation/panelChoosePlayers.js b/diplomacy/web/src/gui/wizards/gameCreation/panelChoosePlayers.js
new file mode 100644
index 0000000..84a47a0
--- /dev/null
+++ b/diplomacy/web/src/gui/wizards/gameCreation/panelChoosePlayers.js
@@ -0,0 +1,61 @@
+import React from "react";
+import {FancyBox} from "../../components/fancyBox";
+import PropTypes from "prop-types";
+import Octicon, {ArrowLeft} from "@primer/octicons-react";
+
+export class PanelChoosePlayers extends React.Component {
+ render() {
+ return (
+ <FancyBox title={'Number of human players'} onClose={this.props.cancel}>
+ <div className="row">
+ <div className="col-sm">
+ <button type="button" className="btn btn-secondary btn-sm btn-block inline" onClick={() => {
+ this.props.onUpdateParams({n_controls: 0});
+ this.props.forward(2);
+ }}>None - just bots
+ </button>
+ </div>
+ <div className="col-sm">
+ <button type="button" className="btn btn-secondary btn-sm btn-block inline" onClick={() => {
+ this.props.onUpdateParams({n_controls: this.props.nbPowers});
+ this.props.forward();
+ }}>All humans - no bots
+ </button>
+ </div>
+ </div>
+ <div className="d-flex flex-row justify-content-center my-2">
+ {(() => {
+ const choice = [];
+ for (let i = 0; i < this.props.nbPowers; ++i) {
+ choice.push(
+ <button key={i} type="button"
+ className={`btn btn-secondary btn-sm flex-grow-1 ${i === 0 ? '' : 'ml-sm-1'}`}
+ onClick={() => {
+ this.props.onUpdateParams({n_controls: i + 1});
+ this.props.forward();
+ }}>
+ {i + 1}
+ </button>
+ );
+ }
+ return choice;
+ })()}
+ </div>
+ <div>
+ <button type="button" className="btn btn-secondary btn-sm px-3"
+ onClick={() => this.props.backward()}>
+ <Octicon icon={ArrowLeft}/>
+ </button>
+ </div>
+ </FancyBox>
+ );
+ }
+}
+
+PanelChoosePlayers.propTypes = {
+ backward: PropTypes.func.isRequired,
+ forward: PropTypes.func.isRequired,
+ cancel: PropTypes.func.isRequired,
+ onUpdateParams: PropTypes.func.isRequired,
+ nbPowers: PropTypes.number.isRequired
+};
diff --git a/diplomacy/web/src/gui/wizards/gameCreation/panelChoosePower.js b/diplomacy/web/src/gui/wizards/gameCreation/panelChoosePower.js
new file mode 100644
index 0000000..dc400bd
--- /dev/null
+++ b/diplomacy/web/src/gui/wizards/gameCreation/panelChoosePower.js
@@ -0,0 +1,62 @@
+import React from "react";
+import {FancyBox} from "../../components/fancyBox";
+import PropTypes from "prop-types";
+import Octicon, {ArrowLeft} from "@primer/octicons-react";
+
+export class PanelChoosePower extends React.Component {
+ render() {
+ return (
+ <FancyBox title={'Choose your power'} onClose={this.props.cancel}>
+ <div className="row">
+ <div className="col-sm">
+ <button type="button" className="btn btn-secondary btn-sm btn-block inline" onClick={() => {
+ this.props.onUpdateParams({power_name: null});
+ this.props.forward();
+ }}>I just want to observe
+ </button>
+ </div>
+ <div className="col-sm">
+ <button type="button" className="btn btn-secondary btn-sm btn-block inline" onClick={() => {
+ const powerName = this.props.powers[Math.floor(Math.random() * this.props.powers.length)];
+ this.props.onUpdateParams({power_name: powerName});
+ this.props.forward();
+ }}>Choose randomly for me
+ </button>
+ </div>
+ </div>
+ <div className="d-flex flex-row justify-content-center my-2">
+ {(() => {
+ const choice = [];
+ for (let i = 0; i < this.props.powers.length; ++i) {
+ choice.push(
+ <button key={i} type="button"
+ className={`btn btn-secondary btn-sm flex-grow-1 ${i === 0 ? '' : 'ml-sm-1'}`}
+ onClick={() => {
+ this.props.onUpdateParams({power_name: this.props.powers[i]});
+ this.props.forward();
+ }}>
+ {this.props.powers[i]}
+ </button>
+ );
+ }
+ return choice;
+ })()}
+ </div>
+ <div>
+ <button type="button" className="btn btn-secondary btn-sm px-3"
+ onClick={() => this.props.backward()}>
+ <Octicon icon={ArrowLeft}/>
+ </button>
+ </div>
+ </FancyBox>
+ );
+ }
+}
+
+PanelChoosePower.propTypes = {
+ backward: PropTypes.func.isRequired,
+ forward: PropTypes.func.isRequired,
+ cancel: PropTypes.func.isRequired,
+ onUpdateParams: PropTypes.func.isRequired,
+ powers: PropTypes.arrayOf(PropTypes.string).isRequired
+};
diff --git a/diplomacy/web/src/gui/wizards/gameCreation/panelChooseSettings.js b/diplomacy/web/src/gui/wizards/gameCreation/panelChooseSettings.js
new file mode 100644
index 0000000..e509158
--- /dev/null
+++ b/diplomacy/web/src/gui/wizards/gameCreation/panelChooseSettings.js
@@ -0,0 +1,113 @@
+import React from "react";
+import {FancyBox} from "../../components/fancyBox";
+import PropTypes from "prop-types";
+import {UTILS} from "../../../diplomacy/utils/utils";
+import Octicon, {ArrowLeft} from "@primer/octicons-react";
+
+const DEADLINES = [
+ [0, '(no deadline)'],
+ [60, '1 min'],
+ [60 * 5, '5 min'],
+ [60 * 30, '30 min'],
+ [60 * 60 * 2, '2 hrs'],
+ [60 * 60 * 24, '24 hrs'],
+];
+
+export class PanelChooseSettings extends React.Component {
+ constructor(props) {
+ super(props);
+ this.onCheckNoPress = this.onCheckNoPress.bind(this);
+ this.onSelectDeadline = this.onSelectDeadline.bind(this);
+ this.onSetRegistrationPassword = this.onSetRegistrationPassword.bind(this);
+ this.onSetGameID = this.onSetGameID.bind(this);
+ }
+
+ onCheckNoPress(event) {
+ this.props.onUpdateParams({no_press: event.target.checked});
+ }
+
+ onSelectDeadline(event) {
+ this.props.onUpdateParams({deadline: parseInt(event.target.value)});
+ }
+
+ onSetRegistrationPassword(event) {
+ this.props.onUpdateParams({registration_password: event.target.value});
+ }
+
+ onSetGameID(event) {
+ let gameID = event.target.value;
+ if (!gameID)
+ gameID = UTILS.createGameID(this.props.username);
+ this.props.onUpdateParams({game_id: gameID});
+ }
+
+ render() {
+ return (
+ <FancyBox title={'Other settings'} onClose={this.props.cancel}>
+ <div>
+ <form>
+ <div className="form-group row align-items-center mb-2">
+ <label className="col-md col-form-label" htmlFor="deadline">Deadline</label>
+ <div className="col-md">
+ <select id="deadline" className="custom-select custom-select-sm"
+ value={this.props.params.deadline}
+ onChange={this.onSelectDeadline}>
+ {DEADLINES.map((deadline, index) => (
+ <option key={index} value={deadline[0]}>{deadline[1]}</option>
+ ))}
+ </select>
+ </div>
+ </div>
+ <div className="form-group row mb-2">
+ <label className="col-md col-form-label" htmlFor="registration-password">Login
+ password</label>
+ <div className="col-md">
+ <input type="password" className="form-control form-control-sm"
+ id="registration-password"
+ value={this.props.params.registration_password}
+ onChange={this.onSetRegistrationPassword} placeholder="(no password)"/>
+ </div>
+ </div>
+ <div className="form-group row mb-2">
+ <label className="col-md col-form-label" htmlFor="game-id">Game ID</label>
+ <div className="col-md">
+ <input type="text" className="form-control form-control-sm"
+ id="game-id"
+ value={this.props.params.game_id}
+ onChange={this.onSetGameID}/>
+ </div>
+ </div>
+ <div className="custom-control custom-checkbox mb-5">
+ <input type="checkbox" className="custom-control-input" id="no-press"
+ checked={this.props.params.no_press} onChange={this.onCheckNoPress}/>
+ <label className="custom-control-label" htmlFor="no-press">No messages allowed</label>
+ </div>
+ </form>
+ </div>
+ <div className="row">
+ <div className="col-sm">
+ <button type="button" className="btn btn-secondary btn-sm btn-block"
+ onClick={() => this.props.backward()}>
+ <Octicon icon={ArrowLeft}/>
+ </button>
+ </div>
+ <div className="col-sm">
+ <button type="button" className="btn btn-success btn-sm btn-block inline"
+ onClick={() => this.props.forward()}>
+ <strong>create the game</strong>
+ </button>
+ </div>
+ </div>
+ </FancyBox>
+ );
+ }
+}
+
+PanelChooseSettings.propTypes = {
+ backward: PropTypes.func.isRequired,
+ forward: PropTypes.func.isRequired,
+ cancel: PropTypes.func.isRequired,
+ params: PropTypes.object.isRequired,
+ onUpdateParams: PropTypes.func.isRequired,
+ username: PropTypes.string.isRequired
+};
diff --git a/diplomacy/web/src/gui/wizards/gameCreation/panelList.js b/diplomacy/web/src/gui/wizards/gameCreation/panelList.js
new file mode 100644
index 0000000..0b6100c
--- /dev/null
+++ b/diplomacy/web/src/gui/wizards/gameCreation/panelList.js
@@ -0,0 +1,6 @@
+export const Panels = {
+ CHOOSE_MAP: 0,
+ CHOOSE_PLAYERS: 1,
+ CHOOSE_POWER: 2,
+ CHOOSE_SETTINGS: 3
+};