diff --git a/src/App.css b/src/App.css index 5a477f679bfbf8c30d23e742e4ed96648624cc75..fe44e37477b045f8d82ed74f1ef0658da3cbacd1 100644 --- a/src/App.css +++ b/src/App.css @@ -304,3 +304,50 @@ div.login button:hover { .filterContainer input:hover { cursor: pointer; } + +/* Score Counter */ +/* div.scoreContainer { + border-radius: 8px; + position: absolute; + display: flex; + flex-direction: row; + color: white; + background-color: #1d1d1b; + opacity: 0.9; + height: 50px; + max-width: 400px; + margin: auto; + top: 5px; + left: calc(50vw - 100px); + align-items: center; + justify-content: center; + z-index: 1000; +} + +div.scoreBlock { + flex: 1; + padding: 5px; + max-width: 120px; + text-align: center; + justify-content: center; + letter-spacing: 0.05em; + font-size: 1.5em; +} + +div.scoreDivider { + background-color: white; + float: left; + flex: 1; + width: 2px; + height: 70%; + margin: 5px; +} + +span.scoreCircle { + margin: 10px; + height: 25px; + width: 25px; + background-color: red; + border-radius: 50%; + display: inline-block; +} */ diff --git a/src/components/GameView.js b/src/components/GameView.js index 82c9091dcb128110e0f0662e296a6767967c9090..73f61c60cfb6160af96c32850113f711bb2f2eb7 100644 --- a/src/components/GameView.js +++ b/src/components/GameView.js @@ -66,6 +66,37 @@ export default class GameView extends React.Component { }); } + handleLeaveFaction = e => { + let token = sessionStorage.getItem("token"); + let error = false; + fetch( + `${process.env.REACT_APP_API_URL}/faction/leave/${ + this.state.gameInfo.id + }`, + { + method: "DELETE", + headers: { + Authorization: "Bearer " + token + } + } + ) + .then(res => { + if (!res.ok) { + throw Error(); + } else { + return res.json(); + } + }) + .then(res => { + alert(res.message); + this.getPlayerRole(this.state.gameInfo.id); + }) + .catch(error => { + alert("Game not found"); + window.document.location.href = "/"; + }); + }; + handleLeaveFaction = e => { if (window.confirm("Are you sure you want to leave your faction?")) { let token = sessionStorage.getItem("token"); diff --git a/src/components/ReplayMap.js b/src/components/ReplayMap.js index 1e6305e1fe5e32757d3f78f8884f188aa862153a..2a16aeb726086efcf62f2b866d61cb8024dad537 100644 --- a/src/components/ReplayMap.js +++ b/src/components/ReplayMap.js @@ -15,9 +15,11 @@ export default class ReplayMap extends React.Component { // stores the playback object playback: null, // stores player locations from backend - data: null, + players: [], // stores all factions from the game factions: [], + // stores all scores from the game + scores: [], // stores all drawings from backend allGeoJSON: [], // stores all active drawings on the map @@ -30,32 +32,19 @@ export default class ReplayMap extends React.Component { await this.setState({ gameId: await new URL(window.location.href).searchParams.get("id") }); - // fetch player data with gameId - // throws error if game is not found and redirects back to game selection + // fetch all data and set it to state + let replaydata = await this.fetchReplayData(); await this.setState({ - data: await this.fetchPlayerData() + players: replaydata.players, + factions: replaydata.factions, + scores: replaydata.scores }); - // fetch factions from the game - await this.setState({ - factions: await this.fetchFactions() - }); - // fetch drawings with gameId - await this.setState({ - allGeoJSON: await this.fetchDrawingData() - }); - // WIP, map only active drawings to activeGeoJSON state - await this.setState({ - activeGeoJSON: this.tickDrawings() - }); - // if game was found but game has no replay data, alert the user - this.state.data.length > 1 - ? this.replay() - : alert("No replay data was found"); + replaydata ? this.replay() : alert("No replay data was found"); } - fetchPlayerData = async () => { + fetchReplayData = async () => { let res = await fetch( - `${process.env.REACT_APP_API_URL}/replay/players/${this.state.gameId}` + `${process.env.REACT_APP_API_URL}/replay/${this.state.gameId}` ); if (await res.ok) { return await res.json(); @@ -65,36 +54,6 @@ export default class ReplayMap extends React.Component { } }; - fetchFactions = async () => { - let res = await fetch( - `${process.env.REACT_APP_API_URL}/game/${this.state.gameId}` - ); - if (await res.ok) { - let data = await res.json(); - let factions = data.factions.map(faction => { - return { - name: faction.factionName, - colour: faction.colour, - active: true - }; - }); - return await factions; - } else { - alert(res.statusText); - } - }; - - fetchDrawingData = async () => { - let res = await fetch( - `${process.env.REACT_APP_API_URL}/replay/${this.state.gameId}` - ); - if (await res.ok) { - return await res.json(); - } else { - alert(res.statusText); - } - }; - tickDrawings = () => { return this.state.allGeoJSON.map(drawing => { return drawing[0]; @@ -107,7 +66,7 @@ export default class ReplayMap extends React.Component { attribution: '© <a href="https://www.maanmittauslaitos.fi/">Maanmittauslaitos</a>' }).addTo(this.map); - this.trackplayback = new L.TrackPlayBack(this.state.data, this.map, { + this.trackplayback = new L.TrackPlayBack(this.state.players, this.map, { trackPointOptions: { // whether to draw track point isDraw: true, @@ -149,6 +108,9 @@ export default class ReplayMap extends React.Component { }, filterOptions: { factions: this.state.factions + }, + scoreOptions: { + scores: this.state.scores } }); this.setState({ diff --git a/src/components/TaskItem.js b/src/components/TaskItem.js index 4a849ef3ae726f17496d4be45ab1e74c64b9b96d..21644f10a0bde41ed9d09b7c0a02406969ede078 100644 --- a/src/components/TaskItem.js +++ b/src/components/TaskItem.js @@ -70,15 +70,11 @@ class TaskItem extends React.Component { }; render() { - let factionlistItems = []; - for (let i = 0; i < this.state.factions.length; i++) { - const faction = this.state.factions[i]; - factionlistItems.push( - <option key={faction.factionId} value={faction.factionId}> - {faction.factionName} - </option> - ); - } + let factionlistItems = this.state.factions.map(faction => ( + <option key={faction.factionId} value={faction.factionId}> + {faction.factionName} + </option> + )); return ( <div className="tasklist-item"> diff --git a/src/components/UserMap.js b/src/components/UserMap.js index 7b459ba579f18753770610a3764050674d66a76d..83f4de8d09da8efa58426855273b27fbf4145b0b 100644 --- a/src/components/UserMap.js +++ b/src/components/UserMap.js @@ -163,7 +163,6 @@ class UserMap extends Component { url={this.props.mapUrl} /> <ZoomControl position="topright" /> - <DrawTools position={this.props.position} sendGeoJSON={this.sendGeoJSON} @@ -171,7 +170,6 @@ class UserMap extends Component { currentGameId={this.props.currentGameId} role={this.props.role} /> - {this.state.ownLat !== null && ( <Marker position={[this.state.ownLat, this.state.ownLng]}> <Popup> diff --git a/src/track-playback/src/control.trackplayback/control.playback.js b/src/track-playback/src/control.trackplayback/control.playback.js index 18ee33f079993f32cc1b92a2d197f82845cb0776..2d2e9f5ddd0da2e61f9ed56fe45e862ac53f84a7 100644 --- a/src/track-playback/src/control.trackplayback/control.playback.js +++ b/src/track-playback/src/control.trackplayback/control.playback.js @@ -136,17 +136,29 @@ export const TrackPlayBackControl = L.Control.extend({ "faction-text-filter", this._filterContainer ); - // create checkboxes for filtering persons based on their faction + // get factions in replay let factions = this.trackPlayBack.passFactions(); - let factionCheckboxes = []; - factions.map(faction => { - factionCheckboxes.push( - this._createCheckbox( - `show ${faction.name}`, - `show-${faction.name}`, - this._filterContainer, - this._showFaction - ) + // create checkboxes for filtering persons based on their faction + this._factionCheckboxes = factions.map(faction => { + return this._createCheckbox( + `show ${faction.name}`, + `show-${faction.name}`, + this._filterContainer, + this._showFaction + ); + }); + // create a div container for score replay + this._scoreContainer = this._createContainer( + "scoreContainer", + this._container + ); + // create score blocks for each faction + this._factionScoreboxes = factions.map(faction => { + return this._createInfo( + `${faction.name}: `, + 0, + "scoreBlock", + this._scoreContainer ); }); @@ -367,6 +379,10 @@ export const TrackPlayBackControl = L.Control.extend({ // 更新时间 let time = this.getTimeStrFromUnix(e.time); this._infoCurTime.innerHTML = time; + // tick scores + for (let i = 0; i < this._factionScoreboxes.length; i++) { + this._factionScoreboxes[i].innerHTML = this.trackPlayBack.passScores(i); + } // 更新时间轴 this._slider.value = e.time; // æ’放结æŸåŽæ”¹å˜æ’æ”¾æŒ‰é’®æ ·å¼ diff --git a/src/track-playback/src/leaflet.trackplayback/draw.js b/src/track-playback/src/leaflet.trackplayback/draw.js index 9949f45fd090be1efdf684b9fcc556ee0eb66ac6..8fdfefcb7a6e9813126ec42f006944ab3854bd53 100644 --- a/src/track-playback/src/leaflet.trackplayback/draw.js +++ b/src/track-playback/src/leaflet.trackplayback/draw.js @@ -53,6 +53,7 @@ export const Draw = L.Class.extend({ L.extend(this.targetOptions, options.targetOptions); L.extend(this.toolTipOptions, options.toolTipOptions); L.extend(this.filterOptions, options.filterOptions); + L.extend(this.scoreOptions, options.scoreOptions); this._showTrackPoint = this.trackPointOptions.isDraw; this._showTrackLine = this.trackLineOptions.isDraw; diff --git a/src/track-playback/src/leaflet.trackplayback/trackcontroller.js b/src/track-playback/src/leaflet.trackplayback/trackcontroller.js index 2e8157437f541500e2aa0774329d2c9969a7d6ce..c2d53d9a230b2ae1e81fddc2c3d2cbba02470af0 100644 --- a/src/track-playback/src/leaflet.trackplayback/trackcontroller.js +++ b/src/track-playback/src/leaflet.trackplayback/trackcontroller.js @@ -8,10 +8,11 @@ import { Track } from "./track"; * 控制轨迹和绘制 */ export const TrackController = L.Class.extend({ - initialize: function(tracks = [], draw, options) { + initialize: function(tracks = [], draw, allScores, options) { L.setOptions(this, options); - + this._activeScores = [0, 0]; this._tracks = []; + this._scores = allScores.scores; this.addTrack(tracks); this._draw = draw; @@ -49,6 +50,16 @@ export const TrackController = L.Class.extend({ let tps = track.getTrackPointsBeforeTime(time); if (tps && tps.length) this._draw.drawTrack(tps); } + for (let i = 0; i < this._scores.length; i++) { + let newScore = 0; + let scores = this._scores[i]; + for (let j = 0; j < scores.length; j++) { + if (scores[j].timestamp < time) { + newScore = scores[j].score; + } + } + this._activeScores[i] = newScore; + } }, _updateTime: function() { diff --git a/src/track-playback/src/leaflet.trackplayback/trackplayback.js b/src/track-playback/src/leaflet.trackplayback/trackplayback.js index 5aa35aa0cabe74f17ee026b3108bc55bacad4b45..c26733cbfdc9f6056af2ca68b39e62d5de358654 100644 --- a/src/track-playback/src/leaflet.trackplayback/trackplayback.js +++ b/src/track-playback/src/leaflet.trackplayback/trackplayback.js @@ -23,10 +23,15 @@ export const TrackPlayBack = L.Class.extend({ targetOptions: options.targetOptions, toolTipOptions: options.toolTipOptions, filterOptions: options.filterOptions + //scoreOptions: options.scoreOptions }; this.tracks = this._initTracks(data); this.draw = new Draw(map, drawOptions); - this.trackController = new TrackController(this.tracks, this.draw); + this.trackController = new TrackController( + this.tracks, + this.draw, + options.scoreOptions + ); this.clock = new Clock(this.trackController, options.clockOptions); this.clock.on("tick", this._tick, this); @@ -118,6 +123,9 @@ export const TrackPlayBack = L.Class.extend({ passFactions: function() { return this.draw.filterOptions.factions; }, + passScores: function(i) { + return this.trackController._activeScores[i]; + }, dispose: function() { this.clock.off("tick", this._tick); this.draw.remove();