Redesign and fix dupe events

This commit is contained in:
2023-06-18 01:49:43 +03:00
parent 28ab992aa1
commit fc6ae4e245
9 changed files with 106 additions and 70 deletions

View File

@@ -3,6 +3,7 @@ import session from 'express-session';
import mongodb from 'mongodb'; import mongodb from 'mongodb';
import MongoStore from 'connect-mongo'; import MongoStore from 'connect-mongo';
import cors from 'cors'; import cors from 'cors';
import crypto from 'crypto'
import { createNanoEvents } from 'nanoevents'; import { createNanoEvents } from 'nanoevents';
import "dotenv/config"; import "dotenv/config";
@@ -103,7 +104,6 @@ const client = new MongoClient(process.env.URI, { useUnifiedTopology: true });
} }
let players = {} let players = {}
let oldPlayers = {}
let score = {} let score = {}
let card = await drawCard() let card = await drawCard()
let oldCard = null; let oldCard = null;
@@ -257,6 +257,8 @@ const client = new MongoClient(process.env.URI, { useUnifiedTopology: true });
}); });
app.get('/api/stream', async (req, res) => { app.get('/api/stream', async (req, res) => {
const id = crypto.randomUUID()
res.set({ res.set({
'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Origin': '*',
'Cache-Control': 'no-cache', 'Cache-Control': 'no-cache',
@@ -278,6 +280,7 @@ const client = new MongoClient(process.env.URI, { useUnifiedTopology: true });
players, players,
selected selected
} }
res.write(`data: ${JSON.stringify(data)}\nevent: answer\n\n`); res.write(`data: ${JSON.stringify(data)}\nevent: answer\n\n`);
answers += 1 answers += 1
@@ -295,11 +298,12 @@ const client = new MongoClient(process.env.URI, { useUnifiedTopology: true });
answers = 0 answers = 0
oldCard = { ...card } oldCard = { ...card }
card = await drawCard() card = await drawCard()
emitter.emit('allDone');
emitter.emit(`allDone-${id}`);
} }
}); });
emitter.on('allDone', () => { const unbindAllDone = emitter.on(`allDone-${id}`, () => {
const data = { const data = {
correctAnswer: oldCard.name, correctAnswer: oldCard.name,
score score

View File

@@ -28,6 +28,7 @@
:root { :root {
--clr-bg: #ffd537; --clr-bg: #ffd537;
--clr-accent: #37ffac; --clr-accent: #37ffac;
--clr-text: #141414;
} }
body { body {
@@ -35,16 +36,17 @@ body {
background-color: var(--clr-bg); background-color: var(--clr-bg);
} }
input, button {
font: inherit;
}
#app { #app {
font-family: "Pangram Sans Rounded", Avenir, Helvetica, Arial, sans-serif; font-family: "Pangram Sans Rounded", Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
text-align: center; text-align: center;
color: black; color: var(--clr-text);
margin-top: 60px; min-height: 100vh;
} box-sizing: border-box;
#game {
margin-bottom: 100px;
} }
</style> </style>

View File

@@ -2,7 +2,7 @@
$resulting-shadow: null; $resulting-shadow: null;
@for $i from 1 through $distance { @for $i from 1 through $distance {
$resulting-shadow: $resulting-shadow, #{$i}px #{$i}px 0 black; $resulting-shadow: $resulting-shadow, #{$i}px #{$i}px 0 var(--clr-text);
} }
box-shadow: $resulting-shadow; box-shadow: $resulting-shadow;

View File

@@ -22,10 +22,10 @@ function endGame() {
<style scoped lang="scss"> <style scoped lang="scss">
.end { .end {
position: fixed; // position: fixed;
bottom: 8px; // bottom: 8px;
left: 50%; // left: 50%;
transform: translateX(-50%); // transform: translateX(-50%);
} }
.endButton { .endButton {
@@ -33,7 +33,7 @@ function endGame() {
border: none; border: none;
font: inherit; font: inherit;
padding: 8px 12px; padding: 8px 12px;
border-bottom: 1px dotted black; border-bottom: 1px dotted var(--clr-text);
&:hover { &:hover {
cursor: pointer; cursor: pointer;

View File

@@ -1,5 +1,5 @@
<template> <template>
<h1>Флекспатруль мультиплеер</h1> <h1 class="header">Флекспатруль мультиплеер</h1>
<div class="main"> <div class="main">
<div <div
@@ -12,16 +12,14 @@
> >
<h2>Кто скинул этот мем?</h2> <h2>Кто скинул этот мем?</h2>
<div class="interactive"> <div class="interactive">
<transition name="fade-answers"> <transition name="fade-answers" mode="out-in">
<List <List
v-if="!showResult" v-if="!showResult"
:options="options" :options="options"
@selectedAnswer="selectAnswer" @selectedAnswer="selectAnswer"
/> />
</transition>
<transition name="spin-result">
<Result <Result
v-if="showResult" v-else
:selectedName="selectedAnswer" :selectedName="selectedAnswer"
:correct="correctAnswer" :correct="correctAnswer"
/> />
@@ -97,19 +95,32 @@ onMounted(async () => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.header {
padding: 60px;
margin: auto;
height: 42px;
}
.main { .main {
padding-bottom: 200px; position: relative;
min-height: calc(100vh - 162px);
box-sizing: border-box;
padding: 8px;
display: flex;
flex-direction: column;
justify-content: space-between;
} }
.card { .card {
width: 450px; width: 450px;
margin: auto; margin: 0 auto;
min-height: 0;
} }
.meme { .meme {
width: 100%; width: 100%;
border-radius: 32px; border-radius: 32px;
border: 3px solid black; border: 3px solid var(--clr-text);
@include filled-shadow(16); @include filled-shadow(16);
transform: translateX(-8px); transform: translateX(-8px);
} }
@@ -120,11 +131,6 @@ onMounted(async () => {
.interactive { .interactive {
position: relative; position: relative;
> * {
position: absolute;
width: 100%;
}
} }
.fade-answers-leave-active { .fade-answers-leave-active {
@@ -135,14 +141,6 @@ onMounted(async () => {
transform: scale(0.3); transform: scale(0.3);
} }
.spin-result-enter-active {
transition: all 2s ease;
}
.spin-result-enter-from {
transform: scale(0.2);
transform: rotateY(120deg);
}
.loader { .loader {
margin-top: 100px; margin-top: 100px;
} }

View File

@@ -31,12 +31,12 @@ export default {
<style scoped> <style scoped>
.result { .result {
padding: 30px 40px; padding: 30px 40px;
border-radius: 8px; border-radius: 32px;
background-color: white; background-color: white;
} }
.correct { .correct {
color: black; color: var(--clr-text);
background-color: var(--clr-accent); background-color: var(--clr-accent);
} }

View File

@@ -1,6 +1,4 @@
<template> <template>
<h1>Флекспатруль мультиплеер</h1>
<div class="authCard"> <div class="authCard">
<h1>Авторизация:</h1> <h1>Авторизация:</h1>
@@ -9,21 +7,25 @@
<input <input
placeholder="Ответ" placeholder="Ответ"
v-model="answer" v-model="answer"
class="input"
> >
<input <input
v-if="mode === 'player'" v-if="mode === 'player'"
placeholder="Ваше имя" placeholder="Ваше имя"
v-model="username" v-model="username"
class="input"
> >
<button <button
v-if="mode === 'player'" v-if="mode === 'player'"
class="login"
@click="loginPlayer" @click="loginPlayer"
> >
Войти как игрок Войти как игрок
</button> </button>
<button <button
v-else v-else
class="login"
@click="loginScreen" @click="loginScreen"
> >
Войти как большой экран Войти как большой экран
@@ -31,7 +33,7 @@
<button <button
@click="switchMode" @click="switchMode"
class="secondary" class="switchMode"
> >
Я не {{ mode === 'player' ? 'игрок' : 'большой экран' }}! Я не {{ mode === 'player' ? 'игрок' : 'большой экран' }}!
</button> </button>
@@ -60,6 +62,10 @@ function switchMode() {
} }
async function loginPlayer() { async function loginPlayer() {
if (!answer.value || !username.value) {
return
}
store.username = username.value store.username = username.value
await axios await axios
@@ -83,7 +89,7 @@ async function loginScreen() {
} }
</script> </script>
<style scoped> <style scoped lang="scss">
.auth { .auth {
display: flex; display: flex;
gap: 16px; gap: 16px;
@@ -92,43 +98,68 @@ async function loginScreen() {
} }
.authCard { .authCard {
background-color: #121212; position: fixed;
color: white; top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: var(--clr-text);
color: var(--clr-text);
width: 400px; width: 400px;
margin: auto; margin: auto;
border-radius: 18px; border-radius: 32px;
padding: 40px 10px; padding: 40px 40px;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.6); box-sizing: border-box;
background: white;
border: 3px solid var(--clr-text);
@include filled-shadow(16);
} }
input { .input {
font-size: 1em; font-size: 16px;
text-align: center; padding: 16px;
padding: 5px 8px; border: 2px solid var(--clr-text);
border-radius: 6px; width: 100%;
border: none; box-sizing: border-box;
width: 20ch; @include filled-shadow(4);
border-radius: 12px;
&:focus {
outline: none;
}
} }
button { .login {
color: white; color: var(--clr-text);
font-size: 1em; font-size: 16px;
box-sizing: content-box; box-sizing: border-box;
background-color: #5a5a5a; background-color: var(--clr-bg);
border-radius: 6px;
border: none; border: none;
width: 20ch; width: 100%;
padding: 5px 8px; padding: 16px;
cursor: pointer; cursor: pointer;
border: 2px solid var(--clr-text);
@include filled-shadow(4);
border-radius: 12px;
} }
button.secondary { .switchMode {
background: #919191; position: absolute;
color: var(--clr-text);
background: var(--clr-accent);
font-size: 12px; font-size: 12px;
width: 70px;
height: 70px;
border-radius: 100px;
border: 2px solid var(--clr-text);
left: 0;
bottom: 0;
transform: translate(-50%, 50%);
cursor: pointer;
@include filled-shadow(4);
} }
@media only screen and (max-width: 520px) { @media only screen and (max-width: 520px) {
div { .authCard {
width: 100%; width: 100%;
padding: 40px 0; padding: 40px 0;
} }

View File

@@ -25,7 +25,7 @@ const position = reactive({
border-radius: 32px; border-radius: 32px;
font-size: 30px; font-size: 30px;
padding: 32px; padding: 32px;
border: 3px solid black; border: 3px solid var(--clr-text);
top: 50%; top: 50%;
left: 50%; left: 50%;
font-weight: 600; font-weight: 600;

View File

@@ -148,7 +148,7 @@ onMounted(() => {
padding: 64px; padding: 64px;
background: var(--clr-bg); background: var(--clr-bg);
box-sizing: border-box; box-sizing: border-box;
color: black; color: var(--clr-text);
} }
.image { .image {
@@ -158,7 +158,8 @@ onMounted(() => {
object-fit: contain; object-fit: contain;
margin-top: auto; margin-top: auto;
margin-bottom: auto; margin-bottom: auto;
border: 3px solid black; background: var(--clr-text);
border: 3px solid var(--clr-text);
@include filled-shadow(16); @include filled-shadow(16);
border-radius: 64px; border-radius: 64px;
animation-name: rock; animation-name: rock;
@@ -187,7 +188,7 @@ onMounted(() => {
} }
.users.-unanwsered { .users.-unanwsered {
border-right: 1px dashed black; border-right: 1px dashed var(--clr-text);
} }
.user.-correct { .user.-correct {