mirror of
https://github.com/anatolykopyl/vk-bingo.git
synced 2026-03-26 12:54:25 +00:00
Redesign and fix dupe events
This commit is contained in:
@@ -3,6 +3,7 @@ import session from 'express-session';
|
||||
import mongodb from 'mongodb';
|
||||
import MongoStore from 'connect-mongo';
|
||||
import cors from 'cors';
|
||||
import crypto from 'crypto'
|
||||
import { createNanoEvents } from 'nanoevents';
|
||||
|
||||
import "dotenv/config";
|
||||
@@ -103,7 +104,6 @@ const client = new MongoClient(process.env.URI, { useUnifiedTopology: true });
|
||||
}
|
||||
|
||||
let players = {}
|
||||
let oldPlayers = {}
|
||||
let score = {}
|
||||
let card = await drawCard()
|
||||
let oldCard = null;
|
||||
@@ -257,6 +257,8 @@ const client = new MongoClient(process.env.URI, { useUnifiedTopology: true });
|
||||
});
|
||||
|
||||
app.get('/api/stream', async (req, res) => {
|
||||
const id = crypto.randomUUID()
|
||||
|
||||
res.set({
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Cache-Control': 'no-cache',
|
||||
@@ -278,6 +280,7 @@ const client = new MongoClient(process.env.URI, { useUnifiedTopology: true });
|
||||
players,
|
||||
selected
|
||||
}
|
||||
|
||||
res.write(`data: ${JSON.stringify(data)}\nevent: answer\n\n`);
|
||||
|
||||
answers += 1
|
||||
@@ -295,11 +298,12 @@ const client = new MongoClient(process.env.URI, { useUnifiedTopology: true });
|
||||
answers = 0
|
||||
oldCard = { ...card }
|
||||
card = await drawCard()
|
||||
emitter.emit('allDone');
|
||||
|
||||
emitter.emit(`allDone-${id}`);
|
||||
}
|
||||
});
|
||||
|
||||
emitter.on('allDone', () => {
|
||||
const unbindAllDone = emitter.on(`allDone-${id}`, () => {
|
||||
const data = {
|
||||
correctAnswer: oldCard.name,
|
||||
score
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
:root {
|
||||
--clr-bg: #ffd537;
|
||||
--clr-accent: #37ffac;
|
||||
--clr-text: #141414;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -35,16 +36,17 @@ body {
|
||||
background-color: var(--clr-bg);
|
||||
}
|
||||
|
||||
input, button {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
#app {
|
||||
font-family: "Pangram Sans Rounded", Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: black;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
#game {
|
||||
margin-bottom: 100px;
|
||||
color: var(--clr-text);
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
$resulting-shadow: null;
|
||||
|
||||
@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;
|
||||
|
||||
@@ -22,10 +22,10 @@ function endGame() {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.end {
|
||||
position: fixed;
|
||||
bottom: 8px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
// position: fixed;
|
||||
// bottom: 8px;
|
||||
// left: 50%;
|
||||
// transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.endButton {
|
||||
@@ -33,7 +33,7 @@ function endGame() {
|
||||
border: none;
|
||||
font: inherit;
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px dotted black;
|
||||
border-bottom: 1px dotted var(--clr-text);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<h1>Флекспатруль мультиплеер</h1>
|
||||
<h1 class="header">Флекспатруль мультиплеер</h1>
|
||||
|
||||
<div class="main">
|
||||
<div
|
||||
@@ -12,16 +12,14 @@
|
||||
>
|
||||
<h2>Кто скинул этот мем?</h2>
|
||||
<div class="interactive">
|
||||
<transition name="fade-answers">
|
||||
<transition name="fade-answers" mode="out-in">
|
||||
<List
|
||||
v-if="!showResult"
|
||||
:options="options"
|
||||
@selectedAnswer="selectAnswer"
|
||||
/>
|
||||
</transition>
|
||||
<transition name="spin-result">
|
||||
<Result
|
||||
v-if="showResult"
|
||||
v-else
|
||||
:selectedName="selectedAnswer"
|
||||
:correct="correctAnswer"
|
||||
/>
|
||||
@@ -97,19 +95,32 @@ onMounted(async () => {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.header {
|
||||
padding: 60px;
|
||||
margin: auto;
|
||||
height: 42px;
|
||||
}
|
||||
|
||||
.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 {
|
||||
width: 450px;
|
||||
margin: auto;
|
||||
margin: 0 auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.meme {
|
||||
width: 100%;
|
||||
border-radius: 32px;
|
||||
border: 3px solid black;
|
||||
border: 3px solid var(--clr-text);
|
||||
@include filled-shadow(16);
|
||||
transform: translateX(-8px);
|
||||
}
|
||||
@@ -120,11 +131,6 @@ onMounted(async () => {
|
||||
|
||||
.interactive {
|
||||
position: relative;
|
||||
|
||||
> * {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.fade-answers-leave-active {
|
||||
@@ -135,14 +141,6 @@ onMounted(async () => {
|
||||
transform: scale(0.3);
|
||||
}
|
||||
|
||||
.spin-result-enter-active {
|
||||
transition: all 2s ease;
|
||||
}
|
||||
.spin-result-enter-from {
|
||||
transform: scale(0.2);
|
||||
transform: rotateY(120deg);
|
||||
}
|
||||
|
||||
.loader {
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
@@ -31,12 +31,12 @@ export default {
|
||||
<style scoped>
|
||||
.result {
|
||||
padding: 30px 40px;
|
||||
border-radius: 8px;
|
||||
border-radius: 32px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.correct {
|
||||
color: black;
|
||||
color: var(--clr-text);
|
||||
background-color: var(--clr-accent);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<template>
|
||||
<h1>Флекспатруль мультиплеер</h1>
|
||||
|
||||
<div class="authCard">
|
||||
<h1>Авторизация:</h1>
|
||||
|
||||
@@ -9,21 +7,25 @@
|
||||
<input
|
||||
placeholder="Ответ"
|
||||
v-model="answer"
|
||||
class="input"
|
||||
>
|
||||
<input
|
||||
v-if="mode === 'player'"
|
||||
placeholder="Ваше имя"
|
||||
v-model="username"
|
||||
class="input"
|
||||
>
|
||||
|
||||
<button
|
||||
v-if="mode === 'player'"
|
||||
class="login"
|
||||
@click="loginPlayer"
|
||||
>
|
||||
Войти как игрок
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
class="login"
|
||||
@click="loginScreen"
|
||||
>
|
||||
Войти как большой экран
|
||||
@@ -31,7 +33,7 @@
|
||||
|
||||
<button
|
||||
@click="switchMode"
|
||||
class="secondary"
|
||||
class="switchMode"
|
||||
>
|
||||
Я не {{ mode === 'player' ? 'игрок' : 'большой экран' }}!
|
||||
</button>
|
||||
@@ -60,6 +62,10 @@ function switchMode() {
|
||||
}
|
||||
|
||||
async function loginPlayer() {
|
||||
if (!answer.value || !username.value) {
|
||||
return
|
||||
}
|
||||
|
||||
store.username = username.value
|
||||
|
||||
await axios
|
||||
@@ -83,7 +89,7 @@ async function loginScreen() {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style scoped lang="scss">
|
||||
.auth {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
@@ -92,43 +98,68 @@ async function loginScreen() {
|
||||
}
|
||||
|
||||
.authCard {
|
||||
background-color: #121212;
|
||||
color: white;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: var(--clr-text);
|
||||
color: var(--clr-text);
|
||||
width: 400px;
|
||||
margin: auto;
|
||||
border-radius: 18px;
|
||||
padding: 40px 10px;
|
||||
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.6);
|
||||
border-radius: 32px;
|
||||
padding: 40px 40px;
|
||||
box-sizing: border-box;
|
||||
background: white;
|
||||
border: 3px solid var(--clr-text);
|
||||
@include filled-shadow(16);
|
||||
}
|
||||
|
||||
input {
|
||||
font-size: 1em;
|
||||
text-align: center;
|
||||
padding: 5px 8px;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
width: 20ch;
|
||||
.input {
|
||||
font-size: 16px;
|
||||
padding: 16px;
|
||||
border: 2px solid var(--clr-text);
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
@include filled-shadow(4);
|
||||
border-radius: 12px;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
color: white;
|
||||
font-size: 1em;
|
||||
box-sizing: content-box;
|
||||
background-color: #5a5a5a;
|
||||
border-radius: 6px;
|
||||
.login {
|
||||
color: var(--clr-text);
|
||||
font-size: 16px;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--clr-bg);
|
||||
border: none;
|
||||
width: 20ch;
|
||||
padding: 5px 8px;
|
||||
width: 100%;
|
||||
padding: 16px;
|
||||
cursor: pointer;
|
||||
border: 2px solid var(--clr-text);
|
||||
@include filled-shadow(4);
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
button.secondary {
|
||||
background: #919191;
|
||||
.switchMode {
|
||||
position: absolute;
|
||||
color: var(--clr-text);
|
||||
background: var(--clr-accent);
|
||||
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) {
|
||||
div {
|
||||
.authCard {
|
||||
width: 100%;
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ const position = reactive({
|
||||
border-radius: 32px;
|
||||
font-size: 30px;
|
||||
padding: 32px;
|
||||
border: 3px solid black;
|
||||
border: 3px solid var(--clr-text);
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -148,7 +148,7 @@ onMounted(() => {
|
||||
padding: 64px;
|
||||
background: var(--clr-bg);
|
||||
box-sizing: border-box;
|
||||
color: black;
|
||||
color: var(--clr-text);
|
||||
}
|
||||
|
||||
.image {
|
||||
@@ -158,7 +158,8 @@ onMounted(() => {
|
||||
object-fit: contain;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
border: 3px solid black;
|
||||
background: var(--clr-text);
|
||||
border: 3px solid var(--clr-text);
|
||||
@include filled-shadow(16);
|
||||
border-radius: 64px;
|
||||
animation-name: rock;
|
||||
@@ -187,7 +188,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.users.-unanwsered {
|
||||
border-right: 1px dashed black;
|
||||
border-right: 1px dashed var(--clr-text);
|
||||
}
|
||||
|
||||
.user.-correct {
|
||||
|
||||
Reference in New Issue
Block a user