import React from "react"; import * as I from "csgogsi-socket"; import "./matchbar.scss"; import TeamScore from "./TeamScore"; import Bomb from "./../Timers/BombTimer"; import Countdown from "./../Timers/Countdown"; import { GSI } from "../../App"; import { Match } from "../../api/interfaces"; function stringToClock(time: string | number, pad = true) { if (typeof time === "string") { time = parseFloat(time); } const countdown = Math.abs(Math.ceil(time)); const minutes = Math.floor(countdown / 60); const seconds = countdown - minutes * 60; if (pad && seconds < 10) { return `${minutes}:0${seconds}`; } return `${minutes}:${seconds}`; } interface IProps { match: Match | null; map: I.Map; phase: I.PhaseRaw, bomb: I.Bomb | null, } export interface Timer { width: number; active: boolean; countdown: number; side: "left"|"right"; type: "defusing" | "planting"; player: I.Player | null; } interface IState { defusing: Timer, planting: Timer, winState: { side: "left"|"right", show: boolean } } export default class TeamBox extends React.Component { constructor(props: IProps){ super(props); this.state = { defusing: { width: 0, active: false, countdown: 10, side: "left", type: "defusing", player: null }, planting: { width: 0, active: false, countdown: 10, // Fake side: "right", type: "planting", player: null }, winState: { side: 'left', show: false } } } plantStop = () => this.setState(state => { state.planting.active = false; return state; }); setWidth = (type: 'defusing' | 'planting', width: number) => { this.setState(state => { state[type].width = width; return state; }) } initPlantTimer = () => { const bomb = new Countdown(time => { let width = time * 100; this.setWidth("planting", width/3); }); GSI.on("bombPlantStart", player => { if(!player || !player.team) return; this.setState(state => { state.planting.active = true; state.planting.side = player.team.orientation; state.planting.player = player; }) }) GSI.on("data", data => { if(!data.bomb || !data.bomb.countdown || data.bomb.state !== "planting") return this.plantStop(); this.setState(state => { state.planting.active = true; }) return bomb.go(data.bomb.countdown); }); } defuseStop = () => this.setState(state => { state.defusing.active = false; state.defusing.countdown = 10; return state; }); initDefuseTimer = () => { const bomb = new Countdown(time => { let width = time > this.state.defusing.countdown ? this.state.defusing.countdown*100 : time * 100; this.setWidth("defusing", width/this.state.defusing.countdown); }); GSI.on("defuseStart", player => { if(!player || !player.team) return; this.setState(state => { state.defusing.active = true; state.defusing.countdown = !Boolean(player.state.defusekit) ? 10 : 5; state.defusing.side = player.team.orientation; state.defusing.player = player; return state; }) }) GSI.on("data", data => { if(!data.bomb || !data.bomb.countdown || data.bomb.state !== "defusing") return this.defuseStop(); this.setState(state => { state.defusing.active = true; return state; }) return bomb.go(data.bomb.countdown); }); } resetWin = () => { setTimeout(() => { this.setState(state => { state.winState.show = false; return state; }) }, 6000); } componentDidMount(){ this.initDefuseTimer(); this.initPlantTimer(); GSI.on("roundEnd", score => { this.setState(state => { state.winState.show = true; state.winState.side = score.winner.orientation; return state; }, this.resetWin); }); } getRoundLabel = () => { const { map } = this.props; const round = map.round + 1; if (round <= 24) { return `Round ${round}/24`; } const additionalRounds = round - 24; const OT = Math.ceil(additionalRounds/6); return `OT ${OT} (${additionalRounds - (OT - 1)*6}/6)`; } render() { const { defusing, planting, winState } = this.state; const { bomb, match, map, phase } = this.props; const time = stringToClock(phase.phase_ends_in); const left = map.team_ct.orientation === "left" ? map.team_ct : map.team_t; const right = map.team_ct.orientation === "left" ? map.team_t : map.team_ct; const isPlanted = bomb && (bomb.state === "defusing" || bomb.state === "planted"); const bo = (match && Number(match.matchType.substr(-1))) || 0; let leftTimer: Timer | null = null, rightTimer: Timer | null = null; if(defusing.active || planting.active){ if(defusing.active){ if(defusing.side === "left") leftTimer = defusing; else rightTimer = defusing; } else { if(planting.side === "left") leftTimer = planting; else rightTimer = planting; } } return ( <>
{left.score}
{time}
{this.getRoundLabel()}
{right.score}
); } }