이것저것 수정중.. 지금상태로는 안돌아감

This commit is contained in:
pd0a6847 2025-11-19 17:28:38 +09:00
parent 992737ef33
commit 97a0533afd
4 changed files with 75 additions and 153 deletions

View File

@ -1,7 +1,11 @@
import type { DurableObjectNamespace, DurableObjectState } from '@cloudflare/workers-types';
import type { Session, BettingInfo } from './types';
import type { Session } from './types';
import { applyBetResults } from './game-results';
// 게임 지속 시간 상수 (ms)
export const NO_MORE_BET_DURATION_MS = 15_000; // 15초
export const BETTING_DURATION_MS = 45_000; // 45초
export interface Env {
COUNTER: DurableObjectNamespace;
}
@ -141,18 +145,15 @@ export class CounterDurableObject {
private startNoMoreBetPeriod() {
this.noMoreBet = true;
this.noMoreBetStartTime = Date.now();
this.noMoreBetEndTime = this.noMoreBetStartTime + 15000; // 15초
this.noMoreBetEndTime = this.noMoreBetStartTime + NO_MORE_BET_DURATION_MS; // 15초
// 3개의 주사위 랜덤 생성 (1-6)
this.dice1 = Math.floor(Math.random() * 6) + 1;
this.dice2 = Math.floor(Math.random() * 6) + 1;
this.dice3 = Math.floor(Math.random() * 6) + 1;
// 주사위 합계
const sum = this.dice1 + this.dice2 + this.dice3;
// 추출된 함수로 배팅 결과 계산 및 세션 갱신
applyBetResults(this.sessions, sum);
applyBetResults(this.sessions, this.dice1, this.dice2, this.dice3);
// 상태 저장
this.ctx.storage.put('noMoreBet', this.noMoreBet);
@ -166,14 +167,14 @@ export class CounterDurableObject {
}
this.gameTimer = setTimeout(() => {
this.startBettingPeriod();
}, 15000);
}, NO_MORE_BET_DURATION_MS);
}
// 2번 로직: noMoreBet = false, 45초간 유지
private startBettingPeriod() {
this.noMoreBet = false;
this.noMoreBetStartTime = Date.now();
this.noMoreBetEndTime = this.noMoreBetStartTime + 45000; // 45초
this.noMoreBetEndTime = this.noMoreBetStartTime + BETTING_DURATION_MS; // 45초
// 주사위 값 클리어
this.dice1 = null;
@ -205,7 +206,7 @@ export class CounterDurableObject {
}
this.gameTimer = setTimeout(() => {
this.startNoMoreBetPeriod();
}, 45000);
}, BETTING_DURATION_MS);
}
async webSocketClose(ws: WebSocket, code: number, _reason: string, _wasClean: boolean) {
@ -222,21 +223,6 @@ export class CounterDurableObject {
// WebSocket Hibernation API를 사용할 때는 getWebSockets()로 실제 연결 수를 확인
const connectedWebSockets = this.ctx.getWebSockets();
// 전체 사용자 배팅 내역 수집
const allBettings: BettingInfo[] = [];
this.sessions.forEach((session) => {
if (session.nickname && (session.oddBet > 0 || session.evenBet > 0 || session.bigBet > 0 || session.smallBet > 0)) {
allBettings.push({
nickname: session.nickname,
oddBet: session.oddBet,
evenBet: session.evenBet,
bigBet: session.bigBet,
smallBet: session.smallBet
});
}
});
// 각 세션별로 메시지 전송
// @ts-ignore - Cloudflare Workers types 불일치
connectedWebSockets.forEach((ws: WebSocket) => {
@ -258,8 +244,7 @@ export class CounterDurableObject {
bigResult: session?.bigResult,
smallResult: session?.smallResult,
lastWinAmount: session?.lastWinAmount,
// 전체 사용자 배팅 내역
allBettings: allBettings
});
ws.send(message);

View File

@ -5,7 +5,9 @@ import type { Session } from './types';
* * 2 , .
* lastWinAmount = ( - )
*/
export function applyBetResults(sessions: Map<WebSocket, Session>, sum: number) {
export function applyBetResults(sessions: Map<WebSocket, Session>, dice1: number, dice2: number, dice3: number) {
// 주사위 합계
const sum = dice1 + dice2 + dice3;
const isOdd = sum % 2 === 1;
const isBig = sum >= 10; // 10~18: 대

View File

@ -1,82 +1,72 @@
export interface Session {
id: string;
token: string;
webSocket: WebSocket;
nickname?: string;
capital?: number;
// 배팅 정보
oddBet: number;
evenBet: number;
bigBet: number;
smallBet: number;
// 결과
oddResult?: 'win' | 'lose' | null;
evenResult?: 'win' | 'lose' | null;
bigResult?: 'win' | 'lose' | null;
smallResult?: 'win' | 'lose' | null;
lastWinAmount?: number;
betInfo: BettingInfo[]; // 배팅 정보
capital?: number; // 현재 자본금
}
export interface BettingInfo {
nickname: string;
oddBet: number;
evenBet: number;
bigBet: number;
smallBet: number;
gameId: string; // 게임 고유 ID
betType: BetTypeKey;
betMoney: number; //배팅금액
isWin?: boolean; //승리여부
winMoney?: number; //승리금액
}
export const BetType = {
BIG: {
category: 'A',
typeDescriptionEng: 'Big / Small Bet',
typeDescriptionKr: '대/소 배팅',
tripeLose: true,
key: 'big',
keyName: 'Big Bet',
rslt: 'big_rslt',
rsltName: 'Big Result',
winConditionDescription: '주사위 총합 10~18',
maxAmount: 300000,
payout: 2,
},
SMALL: {
category: 'A',
typeDescriptionEng: 'Big / Small Bet',
typeDescriptionKr: '대/소 배팅',
tripeLose: true,
key: 'small',
keyName: 'Small Bet',
rslt: 'small_rslt',
rsltName: 'Small Result',
winConditionDescription: '주사위 총합 1~9',
maxAmount: 300000,
payout: 2,
},
EVEN: {
category: 'B',
typeDescriptionEng: 'Even / Odd Bet',
typeDescriptionKr: '홀/짝 배팅',
tripeLose: true,
key: 'even',
keyName: 'Even Bet',
rslt: 'even_rslt',
rsltName: 'Even Result',
winConditionDescription: '주사위 총합 짝수',
maxAmount: 300000,
payout: 2,
},
ODD: {
category: 'B',
typeDescriptionEng: 'Even / Odd Bet',
typeDescriptionKr: '홀/짝 배팅',
tripeLose: true,
key: 'odd',
keyName: 'Odd Bet',
rslt: 'odd_rslt',
rsltName: 'Odd Result',
winConditionDescription: '주사위 총합 홀수',
maxAmount: 300000,
payout: 2,
}
// 11~17
Big: { maxBet: 300, payout: 1 },
Small: { maxBet: 300, payout: 1 },
Even: { maxBet: 300, payout: 1 },
Odd: { maxBet: 300, payout: 1 },
Pair1: { maxBet: 35, payout: 8 },
Pair2: { maxBet: 35, payout: 8 },
Pair3: { maxBet: 35, payout: 8 },
Pair4: { maxBet: 35, payout: 8 },
Pair5: { maxBet: 35, payout: 8 },
Pair6: { maxBet: 35, payout: 8 },
Triple1: { maxBet: 2, payout: 150 },
Triple2: { maxBet: 2, payout: 150 },
Triple3: { maxBet: 2, payout: 150 },
Triple4: { maxBet: 2, payout: 150 },
Triple5: { maxBet: 2, payout: 150 },
Triple6: { maxBet: 2, payout: 150 },
TripleAny: { maxBet: 10, payout: 24 },
Total4: { maxBet: 5, payout: 50 },
Total5: { maxBet: 10, payout: 30 },
Total6: { maxBet: 15, payout: 18 },
Total7: { maxBet: 25, payout: 12 },
Total8: { maxBet: 35, payout: 8 },
Total9: { maxBet: 50, payout: 6 },
Total10: { maxBet: 50, payout: 6 },
Total11: { maxBet: 50, payout: 6 },
Total12: { maxBet: 50, payout: 6 },
Total13: { maxBet: 35, payout: 8 },
Total14: { maxBet: 25, payout: 12 },
Total15: { maxBet: 15, payout: 18 },
Total16: { maxBet: 10, payout: 30 },
Total17: { maxBet: 5, payout: 50 },
Domino12:{ maxBet: 60, payout: 5 },
Domino13:{ maxBet: 60, payout: 5 },
Domino14:{ maxBet: 60, payout: 5 },
Domino15:{ maxBet: 60, payout: 5 },
Domino16:{ maxBet: 60, payout: 5 },
Domino23:{ maxBet: 60, payout: 5 },
Domino24:{ maxBet: 60, payout: 5 },
Domino25:{ maxBet: 60, payout: 5 },
Domino26:{ maxBet: 60, payout: 5 },
Domino34:{ maxBet: 60, payout: 5 },
Domino35:{ maxBet: 60, payout: 5 },
Domino36:{ maxBet: 60, payout: 5 },
Domino45:{ maxBet: 60, payout: 5 },
Domino46:{ maxBet: 60, payout: 5 },
Domino56:{ maxBet: 60, payout: 5 },
Single1_N1:{ maxBet: 100 },
Single2_N1:{ maxBet: 100 },
Single3_N1:{ maxBet: 100 },
Single4_N1:{ maxBet: 100 },
Single5_N1:{ maxBet: 100 },
Single6_N1:{ maxBet: 100 },
} as const;
export type BetTypeKey = keyof typeof BetType;

View File

@ -538,61 +538,6 @@
{/if}
</div>
<!-- 전체 사용자 배팅 내역 -->
{#if isConnected && allBettings.length > 0}
<div class="mb-8 p-6 bg-gradient-to-br from-slate-50 to-gray-50 rounded-xl border-2 border-slate-200">
<h2 class="text-xl font-bold text-center mb-4 text-gray-800">
📊 전체 배팅 현황
</h2>
<div class="space-y-3 max-h-60 overflow-y-auto">
{#each allBettings as betting}
<div class="p-3 bg-white rounded-lg border border-gray-200">
<div class="font-semibold text-gray-800 mb-2">{betting.nickname}</div>
<div class="grid grid-cols-4 gap-2 text-sm">
{#if betting.oddBet > 0}
<div class="bg-blue-50 p-2 rounded text-center">
<div class="text-xs text-gray-600"></div>
<div class="font-semibold text-blue-600">{betting.oddBet.toLocaleString()}</div>
</div>
{/if}
{#if betting.evenBet > 0}
<div class="bg-pink-50 p-2 rounded text-center">
<div class="text-xs text-gray-600"></div>
<div class="font-semibold text-pink-600">{betting.evenBet.toLocaleString()}</div>
</div>
{/if}
{#if betting.bigBet > 0}
<div class="bg-orange-50 p-2 rounded text-center">
<div class="text-xs text-gray-600"></div>
<div class="font-semibold text-orange-600">{betting.bigBet.toLocaleString()}</div>
</div>
{/if}
{#if betting.smallBet > 0}
<div class="bg-purple-50 p-2 rounded text-center">
<div class="text-xs text-gray-600"></div>
<div class="font-semibold text-purple-600">{betting.smallBet.toLocaleString()}</div>
</div>
{/if}
</div>
</div>
{/each}
</div>
</div>
{/if}
<!-- 설명 -->
<div class="mt-8 p-4 bg-gray-50 rounded-lg border border-gray-200">
<h2 class="font-semibold text-gray-800 mb-2">게임 규칙</h2>
<ul class="text-sm text-gray-600 space-y-1">
<li>✅ Cloudflare Durable Objects로 상태 관리</li>
<li>✅ WebSocket으로 실시간 양방향 통신</li>
<li>🎲 <strong>베팅 기간 (45초)</strong>: 홀수 또는 짝수 선택 가능</li>
<li>🚫 <strong>베팅 마감 (15초)</strong>: 주사위 결과 확인 및 대기</li>
<li>📊 Progress bar로 남은 시간 시각화</li>
<li>🔄 게임은 자동으로 반복됩니다</li>
<li>👥 모든 접속자에게 실시간 동기화</li>
</ul>
</div>
</div>
</div>