이것저것 수정중.. 지금상태로는 안돌아감
This commit is contained in:
parent
992737ef33
commit
97a0533afd
@ -1,7 +1,11 @@
|
|||||||
import type { DurableObjectNamespace, DurableObjectState } from '@cloudflare/workers-types';
|
import type { DurableObjectNamespace, DurableObjectState } from '@cloudflare/workers-types';
|
||||||
import type { Session, BettingInfo } from './types';
|
import type { Session } from './types';
|
||||||
import { applyBetResults } from './game-results';
|
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 {
|
export interface Env {
|
||||||
COUNTER: DurableObjectNamespace;
|
COUNTER: DurableObjectNamespace;
|
||||||
}
|
}
|
||||||
@ -141,18 +145,15 @@ export class CounterDurableObject {
|
|||||||
private startNoMoreBetPeriod() {
|
private startNoMoreBetPeriod() {
|
||||||
this.noMoreBet = true;
|
this.noMoreBet = true;
|
||||||
this.noMoreBetStartTime = Date.now();
|
this.noMoreBetStartTime = Date.now();
|
||||||
this.noMoreBetEndTime = this.noMoreBetStartTime + 15000; // 15초
|
this.noMoreBetEndTime = this.noMoreBetStartTime + NO_MORE_BET_DURATION_MS; // 15초
|
||||||
|
|
||||||
// 3개의 주사위 랜덤 생성 (1-6)
|
// 3개의 주사위 랜덤 생성 (1-6)
|
||||||
this.dice1 = Math.floor(Math.random() * 6) + 1;
|
this.dice1 = Math.floor(Math.random() * 6) + 1;
|
||||||
this.dice2 = Math.floor(Math.random() * 6) + 1;
|
this.dice2 = Math.floor(Math.random() * 6) + 1;
|
||||||
this.dice3 = 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);
|
this.ctx.storage.put('noMoreBet', this.noMoreBet);
|
||||||
@ -166,14 +167,14 @@ export class CounterDurableObject {
|
|||||||
}
|
}
|
||||||
this.gameTimer = setTimeout(() => {
|
this.gameTimer = setTimeout(() => {
|
||||||
this.startBettingPeriod();
|
this.startBettingPeriod();
|
||||||
}, 15000);
|
}, NO_MORE_BET_DURATION_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2번 로직: noMoreBet = false, 45초간 유지
|
// 2번 로직: noMoreBet = false, 45초간 유지
|
||||||
private startBettingPeriod() {
|
private startBettingPeriod() {
|
||||||
this.noMoreBet = false;
|
this.noMoreBet = false;
|
||||||
this.noMoreBetStartTime = Date.now();
|
this.noMoreBetStartTime = Date.now();
|
||||||
this.noMoreBetEndTime = this.noMoreBetStartTime + 45000; // 45초
|
this.noMoreBetEndTime = this.noMoreBetStartTime + BETTING_DURATION_MS; // 45초
|
||||||
|
|
||||||
// 주사위 값 클리어
|
// 주사위 값 클리어
|
||||||
this.dice1 = null;
|
this.dice1 = null;
|
||||||
@ -205,7 +206,7 @@ export class CounterDurableObject {
|
|||||||
}
|
}
|
||||||
this.gameTimer = setTimeout(() => {
|
this.gameTimer = setTimeout(() => {
|
||||||
this.startNoMoreBetPeriod();
|
this.startNoMoreBetPeriod();
|
||||||
}, 45000);
|
}, BETTING_DURATION_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
async webSocketClose(ws: WebSocket, code: number, _reason: string, _wasClean: boolean) {
|
async webSocketClose(ws: WebSocket, code: number, _reason: string, _wasClean: boolean) {
|
||||||
@ -222,21 +223,6 @@ export class CounterDurableObject {
|
|||||||
// WebSocket Hibernation API를 사용할 때는 getWebSockets()로 실제 연결 수를 확인
|
// WebSocket Hibernation API를 사용할 때는 getWebSockets()로 실제 연결 수를 확인
|
||||||
const connectedWebSockets = this.ctx.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 불일치
|
// @ts-ignore - Cloudflare Workers types 불일치
|
||||||
connectedWebSockets.forEach((ws: WebSocket) => {
|
connectedWebSockets.forEach((ws: WebSocket) => {
|
||||||
@ -258,8 +244,7 @@ export class CounterDurableObject {
|
|||||||
bigResult: session?.bigResult,
|
bigResult: session?.bigResult,
|
||||||
smallResult: session?.smallResult,
|
smallResult: session?.smallResult,
|
||||||
lastWinAmount: session?.lastWinAmount,
|
lastWinAmount: session?.lastWinAmount,
|
||||||
// 전체 사용자 배팅 내역
|
|
||||||
allBettings: allBettings
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.send(message);
|
ws.send(message);
|
||||||
|
|||||||
@ -5,7 +5,9 @@ import type { Session } from './types';
|
|||||||
* 승리 시 배팅금액 * 2 지급, 패배 시 이미 차감된 상태 유지.
|
* 승리 시 배팅금액 * 2 지급, 패배 시 이미 차감된 상태 유지.
|
||||||
* lastWinAmount = (총 승리 수령액 - 총 배팅액)
|
* 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 isOdd = sum % 2 === 1;
|
||||||
const isBig = sum >= 10; // 10~18: 대
|
const isBig = sum >= 10; // 10~18: 대
|
||||||
|
|
||||||
|
|||||||
132
src/lib/types.ts
132
src/lib/types.ts
@ -1,82 +1,72 @@
|
|||||||
export interface Session {
|
export interface Session {
|
||||||
id: string;
|
token: string;
|
||||||
webSocket: WebSocket;
|
webSocket: WebSocket;
|
||||||
nickname?: string;
|
betInfo: BettingInfo[]; // 배팅 정보
|
||||||
capital?: number;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BettingInfo {
|
export interface BettingInfo {
|
||||||
nickname: string;
|
gameId: string; // 게임 고유 ID
|
||||||
oddBet: number;
|
betType: BetTypeKey;
|
||||||
evenBet: number;
|
betMoney: number; //배팅금액
|
||||||
bigBet: number;
|
isWin?: boolean; //승리여부
|
||||||
smallBet: number;
|
winMoney?: number; //승리금액
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BetType = {
|
export const BetType = {
|
||||||
BIG: {
|
// 11~17
|
||||||
category: 'A',
|
Big: { maxBet: 300, payout: 1 },
|
||||||
typeDescriptionEng: 'Big / Small Bet',
|
Small: { maxBet: 300, payout: 1 },
|
||||||
typeDescriptionKr: '대/소 배팅',
|
Even: { maxBet: 300, payout: 1 },
|
||||||
tripeLose: true,
|
Odd: { maxBet: 300, payout: 1 },
|
||||||
key: 'big',
|
Pair1: { maxBet: 35, payout: 8 },
|
||||||
keyName: 'Big Bet',
|
Pair2: { maxBet: 35, payout: 8 },
|
||||||
rslt: 'big_rslt',
|
Pair3: { maxBet: 35, payout: 8 },
|
||||||
rsltName: 'Big Result',
|
Pair4: { maxBet: 35, payout: 8 },
|
||||||
winConditionDescription: '주사위 총합 10~18',
|
Pair5: { maxBet: 35, payout: 8 },
|
||||||
maxAmount: 300000,
|
Pair6: { maxBet: 35, payout: 8 },
|
||||||
payout: 2,
|
Triple1: { maxBet: 2, payout: 150 },
|
||||||
},
|
Triple2: { maxBet: 2, payout: 150 },
|
||||||
SMALL: {
|
Triple3: { maxBet: 2, payout: 150 },
|
||||||
category: 'A',
|
Triple4: { maxBet: 2, payout: 150 },
|
||||||
typeDescriptionEng: 'Big / Small Bet',
|
Triple5: { maxBet: 2, payout: 150 },
|
||||||
typeDescriptionKr: '대/소 배팅',
|
Triple6: { maxBet: 2, payout: 150 },
|
||||||
tripeLose: true,
|
TripleAny: { maxBet: 10, payout: 24 },
|
||||||
key: 'small',
|
Total4: { maxBet: 5, payout: 50 },
|
||||||
keyName: 'Small Bet',
|
Total5: { maxBet: 10, payout: 30 },
|
||||||
rslt: 'small_rslt',
|
Total6: { maxBet: 15, payout: 18 },
|
||||||
rsltName: 'Small Result',
|
Total7: { maxBet: 25, payout: 12 },
|
||||||
winConditionDescription: '주사위 총합 1~9',
|
Total8: { maxBet: 35, payout: 8 },
|
||||||
maxAmount: 300000,
|
Total9: { maxBet: 50, payout: 6 },
|
||||||
payout: 2,
|
Total10: { maxBet: 50, payout: 6 },
|
||||||
},
|
Total11: { maxBet: 50, payout: 6 },
|
||||||
EVEN: {
|
Total12: { maxBet: 50, payout: 6 },
|
||||||
category: 'B',
|
Total13: { maxBet: 35, payout: 8 },
|
||||||
typeDescriptionEng: 'Even / Odd Bet',
|
Total14: { maxBet: 25, payout: 12 },
|
||||||
typeDescriptionKr: '홀/짝 배팅',
|
Total15: { maxBet: 15, payout: 18 },
|
||||||
tripeLose: true,
|
Total16: { maxBet: 10, payout: 30 },
|
||||||
key: 'even',
|
Total17: { maxBet: 5, payout: 50 },
|
||||||
keyName: 'Even Bet',
|
Domino12:{ maxBet: 60, payout: 5 },
|
||||||
rslt: 'even_rslt',
|
Domino13:{ maxBet: 60, payout: 5 },
|
||||||
rsltName: 'Even Result',
|
Domino14:{ maxBet: 60, payout: 5 },
|
||||||
winConditionDescription: '주사위 총합 짝수',
|
Domino15:{ maxBet: 60, payout: 5 },
|
||||||
maxAmount: 300000,
|
Domino16:{ maxBet: 60, payout: 5 },
|
||||||
payout: 2,
|
Domino23:{ maxBet: 60, payout: 5 },
|
||||||
},
|
Domino24:{ maxBet: 60, payout: 5 },
|
||||||
ODD: {
|
Domino25:{ maxBet: 60, payout: 5 },
|
||||||
category: 'B',
|
Domino26:{ maxBet: 60, payout: 5 },
|
||||||
typeDescriptionEng: 'Even / Odd Bet',
|
Domino34:{ maxBet: 60, payout: 5 },
|
||||||
typeDescriptionKr: '홀/짝 배팅',
|
Domino35:{ maxBet: 60, payout: 5 },
|
||||||
tripeLose: true,
|
Domino36:{ maxBet: 60, payout: 5 },
|
||||||
key: 'odd',
|
Domino45:{ maxBet: 60, payout: 5 },
|
||||||
keyName: 'Odd Bet',
|
Domino46:{ maxBet: 60, payout: 5 },
|
||||||
rslt: 'odd_rslt',
|
Domino56:{ maxBet: 60, payout: 5 },
|
||||||
rsltName: 'Odd Result',
|
Single1_N1:{ maxBet: 100 },
|
||||||
winConditionDescription: '주사위 총합 홀수',
|
Single2_N1:{ maxBet: 100 },
|
||||||
maxAmount: 300000,
|
Single3_N1:{ maxBet: 100 },
|
||||||
payout: 2,
|
Single4_N1:{ maxBet: 100 },
|
||||||
}
|
Single5_N1:{ maxBet: 100 },
|
||||||
|
Single6_N1:{ maxBet: 100 },
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type BetTypeKey = keyof typeof BetType;
|
export type BetTypeKey = keyof typeof BetType;
|
||||||
|
|||||||
@ -538,61 +538,6 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user