import { AssumeUserIdButton } from "javascripts/components/user"; const React = require("react"); const helper = require("javascripts/helper"); const enslUrl = helper.enslUrl; const rankVotes = helper.rankVotes; const obsUrl = helper.observatoryUrl; const SelectPlayerButton = React.createClass({ propTypes: { socket: React.PropTypes.object.isRequired, gather: React.PropTypes.object.isRequired, gatherer: React.PropTypes.object.isRequired }, selectPlayer(e) { e.preventDefault(); this.props.socket.emit("gather:select", { type: this.props.gather.type, player: parseInt(e.target.value, 10) }); }, render() { let button; if (this.props.gatherer.leader) { button = ; } else if (this.props.gatherer.team !== "lobby") { button = ; } else { button = ; } return button; } }); const GathererList = React.createClass({ memberList() { const self = this; return this.props.gather.gatherers .filter(gatherer => gatherer.team === self.props.team) .sort(gatherer => { return gatherer.leader ? 1 : -1 }); }, render() { const extractGatherer = gatherer => { let image; if (gatherer.leader) { image = ; } return ( {image}{gatherer.user.username} ); }; const members = this.memberList() .map(extractGatherer); return ( {members}
); } }); const GatherTeams = React.createClass({ render() { return (
Marines
Aliens
); } }); const ElectionProgressBar = React.createClass({ componentDidMount() { const self = this; this.timer = setInterval(() => { self.forceUpdate(); }, 900); }, progress() { const interval = this.props.gather.election.interval; const startTime = (new Date(this.props.gather.election.startTime)).getTime(); const msTranspired = Math.floor((new Date()).getTime() - startTime); return { num: msTranspired, den: interval, barMessage: Math.floor((interval - msTranspired) / 1000) + "s remaining" } }, componentWillUnmount() { clearInterval(this.timer); }, render() { return (); } }); const ProgressBar = React.createClass({ render() { const progress = this.props.progress; const style = { width: Math.round((progress.num / progress.den * 100)) + "%" }; const barMessage = progress.barMessage || ""; return (
{barMessage}
); } }); const GatherProgress = React.createClass({ stateDescription() { switch (this.props.gather.state) { case "gathering": return "Waiting for more gatherers."; case "election": return "Currently voting for team leaders."; case "selection": return "Waiting for leaders to pick teams."; case "done": return "Gather completed."; default: return "Initialising gather."; } }, gatheringProgress() { const gather = this.props.gather; const num = gather.gatherers.length; const den = gather.teamSize * 2; const remaining = den - num; const message = (remaining === 1) ? "Waiting for last player" : `Waiting for ${remaining} more players`; return { num: num, den: den, message: message }; }, electionProgress() { const gather = this.props.gather; const num = gather.gatherers.reduce((acc, gatherer) => { if (gatherer.leaderVote) acc++; return acc; }, 0); const den = gather.teamSize * 2; return { num: num, den: den, message: den - num + " more votes required" }; }, selectionProgress() { const gather = this.props.gather; const num = gather.gatherers.reduce((acc, gatherer) => { if (gatherer.team !== "lobby") acc++; return acc; }, 0); const den = gather.teamSize * 2; return { num: num, den: den, message: `${num} out of ${den} players assigned. Waiting on ${_.capitalize(gather.pickingTurn)}s to pick next...` }; }, render() { let progress, progressBar; const gatherState = this.props.gather.state; if (gatherState === 'gathering' && this.props.gather.gatherers.length) { progress = this.gatheringProgress(); progressBar = (); } else if (gatherState === 'election') { progress = this.electionProgress(); progressBar = (); } else if (gatherState === 'selection') { progress = this.selectionProgress(); progressBar = (); } if (!progress) return false; return (

{this.stateDescription()} {progress.message}

{progressBar}
); } }); const JoinGatherButton = React.createClass({ propTypes: { thisGatherer: React.PropTypes.object, user: React.PropTypes.object.isRequired, socket: React.PropTypes.object.isRequired, gather: React.PropTypes.object.isRequired }, componentDidMount() { const self = this; this.timer = setInterval(() => { self.forceUpdate(); }, 30000); }, componentWillUnmount() { clearInterval(this.timer); }, joinGather(e) { e.preventDefault(); this.props.socket.emit("gather:join", { type: this.props.gather.type }); }, leaveGather(e) { e.preventDefault(); this.props.socket.emit("gather:leave", { type: this.props.gather.type }); }, cooldownTime() { let user = this.props.user; if (!user) return false; let cooloffTime = this.props.gather.cooldown[user.id]; if (!cooloffTime) return false; let timeRemaining = new Date(cooloffTime) - new Date(); return timeRemaining > 0 ? timeRemaining : false; }, render() { let gather = this.props.gather; let thisGatherer = this.props.thisGatherer; if (thisGatherer) { return ; } if (gather.state === 'gathering') { let cooldownTime = this.cooldownTime(); if (cooldownTime) { return ; } else { return ; } } return false; } }); const CooloffButton = React.createClass({ propTypes: { timeRemaining: React.PropTypes.number.isRequired }, timeRemaining() { return `${Math.floor(this.props.timeRemaining / 60000) + 1} minutes remaining`; }, render() { return } }) const GatherActions = React.createClass({ propTypes: { socket: React.PropTypes.object.isRequired, gather: React.PropTypes.object.isRequired, thisGatherer: React.PropTypes.object }, voteRegather(e) { e.preventDefault(e); this.props.socket.emit("gather:vote", { type: this.props.gather.type, regather: (e.target.value === "true") }); }, regatherVotes() { let gather = this.props.gather; if (!gather) return 0; return gather.gatherers.reduce((acc, gatherer) => { if (gatherer.regatherVote) acc++; return acc; }, 0); }, render() { let regatherButton; const user = this.props.user; const gather = this.props.gather; const socket = this.props.socket; const thisGatherer = this.props.thisGatherer; if (thisGatherer) { let regatherVotes = this.regatherVotes(); if (thisGatherer.regatherVote) { regatherButton = ; } else { regatherButton = ; } } return (
  • {regatherButton}
); } }); const VoteButton = React.createClass({ propTypes: { socket: React.PropTypes.object.isRequired, candidate: React.PropTypes.object.isRequired, thisGatherer: React.PropTypes.object, gather: React.PropTypes.object.isRequired }, cancelVote(e) { this.props.socket.emit("gather:vote", { type: this.props.gather.type, leader: { candidate: null } }); }, vote(e) { e.preventDefault(); this.props.socket.emit("gather:vote", { type: this.props.gather.type, leader: { candidate: parseInt(e.target.value, 10) } }); }, stopGatherMusic() { soundController.stop(); }, render() { let candidate = this.props.candidate; let thisGatherer = this.props.thisGatherer; if (thisGatherer === null) { return false; } if (thisGatherer.leaderVote === candidate.id) { return ( ); } else { return ( ); } } }); const ServerVoting = React.createClass({ propTypes: { socket: React.PropTypes.object.isRequired, gather: React.PropTypes.object.isRequired, thisGatherer: React.PropTypes.object, }, voteHandler(serverId) { return e => { e.preventDefault(); this.props.socket.emit("gather:vote", { type: this.props.gather.type, server: { id: serverId } }); } }, votesForServer(server) { return this.props.gather.gatherers.reduce((acc, gatherer) => { if (gatherer.serverVote.some(voteId => voteId === server.id)) acc++; return acc; }, 0); }, render() { let self = this; let thisGatherer = self.props.thisGatherer; let servers = self.props.gather.servers.sort((a, b) => { const aVotes = self.votesForServer(a); const bVotes = self.votesForServer(b); return bVotes - aVotes; }).map(server => { let votes = self.votesForServer(server); let style = thisGatherer.serverVote.some(voteId => voteId === server.id) ? "list-group-item list-group-item-success" : "list-group-item"; return ( {votes} {server.name || server.description} ); }); let votes = thisGatherer.serverVote.length; return (
{votes === 2 ? "Server Votes" : `Please Vote for a Server. ${2 - votes} votes remaining`}
{servers}
); } }) const MapVoting = React.createClass({ propTypes: { socket: React.PropTypes.object.isRequired, gather: React.PropTypes.object.isRequired, thisGatherer: React.PropTypes.object, maps: React.PropTypes.array.isRequired, }, voteHandler(mapId) { return e => { e.preventDefault(); this.props.socket.emit("gather:vote", { type: this.props.gather.type, map: { id: mapId } }); } }, votesForMap(map) { return this.props.gather.gatherers.reduce((acc, gatherer) => { if (gatherer.mapVote.some(voteId => voteId === map.id)) acc++; return acc; }, 0); }, render() { const self = this; let thisGatherer = self.props.thisGatherer let maps = self.props.maps.sort((a, b) => { const aVotes = self.votesForMap(a); const bVotes = self.votesForMap(b); return bVotes - aVotes; }).map(map => { let votes = self.votesForMap(map); let style = thisGatherer.mapVote.some(voteId => voteId === map.id) ? "list-group-item list-group-item-success" : "list-group-item"; return ( {votes} {map.name} ); }); let votes = thisGatherer.mapVote.length; return (
{votes === 2 ? "Map Votes" : `Please Vote for a Map. ${2 - votes} votes remaining`}
{maps}
); } }) const Gather = exports.Gather = React.createClass({ propTypes: { thisGatherer: React.PropTypes.object, maps: React.PropTypes.array.isRequired, socket: React.PropTypes.object.isRequired, gather: React.PropTypes.object.isRequired }, render() { const socket = this.props.socket; const gather = this.props.gather; const thisGatherer = this.props.thisGatherer; const soundController = this.props.soundController; const maps = this.props.maps; const user = this.props.user; if (gather === null) return
; let voting; if (thisGatherer) { let state = gather.state; if (state === 'gathering' || state === 'election') { voting = (
); } else { voting = ; } } let gatherTeams; if (gather.state === 'selection') { gatherTeams = ; } if (gather.gatherers.length > 0) { return (
{gather.name} ({gather.description})
{gatherTeams} {voting}
); } else { return (
{gather.name} ({gather.description})
); } } }); const LifeformIcons = exports.LifeformIcons = React.createClass({ availableLifeforms() { return ["skulk", "gorge", "lerk", "fade", "onos", "commander"]; }, gathererLifeforms() { let lifeforms = []; let gatherer = this.props.gatherer; let abilities = gatherer.user.profile.abilities; for (let attr in abilities) { if (abilities[attr]) lifeforms.push(_.capitalize(attr)); } return lifeforms; }, render() { let lifeforms = this.gathererLifeforms(); let availableLifeforms = this.availableLifeforms(); let icons = availableLifeforms.map(lifeform => { let containsAbility = lifeforms.some(gathererLifeform => { return gathererLifeform.toLowerCase() === lifeform.toLowerCase() }); if (containsAbility) { return } else { return } }); return {icons} } }); const GatherMenu = exports.GatherMenu = React.createClass({ propTypes: { gatherPool: React.PropTypes.object.isRequired, currentGather: React.PropTypes.string.isRequired, gatherSelectedCallback: React.PropTypes.func.isRequired }, onClick(gather) { return () => { this.props.gatherSelectedCallback(gather.type); } }, itemClass(gather) { let className = ["treeview"]; if (gather.type === this.props.currentGather) { className.push("active"); } return className.join(" "); }, gatherPoolArray() { const gatherArray = []; const gatherPool = this.props.gatherPool; for (let attr in gatherPool) { if (gatherPool.hasOwnProperty(attr)) { gatherArray.push(gatherPool[attr]); } } return gatherArray.sort((a, b) => a.name - b.name); }, render() { return ( ); } }); const GathererListItem = React.createClass({ propTypes: { user: React.PropTypes.object.isRequired, gather: React.PropTypes.object.isRequired, socket: React.PropTypes.object.isRequired, gatherer: React.PropTypes.object.isRequired, thisGatherer: React.PropTypes.object, soundController: React.PropTypes.object.isRequired }, bootGatherer(e) { e.preventDefault(); this.props.socket.emit("gather:leave", { type: this.props.gather.type, gatherer: parseInt(e.target.value, 10) || null }); }, getInitialState() { return { collapse: true }; }, toggleCollapse(e) { e.preventDefault(); this.setState({ collapse: !this.state.collapse }); }, caret() { if (this.state.collapse) { return ; } else { return ; } }, collapseState() { return `panel-collapse out collapse ${this.state.collapse ? "" : "in"}`; }, render() { const user = this.props.user; const gather = this.props.gather; const socket = this.props.socket; const gatherer = this.props.gatherer; const thisGatherer = this.props.thisGatherer; const soundController = this.props.soundController; let country; if (gatherer.user.country) { country = ( {gatherer.user.country} ); }; const skill = gatherer.user.profile.skill || "Not Available"; const hiveStats = []; if (gatherer.user.hive.skill) hiveStats.push(`${gatherer.user.hive.skill} ELO`); if (gatherer.user.hive.playTime) { hiveStats.push(`${Math.floor(gatherer.user.hive.playTime / 3600)} Hours`); } const hive = (hiveStats.length) ? hiveStats.join(", ") : "Not Available"; const team = (gatherer.user.team) ? gatherer.user.team.name : "None"; let action; if (gather.state === "election") { let votes = gather.gatherers.reduce((acc, voter) => { if (voter.leaderVote === gatherer.id) acc++; return acc; }, 0) action = ( {votes + " votes"} ); } if (gather.state === 'selection') { if (thisGatherer && thisGatherer.leader && thisGatherer.team === gather.pickingTurn) { action = ( ); } else { if (gatherer.leader) { action = (Leader); } else if (gatherer.team !== "lobby") { action = ({_.capitalize(gatherer.team)}); } else { action = ( Lobby); } } } let adminOptions; if ((user && user.admin) || (user && user.moderator)) { adminOptions = [
,
Admin
,
 
] } const lastSeenInMinutes = (gatherer) => { return parseInt((Date.now() - gatherer.user.lastSeen) / (1000 * 60)); }; let idleStatus; if (!gatherer.user.online) { const mins = lastSeenInMinutes(gatherer); idleStatus = [
Last Seen
,
{mins} mins ago
] } let tabColor = gatherer.team !== "lobby" ? `panel-${gatherer.team}` : "panel-info"; let onlineStatus = gatherer.user.online ? "" : "font-italic" return (

{country} {gatherer.user.username} Info {this.caret()} {action}

{idleStatus}
Skill Level
{skill}
Team
{team}
Hive Stats
{hive}
Links
ENSL Profile  Observatory Profile
{adminOptions}
); } }); const Gatherers = React.createClass({ propTypes: { user: React.PropTypes.object, thisGatherer: React.PropTypes.object, socket: React.PropTypes.object.isRequired, gather: React.PropTypes.object.isRequired, soundController: React.PropTypes.object.isRequired }, joinGather(e) { e.preventDefault(); this.props.socket.emit("gather:join", { type: this.props.gather.type }); }, render() { const self = this; const user = this.props.user; const socket = this.props.socket; const gather = this.props.gather; const thisGatherer = this.props.thisGatherer; const gatherers = gather.gatherers .sort((a, b) => { return (b.user.hive.skill || 1000) - (a.user.hive.skill || 1000); }) .map(gatherer => { return }); if (gather.gatherers.length) { return (
{gatherers}
); } else { return (
); } } }); const CompletedGather = exports.CompletedGather = React.createClass({ completionDate() { let d = new Date(this.props.gather.done.time); if (d) { return d.toLocaleString(); } else { return "Completed Gather" } }, getInitialState() { return { show: !!this.props.show }; }, toggleGatherInfo() { let newState = !this.state.show; this.setState({ show: newState }); }, render() { let gatherInfo = []; let gather = this.props.gather; let maps = this.props.maps; let gatherName = gather.name || "Classic Gather"; if (this.state.show) { gatherInfo.push(); gatherInfo.push(); } return (
{gatherName} - {this.completionDate()}
{gatherInfo}
); } }); const GatherVotingResults = React.createClass({ // Returns an array of ids voted for e.g. [1,2,5,1,1,3,2] countVotes(voteType) { return this.props.gather.gatherers.reduce((acc, gatherer) => { let votes = gatherer[voteType]; // Temporary fix because some mapvotes are ints and not arrays if (!Array.isArray(votes)) votes = [votes]; if (votes.length > 0) votes.forEach(vote => acc.push(vote)); return acc; }, []); }, selectedMaps() { return rankVotes(this.countVotes('mapVote'), this.props.maps).slice(0, 2) }, selectedServers() { return rankVotes(this.countVotes('serverVote'), this.props.gather.servers || []).slice(0, 2); }, serverTable(server, primary) { let password = server.password ? server.password : "N/A"; let className = primary ? "btn btn-primary max-width" : "btn btn-primary pull-right"; let label = primary ? `Join ${server.name}` : "Join Fallback" return (
Server Name
{server.name}
Address
{server.ip}:{server.port}
Password
{password}

{label}

); }, render() { let maps = this.selectedMaps(); let servers = this.selectedServers(); let mainServer; if (servers[0]) { mainServer = this.serverTable(servers[0], true); } let altServer; if (servers[1]) { altServer = this.serverTable(servers[1]); } return (
Game Information

Map Selection

Maps
{maps[0].name}
(Alternate: {maps[1].name})

Primary Server

{mainServer}

Fallback Server

{altServer}
); } });