728

Casino

 import React, { useEffect, useRef, useState } from 'react';

/**

  • Live Casino Prototype with Extended Bet Types
    • Added: Red/Black, Dozen, Column bets with updated pay table.
    • Still client-side demo only; server-side authority required in production. */

export default function LiveCasinoPrototype() { const videoRef = useRef(null); const canvasRef = useRef(null); const [balance, setBalance] = useState(1000); const [currentBets, setCurrentBets] = useState([]); const [selectedChip, setSelectedChip] = useState(10); const [isSpinning, setIsSpinning] = useState(false); const [lastResult, setLastResult] = useState(null); const [messages, setMessages] = useState([]);

const redNumbers = [1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36]; const blackNumbers = [2,4,6,8,10,11,13,15,17,20,22,24,26,28,29,31,33,35];

useEffect(() => { async function attachDemo() { try { const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false }); if (videoRef.current) videoRef.current.srcObject = stream; } catch (e) { console.warn('No camera available — video placeholder will remain blank.'); } } attachDemo(); drawWheel(0); return () => { if (videoRef.current && videoRef.current.srcObject) { const tracks = videoRef.current.srcObject.getTracks(); tracks.forEach(t => t.stop()); } }; }, []);

function placeBet(type, extra = null) { if (balance < selectedChip) return alert('Insufficient balance'); const bet = { id: Date.now() + Math.random(), type, amount: selectedChip, ...extra }; setCurrentBets(b => [...b, bet]); setBalance(b => b - selectedChip); }

function clearBets() { const refund = currentBets.reduce((s, b) => s + b.amount, 0); setBalance(b => b + refund); setCurrentBets([]); }

function spinWheel() { if (isSpinning) return; setIsSpinning(true); setLastResult(null); const outcome = Math.floor(Math.random() * 37); animateSpin(outcome, () => { resolveBets(outcome); setIsSpinning(false); setLastResult(outcome); }); }

function resolveBets(outcome) { let payout = 0; currentBets.forEach(b => { if (b.type === 'number' && b.number === outcome) { payout += b.amount * 36; } else if (b.type === 'even' && outcome !== 0 && outcome % 2 === 0) { payout += b.amount * 2; } else if (b.type === 'odd' && outcome % 2 === 1) { payout += b.amount * 2; } else if (b.type === 'red' && redNumbers.includes(outcome)) { payout += b.amount * 2; } else if (b.type === 'black' && blackNumbers.includes(outcome)) { payout += b.amount * 2; } else if (b.type === 'dozen' && b.range) { if (outcome >= b.range[0] && outcome <= b.range[1]) payout += b.amount * 3; } else if (b.type === 'column' && b.column) { if (outcome !== 0 && ((outcome - 1) % 3) + 1 === b.column) payout += b.amount * 3; } }); if (payout > 0) setMessages(m => [You won ${payout}, ...m].slice(0, 50)); else setMessages(m => [You lost this round (${outcome}), ...m].slice(0, 50)); setBalance(b => b + payout); setCurrentBets([]); }

function drawWheel(rotation) { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); const size = 300; canvas.width = size; canvas.height = size; ctx.clearRect(0, 0, size, size);

const segments = 37;
const angle = (Math.PI * 2) / segments;

for (let i = 0; i < segments; i++) {
  const start = i * angle + rotation;
  ctx.beginPath();
  ctx.moveTo(size / 2, size / 2);
  ctx.arc(size / 2, size / 2, size / 2 - 10, start, start + angle);
  ctx.closePath();
  ctx.fillStyle = redNumbers.includes(i) ? 'red' : blackNumbers.includes(i) ? 'black' : 'green';
  ctx.fill();
  ctx.save();
  ctx.translate(size / 2, size / 2);
  ctx.rotate(start + angle / 2);
  ctx.fillStyle = '#fff';
  ctx.font = '12px sans-serif';
  ctx.fillText(String(i), size / 2 - 40, 0);
  ctx.restore();
}
ctx.beginPath();
ctx.arc(size / 2, size / 2, 30, 0, Math.PI * 2);
ctx.fillStyle = '#222';
ctx.fill();
ctx.fillStyle = '#c53030';
ctx.beginPath();
ctx.moveTo(size - 10, size / 2 - 10);
ctx.lineTo(size - 10, size / 2 + 10);
ctx.lineTo(size - 30, size / 2);
ctx.closePath();
ctx.fill();

}

function animateSpin(outcome, cb) { const segments = 37; const finalAngle = ((Math.PI * 2) - (outcome * (Math.PI * 2) / segments)) + Math.PI / 4; const start = performance.now(); const duration = 4000 + Math.random() * 2000;

function frame(now) {
  const t = Math.min(1, (now - start) / duration);
  const eased = 1 - Math.pow(1 - t, 3);
  const rotation = eased * finalAngle * 6;
  drawWheel(rotation);
  if (t < 1) requestAnimationFrame(frame);
  else cb();
}
requestAnimationFrame(frame);

}

function placeNumberBet(n) { placeBet('number', { number: n }); }

return (

Live Casino — Extended Bets Prototype

  <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
    <div className="md:col-span-2 bg-gray-50 rounded-lg p-3 shadow">
      <div className="flex gap-3">
        <div className="w-2/3">
          <div className="bg-black rounded overflow-hidden">
            <video ref={videoRef} autoPlay playsInline muted className="w-full h-56 object-cover" />
          </div>
        </div>
        <div className="w-1/3 space-y-2">
          <div className="bg-white p-3 rounded shadow-sm">
            <div className="text-xs text-gray-500">Balance</div>
            <div className="text-xl font-semibold">${balance}</div>
          </div>
          <div className="bg-white p-3 rounded shadow-sm">
            <div className="text-xs text-gray-500">Selected Chip</div>
            <div className="flex gap-2 mt-2">
              {[1,5,10,25,100].map(c => (
                <button key={c} onClick={() => setSelectedChip(c)} className={`px-2 py-1 rounded ${selectedChip===c? 'ring-2 ring-blue-400':''}`}>{c}</button>
              ))}
            </div>
          </div>
          <div className="bg-white p-3 rounded shadow-sm text-center">
            <button onClick={spinWheel} disabled={isSpinning} className={`px-3 py-2 rounded ${isSpinning? 'bg-gray-400 text-white' : 'bg-green-600 text-white'}`}>
              {isSpinning ? 'Spinning…' : 'Spin'}
            </button>
          </div>
        </div>
      </div>

      <div className="mt-4 bg-white p-3 rounded shadow-sm">
        <div className="flex gap-6">
          <canvas ref={canvasRef} width={300} height={300} className="rounded" />
          <div className="flex-1">
            <div className="grid grid-cols-6 gap-2">
              {Array.from({length: 37}, (_, i) => (
                <button key={i} onClick={() => placeNumberBet(i)} className="border rounded p-2 text-sm">{i}</button>
              ))}
            </div>
            <div className="mt-3 flex flex-wrap gap-2">
              <button onClick={() => placeBet('even')} className="px-3 py-1 bg-gray-100 rounded">Even</button>
              <button onClick={() => placeBet('odd')} className="px-3 py-1 bg-gray-100 rounded">Odd</button>
              <button onClick={() => placeBet('red')} className="px-3 py-1 bg-red-200 rounded">Red</button>
              <button onClick={() => placeBet('black')} className="px-3 py-1 bg-black text-white rounded">Black</button>
              <button onClick={() => placeBet('dozen',{range:[1,12]})} className="px-3 py-1 bg-gray-100 rounded">1-12</button>
              <button onClick={() => placeBet('dozen',{range:[13,24]})} className="px-3 py-1 bg-gray-100 rounded">13-24</button>
              <button onClick={() => placeBet('dozen',{range:[25,36]})} className="px-3 py-1 bg-gray-100 rounded">25-36</button>
              <button onClick={() => placeBet('column',{column:1})} className="px-3 py-1 bg-gray-100 rounded">Col 1</button>
              <button onClick={() => placeBet('column',{column:2})} className="px-3 py-1 bg-gray-100 rounded">Col 2</button>
              <button onClick={() => placeBet('column',{column:3})} className="px-3 py-1 bg-gray-100 rounded">Col 3</button>
              <button onClick={clearBets} className="px-3 py-1 bg-red-100 rounded">Clear Bets</button>
            </div>
            <div className="mt-3">
              <div className="text-sm text-gray-500">Placed Bets</div>
              <ul className="text-sm mt-1">
                {currentBets.map(b => (
                  <li key={b.id}>{b.type === 'number' ? `Number ${b.number}` : b.type} — ${b.amount}</li>
                ))}
                {!currentBets.length && <li className="text-gray-400">No bets</li>}
              </ul>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div className="bg-white p-3 rounded shadow-sm">
      <div className="text-sm text-gray-500 mb-2">Activity</div>
      <div className="h-80 overflow-auto border p-2 rounded bg-gray-50">
        {messages.map((m, idx) => (<div key={idx} className="text-sm py-1">{m}</div>))}
        {messages.length===0 && <div className="text-gray-400">No activity yet</div>}
      </div>
    </div>
  </div>

  <div className="mt-6 text-sm text-gray-600">
    <strong>Pay Table:</strong>
    <ul className="list-disc ml-5">
      <li>Exact Number: 35:1</li>
      <li>Even/Odd: 1:1</li>
      <li>Red/Black: 1:1</li>
      <li>Dozens (1-12, 13-24, 25-36): 2:1</li>
      <li>Columns (1st, 2nd, 3rd): 2:1</li>
    </ul>
  </div>
</div>

); }

একটি মন্তব্য পোস্ট করুন

0 মন্তব্যসমূহ
* Please Don't Spam Here. All the Comments are Reviewed by Admin.

#buttons=(Ok, Go it!) #days=(20)

Our website uses cookies to enhance your experience. Learn More
Ok, Go it!