otpion "sans remise"

This commit is contained in:
Didictateur 2025-11-24 14:46:25 +01:00
parent b35694c730
commit c00a3ce3b1
2 changed files with 52 additions and 4 deletions

View file

@ -28,6 +28,13 @@
</label> </label>
</div> </div>
<div style="margin-top:8px">
<label id="no-remise" style="display:none;align-items:center;gap:8px;">
<input type="checkbox" id="no-remiseToggle" />
Sans remise
</label>
</div>
<div style="margin-top:8px"> <div style="margin-top:8px">
<button id="startBtn" style="display:none" class="btn-cta">Commencer la partie</button> <button id="startBtn" style="display:none" class="btn-cta">Commencer la partie</button>
<button id="copyInviteBtn" style="margin-left:8px" class="btn-ghost">Copier le lien d'invitation</button> <button id="copyInviteBtn" style="margin-left:8px" class="btn-ghost">Copier le lien d'invitation</button>
@ -54,6 +61,8 @@
const youAreHostEl = document.getElementById('youAreHost'); const youAreHostEl = document.getElementById('youAreHost');
const autoDrawLabelEl = document.getElementById('autoDrawLabel'); const autoDrawLabelEl = document.getElementById('autoDrawLabel');
const autoDrawToggleEl = document.getElementById('autoDrawToggle'); const autoDrawToggleEl = document.getElementById('autoDrawToggle');
const noRemiseLabelEl = document.getElementById('no-remise');
const noRemiseToggleEl = document.getElementById('no-remiseToggle');
function log(...args){ console.log(...args); } function log(...args){ console.log(...args); }
@ -114,6 +123,20 @@
} }
} }
}catch(_){ } }catch(_){ }
// update no-remise UI if server provides it
try{
if(typeof data.noRemise !== 'undefined' && noRemiseLabelEl && noRemiseToggleEl){
// show the control only to the host
if(myPlayerId && roomHostId && myPlayerId === roomHostId){
noRemiseLabelEl.style.display = 'inline-flex';
noRemiseToggleEl.checked = !!data.noRemise;
noRemiseToggleEl.disabled = false;
} else {
// hide control for non-hosts
noRemiseLabelEl.style.display = 'none';
}
}
}catch(_){ }
}); });
// register game started handler early so we don't miss the broadcast // register game started handler early so we don't miss the broadcast
@ -162,6 +185,16 @@
if(autoDrawLabelEl) autoDrawLabelEl.style.display = 'none'; if(autoDrawLabelEl) autoDrawLabelEl.style.display = 'none';
} }
} }
// set no-remise independently so host sees it even if autoDraw is undefined
try{
if(roomInfo && typeof roomInfo.noRemise !== 'undefined'){
if(myPlayerId && roomHostId && myPlayerId === roomHostId){
if(noRemiseLabelEl && noRemiseToggleEl){ noRemiseLabelEl.style.display = 'inline-flex'; noRemiseToggleEl.checked = !!roomInfo.noRemise; noRemiseToggleEl.disabled = false; }
} else {
if(noRemiseLabelEl) noRemiseLabelEl.style.display = 'none';
}
}
}catch(_){ }
}catch(_){ } }catch(_){ }
if(roomInfo && roomInfo.status === 'playing'){ if(roomInfo && roomInfo.status === 'playing'){
// server already marked room as playing; redirect immediately // server already marked room as playing; redirect immediately

View file

@ -38,6 +38,7 @@ function sendRoomUpdate(room){
size: (room.boardState && room.boardState.width) || room.size, size: (room.boardState && room.boardState.width) || room.size,
cards: Object.keys(room.cards || {}), cards: Object.keys(room.cards || {}),
autoDraw: !!room.autoDraw, autoDraw: !!room.autoDraw,
noRemise: !!room.noRemise,
deckCount: (room.deck && room.deck.length) || 0, deckCount: (room.deck && room.deck.length) || 0,
discardCount: (room.discard && room.discard.length) || 0 discardCount: (room.discard && room.discard.length) || 0
}; };
@ -296,8 +297,8 @@ function drawCardForPlayer(room, playerId){
} }
if(hand.length >= 5) return null; // hand full if(hand.length >= 5) return null; // hand full
if(room.deck.length === 0){ if(room.deck.length === 0){
// if deck empty, try to refill from discard and shuffle // if deck empty, try to refill from discard and shuffle — unless 'noRemise' is enabled
if(room.discard && room.discard.length > 0){ if(!room.noRemise && room.discard && room.discard.length > 0){
// move all discard into deck // move all discard into deck
room.deck = room.discard.splice(0).concat(room.deck || []); room.deck = room.discard.splice(0).concat(room.deck || []);
// simple Fisher-Yates shuffle // simple Fisher-Yates shuffle
@ -717,7 +718,7 @@ app.post('/rooms', (req, res) => {
// hostId will be set when the first player joins // hostId will be set when the first player joins
// initialize a deck for this room // initialize a deck for this room
const deck = buildDefaultDeck(); const deck = buildDefaultDeck();
rooms.set(id, { id, boardState, players: [], status: 'waiting', hostId: null, size, cards: {}, playedCards: [], removalTimers: new Map(), deck, hands: {}, autoDraw: false }); rooms.set(id, { id, boardState, players: [], status: 'waiting', hostId: null, size, cards: {}, playedCards: [], removalTimers: new Map(), deck, hands: {}, autoDraw: false, noRemise: false });
res.json({ roomId: id, size }); res.json({ roomId: id, size });
}); });
@ -726,7 +727,7 @@ app.get('/rooms/:id', (req, res) => {
if (!room) return res.status(404).json({ error: 'room not found' }); if (!room) return res.status(404).json({ error: 'room not found' });
const boardState = room.boardState || null; const boardState = room.boardState || null;
const size = (room.boardState && room.boardState.width) || room.size; const size = (room.boardState && room.boardState.width) || room.size;
res.json({ id: room.id, boardState, size: size, players: room.players.map(p => ({ id: p.id, color: p.color })), status: room.status, hostId: room.hostId, cards: Object.keys(room.cards || {}), autoDraw: !!room.autoDraw }); res.json({ id: room.id, boardState, size: size, players: room.players.map(p => ({ id: p.id, color: p.color })), status: room.status, hostId: room.hostId, cards: Object.keys(room.cards || {}), autoDraw: !!room.autoDraw, noRemise: !!room.noRemise });
}); });
io.on('connection', (socket) => { io.on('connection', (socket) => {
@ -824,6 +825,20 @@ io.on('connection', (socket) => {
return cb && cb({ ok: true, autoDraw: room.autoDraw }); return cb && cb({ ok: true, autoDraw: room.autoDraw });
}); });
// Host can toggle the 'no remise' flag (prevent reshuffling discard into deck). Only the host may change this setting.
socket.on('room:no_remise:set', ({ roomId, enabled }, cb) => {
const room = rooms.get(roomId);
if(!room) return cb && cb({ error: 'room not found' });
const sender = socket.data.playerId;
if(!sender) return cb && cb({ error: 'not joined' });
if(room.hostId !== sender) return cb && cb({ error: 'only the host can change no-remise' });
room.noRemise = !!enabled;
// Broadcast updated room state to all participants
try{ sendRoomUpdate(room); }catch(_){ }
try{ io.to(room.id).emit('room:no_remise:changed', { roomId: room.id, enabled: room.noRemise }); }catch(_){ }
return cb && cb({ ok: true, noRemise: room.noRemise });
});
socket.on('game:move', ({ roomId, from, to, promotion }, cb) => { socket.on('game:move', ({ roomId, from, to, promotion }, cb) => {
const room = rooms.get(roomId); const room = rooms.get(roomId);
if (!room) return cb && cb({ error: 'room not found' }); if (!room) return cb && cb({ error: 'room not found' });