Centurion together

master
Wilco Kruijer 5 years ago
parent 3f7987f482
commit c54f9b6273
  1. 2713
      backend/data/timeline.js
  2. 53
      backend/src/Lobby.js
  3. 15
      backend/src/app.js
  4. 25
      backend/src/index.js
  5. 6
      backend/src/state.js
  6. 39
      backend/src/timeline.js
  7. 15
      backend/test/a.js
  8. 7
      backend/test/b.js
  9. 12
      backend/test/state.js
  10. 16
      frontend/src/App.tsx
  11. 23
      frontend/src/components/Feed.tsx
  12. 6
      frontend/src/components/Lobby.tsx
  13. 38
      frontend/src/components/NextShot.tsx
  14. 20
      frontend/src/components/ShotsTaken.tsx
  15. 2
      frontend/src/css/lobby.css
  16. 17
      frontend/src/types/types.ts

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
const User = require("./User.js");
const timeline = require("./timeline.js");
module.exports = class Lobby {
/**
* @type {User[]}
@ -11,23 +11,58 @@ module.exports = class Lobby {
leaderId = undefined;
running = false;
runningInterval = undefined;
currentTime = 0;
startTime = 0;
currentSeconds = 0;
timelineIndex = 0;
// For debugging purposes
speedFactor = 1;
constructor(name) {
this.name = name;
}
run() {
run(ioLobby) {
this.running = true;
this.runningInterval = setInterval(() => {
this.currentTime += 1;
}, 1000);
this.startTime = Date.now();
const doTick = () => {
if (this.users.length === 0) {
// this lobby is over.
return;
}
pause() {
console.log(this.currentSeconds);
const timestamp = timeline.getIndex(this.timelineIndex);
const nextShot = timeline.getNextShot(this.timelineIndex);
if (!timestamp) {
// We are done.
console.log("Done");
this.running = false;
clearInterval(this.runningInterval);
return;
}
ioLobby.emit('tick_event', {
current: this.currentSeconds,
next: timestamp,
nextShot: nextShot
});
if (this.currentSeconds >= timestamp.timestamp) {
this.timelineIndex += 1;
}
this.currentSeconds += 1;
// We spend some time processing, wait a bit less than 1000ms
const nextTickTime = this.startTime + (1000 * this.currentSeconds / this.speedFactor);
const waitTime = nextTickTime - Date.now();
console.log("waiting", waitTime);
setTimeout(doTick, Math.floor(waitTime / this.speedFactor));
};
doTick();
}
/**

@ -0,0 +1,15 @@
const express = require("express");
const socketIO = require("socket.io");
const state = require("./state.js");
const PORT = 3001;
const app = express();
const server = app.listen(PORT, () => console.log(`Example app listening on port ${PORT}!`));
const io = socketIO(server);
app.get('/', (req, res) => res.send('<pre>' + JSON.stringify(state) + '</pre>'));
module.exports = {
app, server, io
};

@ -1,16 +1,7 @@
const express = require("express");
const socketIO = require("socket.io");
const service = require("./service.js");
const state = require("./state.js");
const PORT = 3001;
const app = express();
const server = app.listen(PORT, () => console.log(`Example app listening on port ${PORT}!`));
const io = socketIO(server);
app.get('/', (req, res) => res.send('<pre>' + JSON.stringify(state) + '</pre>'));
const { io } = require('./app.js');
io.on('connection', socket => {
const socketId = socket.id;
@ -67,5 +58,19 @@ io.on('connection', socket => {
status: 'ok',
lobby: lobby
});
});
socket.on('request_start', () => {
console.log('request start', socket.rooms);
const lobby = service.getUserLobby(socketId);
if (!lobby.isLeader(socketId)) {
console.warn("Non leader tried to start.");
return;
}
const ioLobby = io.to(lobby.name + "")
ioLobby.emit('started');
lobby.run(ioLobby);
})
});

@ -7,7 +7,6 @@ class State {
* @type {Object.<string, Lobby>}
*/
lobbies = {};
lobbyCount = 0;
constructor() {
}
@ -19,7 +18,8 @@ class State {
let lobby = undefined;
while (!lobby) {
const id = getRandomInt(100, Math.max(1000, this.lobbyCount * 2));
const lobbyCount = Object.keys(this.lobbies).length;
const id = getRandomInt(100, Math.max(1000, lobbyCount * 2));
lobby = this.createLobby(id);
}
@ -49,12 +49,10 @@ class State {
return undefined;
}
this.lobbyCount += 1;
return new Lobby(lobbyId);
}
removeLobby(lobbyId) {
this.lobbyCount -= 1;
delete this.lobbies[lobbyId];
}
}

@ -0,0 +1,39 @@
const timeline = require('../data/timeline.js');
/**
*
* @param i
* @returns {*}
*/
function getIndex(i) {
if (i >= timeline.length) {
return;
}
return timeline[i];
}
/**
* @param {number} i - the index.
* @returns {{count: number, timestamp: number}|undefined}
*/
function getNextShot(i) {
for (; i < timeline.length; i++) {
const time = getIndex(i);
for (let event of time.events) {
if (event.type === 'shot') {
return {
timestamp: time.timestamp,
count: event.shotCount
}
}
}
}
return undefined;
}
module.exports = {
getIndex, getNextShot
};

@ -1,15 +0,0 @@
const express = require('express');
const state = require('./state.js');
const b = require('./b.js');
const PORT = 3002;
const app = express();
const server = app.listen(PORT, () => console.log(`Example app listening on port ${PORT}!`));
app.get('/', (req, res) => {
let i = state.a;
b.test(i += 1);
return res.send('<pre>' + JSON.stringify(state) + '</pre>')
});

@ -1,7 +0,0 @@
const state = require('./state.js');
module.exports = {
test: (i) => {
state.setA(i);
}
};

@ -1,12 +0,0 @@
class State {
a = 3;
constructor() {
}
setA(i) {
this.a = i;
}
}
module.exports = new State();

@ -10,22 +10,20 @@ import Lobby from "./components/Lobby";
const App = () => {
const [connected, setConnected] = useState(false);
const [lobbyId, setLobbyId] = useState(null);
const [started, setStarted] = useState(false);
useEffect(() => {
socket.on('welcome', async (obj: any) => {
setLobbyId(obj.lobby.name);
setConnected(true);
socket.on('started', async () => {
setStarted(true);
console.log('ffin started')
});
return () => {
socket.off("SENDING_NEW_TIME");
socket.off("welcome");
socket.off("started");
}
});
const gameContent = (
const feedContent = (
<Row>
<NextShot/>
<Feed/>
@ -37,7 +35,7 @@ const App = () => {
<Lobby/>
);
const content = lobbyContent;
const content = started ? feedContent : lobbyContent;
return (
<>

@ -1,6 +1,7 @@
import React, {useEffect, useState} from 'react';
import {Col, Row} from "antd"
import socket from "../util/socket";
import {Tick} from "../types/types";
const Feed = () => {
@ -10,20 +11,20 @@ const Feed = () => {
}]);
useEffect(() => {
socket.on("SENDING_NEW_TIME", (data: string) => {
console.log(data);
setCount(c => c + 1);
const newItems = feedItems;
newItems.push({
title: "Ha1", body: "Doei", key: count
});
setFeedItems(newItems);
socket.on("tick_event", (tick: Tick) => {
// console.log("Shot:", tick.nextShot?.timestamp, tick.nextShot?.count)
// setCount(c => c + 1);
// const newItems = feedItems;
// newItems.push({
// title: "Ha1", body: "Doei", key: count
// });
//
// setFeedItems(newItems);
});
return () => {
socket.off("SENDING_NEW_TIME");
socket.off("tick_event");
}
});

@ -42,7 +42,7 @@ const Lobby = () => {
<div className="lobby">
<Row>
<Col span={24}>
<h1>Centurion! <img src={beer1} className="beer" alt="beer"/></h1>
<h1 id="centurion-title">Centurion! <img src={beer1} className="beer" alt="beer"/></h1>
</Col>
</Row>
<Row>
@ -55,7 +55,7 @@ const Lobby = () => {
<Row>
<Col className="control" span={8} offset={8}>
<Card title={`Lobby setup (${lobbyId}):`} actions={ isLeader ? [
<span>Start</span>,
<span onClick={async () => {await emit('request_start')}}>Start</span>,
]: []}>
<span>
Huidige lobby <InputNumber size="small" min={100} max={100000} value={lobbyId}
@ -63,7 +63,7 @@ const Lobby = () => {
</span>
<p>Er zijn {userCount} gebruiker(s) aanwezig.</p>
<p> {isLeader ? 'Jij bent de baas.' : 'Wachtend op de baas...'}</p>
<p> {isLeader ? 'Jij bent de baas.' : 'Wachten op de baas...'}</p>
</Card>
</Col>

@ -1,26 +1,52 @@
import React, {useEffect} from 'react';
import React, {useEffect, useRef, useState} from 'react';
import {Col, Progress} from "antd"
import socket from "../util/socket";
import {Tick} from "../types/types";
const NextShot = () => {
const [remaining, setRemaining] = useState(60);
const [remainingPercentage, setRemainingPercentage] = useState(100);
const fullTime = useRef(0);
useEffect(() => {
socket.on("SENDING_NEW_TIME", (data: string) => {
socket.on("tick_event", (tick: Tick) => {
if (!tick.nextShot) {
setRemaining(0);
return;
}
if (fullTime.current === 0) {
fullTime.current = tick.nextShot.timestamp - tick.current;
}
const shotEvent = tick.next.events.find(e => e.type === 'shot');
if (shotEvent && tick.current === tick.next.timestamp) {
fullTime.current = 0;
}
const timeRemaining = tick.nextShot.timestamp - tick.current;
setRemaining(timeRemaining);
// Fix divide by zero (.. || 1)
setRemainingPercentage(Math.ceil(timeRemaining / (fullTime.current || 1) * 100));
});
return () => {
socket.off("SENDING_NEW_TIME");
socket.off("tick_event");
}
});
}, []);
return (
<Col className="sider" span={4}>
<h1>Tijd tot volgende shot:</h1>
<Progress type="circle"
percent={75}
percent={remainingPercentage}
format={_ => remaining + ' sec.'}
strokeColor={"#304ba3"}
strokeWidth={10}/>
strokeWidth={10}
status="normal"/>
</Col>
);

@ -1,24 +1,34 @@
import React, {useEffect} from 'react';
import React, {useEffect, useRef, useState} from 'react';
import {Col, Progress} from "antd"
import socket from "../util/socket";
import {Tick} from "../types/types";
const ShotsTaken = () => {
const [remaining, setRemaining] = useState(100);
useEffect(() => {
socket.on("SENDING_NEW_TIME", (data: string) => {
socket.on("tick_event", (tick: Tick) => {
if (!tick.nextShot) {
setRemaining(0);
return;
}
setRemaining(tick.nextShot.count - 1);
});
return () => {
socket.off("SENDING_NEW_TIME");
socket.off("tick_event");
}
});
}, []);
return (
<Col className="sider" span={4}>
<h1>Shots genomen:</h1>
<Progress type="circle"
percent={25}
percent={100 - remaining}
format={_ => remaining + ' / 100'}
status="normal"
strokeColor={"#304ba3"}
strokeWidth={10}/>
</Col>

@ -1,4 +1,4 @@
h1 {
#centurion-title {
font-size: 3.5rem;
text-align: center;
min-height: inherit;

@ -0,0 +1,17 @@
export interface Tick {
current: number,
next: {
timestamp: number,
events: TimestampEvent[]
},
nextShot?: {
timestamp: number,
count: number
}
}
export interface TimestampEvent {
type: 'talk' | 'shot' | 'song' | 'time',
text: string[],
shotCount?: number
}
Loading…
Cancel
Save