Lustige Raumnamen: Generator, Lobby-Anzeige + Würfel-Button
Build & Deploy / deploy (push) Successful in 19s
Build & Deploy / deploy (push) Successful in 19s
- Server: 3 Name-Muster (Adj+Tiere, Wort-Event, Action-im-Ort), rename-Endpunkt (Host, Lobby) - Lobby: Raumname ueber Code, Host kann wuerfeln, Share-Text mit Name
This commit is contained in:
@@ -24,6 +24,7 @@ export interface Ergebnis {
|
|||||||
|
|
||||||
export interface RaumZustand {
|
export interface RaumZustand {
|
||||||
code: string
|
code: string
|
||||||
|
raumname: string
|
||||||
status: RaumStatus
|
status: RaumStatus
|
||||||
runde: number
|
runde: number
|
||||||
anzahlRunden: number
|
anzahlRunden: number
|
||||||
@@ -110,6 +111,7 @@ export async function raumBeitreten(code: string, name: string): Promise<{ sessi
|
|||||||
export const zustandLaden = (s: RaumSession) => anfrage('GET', `/${s.code}`, undefined, s.token)
|
export const zustandLaden = (s: RaumSession) => anfrage('GET', `/${s.code}`, undefined, s.token)
|
||||||
export const readySetzen = (s: RaumSession, ready: boolean) => anfrage('POST', `/${s.code}/ready`, { ready }, s.token)
|
export const readySetzen = (s: RaumSession, ready: boolean) => anfrage('POST', `/${s.code}/ready`, { ready }, s.token)
|
||||||
export const redModeSetzen = (s: RaumSession, redMode: boolean) => anfrage('POST', `/${s.code}/redmode`, { redMode }, s.token)
|
export const redModeSetzen = (s: RaumSession, redMode: boolean) => anfrage('POST', `/${s.code}/redmode`, { redMode }, s.token)
|
||||||
|
export const raumUmbenennen = (s: RaumSession) => anfrage('POST', `/${s.code}/rename`, {}, s.token)
|
||||||
export const frageStellen = (s: RaumSession, frage: string) => anfrage('POST', `/${s.code}/question`, { frage }, s.token)
|
export const frageStellen = (s: RaumSession, frage: string) => anfrage('POST', `/${s.code}/question`, { frage }, s.token)
|
||||||
export const rankingAbgeben = (s: RaumSession, reihenfolge: string[]) =>
|
export const rankingAbgeben = (s: RaumSession, reihenfolge: string[]) =>
|
||||||
anfrage('POST', `/${s.code}/ranking`, { reihenfolge }, s.token)
|
anfrage('POST', `/${s.code}/ranking`, { reihenfolge }, s.token)
|
||||||
|
|||||||
+17
-2
@@ -3,6 +3,7 @@ import {
|
|||||||
Check,
|
Check,
|
||||||
Copy,
|
Copy,
|
||||||
Crown,
|
Crown,
|
||||||
|
Dice5,
|
||||||
DoorOpen,
|
DoorOpen,
|
||||||
Eraser,
|
Eraser,
|
||||||
EyeOff,
|
EyeOff,
|
||||||
@@ -24,6 +25,7 @@ import {
|
|||||||
zustandLaden,
|
zustandLaden,
|
||||||
readySetzen,
|
readySetzen,
|
||||||
redModeSetzen,
|
redModeSetzen,
|
||||||
|
raumUmbenennen,
|
||||||
frageStellen,
|
frageStellen,
|
||||||
rankingAbgeben,
|
rankingAbgeben,
|
||||||
naechstePhase,
|
naechstePhase,
|
||||||
@@ -265,7 +267,7 @@ function Lobby({
|
|||||||
const teilen = async () => {
|
const teilen = async () => {
|
||||||
if (navigator.share) {
|
if (navigator.share) {
|
||||||
try {
|
try {
|
||||||
await navigator.share({ title: '1 bis 8 Party', text: `Tritt meinem Spielraum ${z.code} bei!`, url: beitrittsUrl })
|
await navigator.share({ title: '1 bis 8 Party', text: `Tritt „${z.raumname}“ bei! Spielraum-Code: ${z.code}`, url: beitrittsUrl })
|
||||||
return
|
return
|
||||||
} catch {
|
} catch {
|
||||||
/* User abgebrochen -> Copy Fallback */
|
/* User abgebrochen -> Copy Fallback */
|
||||||
@@ -294,7 +296,20 @@ function Lobby({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="glass-card p-5 text-center">
|
<div className="glass-card p-5 text-center">
|
||||||
<p className="text-xs font-extrabold uppercase tracking-[0.25em] text-violet-300">Spielraum-Code</p>
|
<p className="text-xs font-extrabold uppercase tracking-[0.25em] text-violet-300">Spielraum</p>
|
||||||
|
<div className="mt-1 flex items-center justify-center gap-2">
|
||||||
|
<p className="font-display text-2xl font-bold text-white">{z.raumname}</p>
|
||||||
|
{ich?.istHost && (
|
||||||
|
<button
|
||||||
|
onClick={() => onAct((s) => raumUmbenennen(s))}
|
||||||
|
title="Namen neu würfeln"
|
||||||
|
className="rounded-full border border-white/15 bg-white/[0.06] p-1.5 text-white/60 transition-all hover:bg-white/10 hover:text-white active:scale-90"
|
||||||
|
>
|
||||||
|
<Dice5 size={16} />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<p className="mt-3 text-xs font-extrabold uppercase tracking-[0.25em] text-violet-300">Code</p>
|
||||||
<p className="mt-1 font-display text-5xl font-bold tracking-[0.25em] text-gradient">{z.code}</p>
|
<p className="mt-1 font-display text-5xl font-bold tracking-[0.25em] text-gradient">{z.code}</p>
|
||||||
<p className="mt-2 text-sm text-white/55">
|
<p className="mt-2 text-sm text-white/55">
|
||||||
Alle öffnen <span className="font-bold text-white/80">1bis.hocks.eu</span> auf dem Handy und
|
Alle öffnen <span className="font-bold text-white/80">1bis.hocks.eu</span> auf dem Handy und
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
* POST /api/game/room/:code/question -> Fragesteller stellt die Frage
|
* POST /api/game/room/:code/question -> Fragesteller stellt die Frage
|
||||||
* POST /api/game/room/:code/ranking -> eigenes geheimes Ranking abgeben
|
* POST /api/game/room/:code/ranking -> eigenes geheimes Ranking abgeben
|
||||||
* POST /api/game/room/:code/next -> Auflösung -> Punktestand -> neue Runde
|
* POST /api/game/room/:code/next -> Auflösung -> Punktestand -> neue Runde
|
||||||
|
* POST /api/game/room/:code/redmode -> Red Mode an/aus (Host, nur Lobby)
|
||||||
|
* POST /api/game/room/:code/rename -> Raumnamen neu würfeln (Host, nur Lobby)
|
||||||
*
|
*
|
||||||
* Auth: X-Player-Token-Header (oder Body-Feld "token"), pro Spieler ein Token.
|
* Auth: X-Player-Token-Header (oder Body-Feld "token"), pro Spieler ein Token.
|
||||||
* Start: Sobald ALLE Spieler ready sind (min. 3), wechselt der Raum automatisch
|
* Start: Sobald ALLE Spieler ready sind (min. 3), wechselt der Raum automatisch
|
||||||
@@ -116,6 +118,49 @@ function neuerCode() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Lustige Raumnamen ──────────────────────────────────── */
|
||||||
|
const NAMEN = {
|
||||||
|
adj: [
|
||||||
|
'durstigen', 'tanzenden', 'kichernden', 'brüllenden', 'flüsternden', 'glühenden',
|
||||||
|
'schunkelnden', 'zappelnden', 'grölenden', 'funkelnden', 'randalierenden', 'frechen',
|
||||||
|
'mutigen', 'verpeilten', 'torkelnden', 'jauchzenden', 'grinsenden', 'schwatzenden',
|
||||||
|
'pfeifenden', 'trommelnden', 'hopsenden', 'sabbernden', 'schleimigen', 'schillernden',
|
||||||
|
'tollpatschigen', 'unersättlichen', 'übermütigen', 'schäumenden', 'quietschenden',
|
||||||
|
'polternden', 'strahlenden', 'müden',
|
||||||
|
],
|
||||||
|
tier: [
|
||||||
|
'Piraten', 'Kartoffeln', 'Nachteulen', 'Chamäleons', 'Pinguine', 'Flamingos',
|
||||||
|
'Rentiere', 'Einhörner', 'Gurken', 'Muffins', 'Kekse', 'Bananen', 'Tomaten',
|
||||||
|
'Schildkröten', 'Waschbären', 'Faultiere', 'Kängurus', 'Seehunde', 'Wombats',
|
||||||
|
'Lemminge', 'Spechte', 'Otter', 'Marder', 'Igel', 'Kamele', 'Lamas', 'Alpakas',
|
||||||
|
'Zebras', 'Quokkas', 'Tukane', 'Kronkorken', 'Glühbirnen', 'Staubsauger', 'Kaugummis',
|
||||||
|
'Regenwürmer', 'Luftballons', 'Wackelpuddinge', 'Nudeln', 'Schokolinsen', 'Popcorntüten',
|
||||||
|
],
|
||||||
|
sing: [
|
||||||
|
'Pinguin', 'Kartoffel', 'Muffin', 'Einhorn', 'Otter', 'Faultier', 'Kamel', 'Lama',
|
||||||
|
'Wackelpudding', 'Kronkorken', 'Kaugummi', 'Regenwurm', 'Igel', 'Quokka', 'Flamingo',
|
||||||
|
'Waschbär', 'Specht', 'Tomate', 'Banane', 'Keks',
|
||||||
|
],
|
||||||
|
event: ['Alarm', 'Manie', 'Panik', 'Invasion', 'Verschwörung', 'Olympiade', 'Revolution', 'Notstand', 'Expedition', 'Befreiung'],
|
||||||
|
action: ['Party', 'Chaos', 'Krawall', 'Sause', 'Rambazamba', 'Zoff'],
|
||||||
|
ort: ['Keller', 'Garten', 'Palast', 'U-Boot', 'Zirkus', 'All', 'Baumhaus', 'Schloss', 'Dschungel', 'Wolkenkuckucksheim', 'Kiosk', 'Weltraum'],
|
||||||
|
};
|
||||||
|
|
||||||
|
const pick = (liste) => liste[crypto.randomInt(liste.length)];
|
||||||
|
|
||||||
|
function lustigerRaumname() {
|
||||||
|
for (let versuch = 0; versuch < 25; versuch++) {
|
||||||
|
const typ = crypto.randomInt(3);
|
||||||
|
let name;
|
||||||
|
if (typ === 0) name = `Die ${pick(NAMEN.adj)} ${pick(NAMEN.tier)}`;
|
||||||
|
else if (typ === 1) name = `${pick(NAMEN.sing)}-${pick(NAMEN.event)}`;
|
||||||
|
else name = `${pick(NAMEN.action)} im ${pick(NAMEN.ort)}`;
|
||||||
|
const vergeben = Object.values(rooms).some((r) => r.raumname === name);
|
||||||
|
if (!vergeben) return name;
|
||||||
|
}
|
||||||
|
return `Die ${pick(NAMEN.adj)} ${pick(NAMEN.tier)} ${crypto.randomInt(100)}`;
|
||||||
|
}
|
||||||
|
|
||||||
function raumFinden(code) {
|
function raumFinden(code) {
|
||||||
const raum = rooms[(code || '').toUpperCase()];
|
const raum = rooms[(code || '').toUpperCase()];
|
||||||
if (!raum) return null;
|
if (!raum) return null;
|
||||||
@@ -141,6 +186,7 @@ function oeffentlicherZustand(raum, token) {
|
|||||||
const alleReady = raum.spieler.length >= MIN_SPIELER && raum.spieler.every((s) => s.ready);
|
const alleReady = raum.spieler.length >= MIN_SPIELER && raum.spieler.every((s) => s.ready);
|
||||||
return {
|
return {
|
||||||
code: raum.code,
|
code: raum.code,
|
||||||
|
raumname: raum.raumname || '',
|
||||||
status: raum.status,
|
status: raum.status,
|
||||||
runde: raum.runde,
|
runde: raum.runde,
|
||||||
anzahlRunden: raum.spieler.length,
|
anzahlRunden: raum.spieler.length,
|
||||||
@@ -207,6 +253,7 @@ const server = http.createServer(async (req, res) => {
|
|||||||
if (!neuerRaumCode) return fehler(res, 500, 'kein Raumcode frei');
|
if (!neuerRaumCode) return fehler(res, 500, 'kein Raumcode frei');
|
||||||
const raum = {
|
const raum = {
|
||||||
code: neuerRaumCode,
|
code: neuerRaumCode,
|
||||||
|
raumname: lustigerRaumname(),
|
||||||
erstelltAm: Date.now(),
|
erstelltAm: Date.now(),
|
||||||
aktivitaet: Date.now(),
|
aktivitaet: Date.now(),
|
||||||
status: 'lobby',
|
status: 'lobby',
|
||||||
@@ -271,6 +318,15 @@ const server = http.createServer(async (req, res) => {
|
|||||||
return antwort(res, 200, { ok: true, zustand: oeffentlicherZustand(raum, token) });
|
return antwort(res, 200, { ok: true, zustand: oeffentlicherZustand(raum, token) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Raumnamen neu wuerfeln (nur Host, nur vor Spielstart) */
|
||||||
|
if (req.method === 'POST' && aktion === 'rename') {
|
||||||
|
if (raum.status !== 'lobby') return fehler(res, 409, 'Der Raumname ist nur vor Spielstart aenderbar');
|
||||||
|
if (!spieler.istHost) return fehler(res, 403, 'Nur der Host kann den Raumnamen aendern');
|
||||||
|
raum.raumname = lustigerRaumname();
|
||||||
|
speichern();
|
||||||
|
return antwort(res, 200, { ok: true, zustand: oeffentlicherZustand(raum, token) });
|
||||||
|
}
|
||||||
|
|
||||||
/* Frage stellen */
|
/* Frage stellen */
|
||||||
if (req.method === 'POST' && aktion === 'question') {
|
if (req.method === 'POST' && aktion === 'question') {
|
||||||
if (raum.status !== 'question') return fehler(res, 409, 'Keine Fragephase');
|
if (raum.status !== 'question') return fehler(res, 409, 'Keine Fragephase');
|
||||||
|
|||||||
Reference in New Issue
Block a user