teambpc / index.html
NeverBlufff's picture
Add 1 files
4f1faf9 verified
Raw History Blame Contribute Delete
16.4 kB
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Poker GTO Trainer - Scanner</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary: #2563eb;
--secondary: #1e40af;
--dark: #1e293b;
--darker: #0f172a;
--light: #f8fafc;
--success: #10b981;
--danger: #ef4444;
--warning: #f59e0b;
}
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background-color: var(--darker);
color: white;
}
.camera-container {
position: relative;
width: 100%;
max-width: 500px;
margin: 0 auto;
height: 70vh;
overflow: hidden;
border-radius: 12px;
background-color: black;
}
.camera-preview {
width: 100%;
height: 100%;
object-fit: cover;
}
.scan-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
}
.scan-guide {
width: 80%;
height: 120px;
border: 2px dashed var(--primary);
border-radius: 8px;
margin-bottom: 20px;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-weight: bold;
}
.capture-btn {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
width: 70px;
height: 70px;
background-color: white;
border-radius: 50%;
border: 4px solid var(--primary);
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
.capture-btn::after {
content: '';
width: 50px;
height: 50px;
background-color: var(--primary);
border-radius: 50%;
}
.result-container {
display: none;
padding: 20px;
background-color: var(--dark);
border-radius: 12px;
margin-top: 20px;
}
.card-display {
width: 80px;
height: 120px;
background-color: white;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
font-weight: bold;
color: black;
margin: 0 auto;
position: relative;
}
.card-display::before {
content: attr(data-suit);
position: absolute;
top: 5px;
left: 5px;
font-size: 16px;
}
.card-display::after {
content: attr(data-suit);
position: absolute;
bottom: 5px;
right: 5px;
font-size: 16px;
transform: rotate(180deg);
}
.heart, .diamond {
color: red;
}
.spade, .club {
color: black;
}
.action-buttons {
display: flex;
gap: 10px;
margin-top: 20px;
}
.btn {
padding: 12px 20px;
border-radius: 8px;
font-weight: bold;
border: none;
cursor: pointer;
flex: 1;
text-align: center;
}
.btn-primary {
background-color: var(--primary);
color: white;
}
.btn-secondary {
background-color: var(--dark);
color: white;
border: 1px solid var(--primary);
}
.btn-danger {
background-color: var(--danger);
color: white;
}
.accuracy-meter {
height: 10px;
background-color: #334155;
border-radius: 5px;
margin-top: 10px;
overflow: hidden;
}
.accuracy-fill {
height: 100%;
background-color: var(--success);
width: 90%;
}
.card-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
margin-top: 20px;
}
.card-option {
padding: 10px;
border: 1px solid #334155;
border-radius: 8px;
text-align: center;
cursor: pointer;
transition: all 0.2s;
}
.card-option:hover {
background-color: #334155;
}
.card-option.selected {
background-color: var(--primary);
border-color: var(--primary);
}
</style>
</head>
<body>
<div class="min-h-screen flex flex-col">
<!-- Header -->
<div class="bg-dark p-4 flex items-center justify-between">
<button class="text-white">
<i class="fas fa-arrow-left"></i>
</button>
<h1 class="text-xl font-bold">Scanner des cartes</h1>
<div class="w-6"></div> <!-- Spacer for balance -->
</div>
<!-- Main Content -->
<div class="flex-1 p-4">
<!-- Camera Preview -->
<div class="camera-container" id="cameraContainer">
<video id="cameraPreview" class="camera-preview" autoplay playsinline></video>
<div class="scan-overlay">
<div class="scan-guide">Placez les cartes dans ce cadre</div>
</div>
<button class="capture-btn" id="captureBtn"></button>
</div>
<!-- Result Display -->
<div class="result-container" id="resultContainer">
<h2 class="text-xl font-bold mb-4">Résultat de l'analyse</h2>
<div class="flex items-center justify-center gap-4 mb-6">
<div class="card-display" id="card1" data-rank="A" data-suit="♠">
A<span class="spade">♠</span>
</div>
<div class="card-display" id="card2" data-rank="K" data-suit="♥">
K<span class="heart">♥</span>
</div>
</div>
<div class="bg-slate-700 p-4 rounded-lg">
<h3 class="font-bold mb-2">Action recommandée</h3>
<p class="text-green-400 font-bold text-lg mb-2">Open Raise (92%)</p>
<div class="accuracy-meter">
<div class="accuracy-fill"></div>
</div>
<p class="text-sm text-slate-300 mt-2">Confiance de l'analyse: 90%</p>
</div>
<div class="mt-6">
<h3 class="font-bold mb-2">Autres options possibles</h3>
<div class="card-grid">
<div class="card-option">Call (8%)</div>
<div class="card-option">Fold (0%)</div>
<div class="card-option">3-Bet (45%)</div>
<div class="card-option">4-Bet (12%)</div>
</div>
</div>
<div class="action-buttons mt-6">
<button class="btn btn-secondary" id="rescanBtn">
<i class="fas fa-redo mr-2"></i>Rescanner
</button>
<button class="btn btn-primary" id="saveResultBtn">
<i class="fas fa-save mr-2"></i>Sauvegarder
</button>
</div>
</div>
<!-- Alternative Upload -->
<div class="mt-6 text-center">
<p class="text-slate-400 mb-3">Ou sélectionnez une image depuis votre galerie</p>
<button class="btn btn-secondary" id="uploadBtn">
<i class="fas fa-upload mr-2"></i>Choisir une image
</button>
<input type="file" id="fileInput" accept="image/*" class="hidden">
</div>
</div>
</div>
<script>
// Camera and scan functionality
let stream = null;
const cameraContainer = document.getElementById('cameraContainer');
const cameraPreview = document.getElementById('cameraPreview');
const captureBtn = document.getElementById('captureBtn');
const resultContainer = document.getElementById('resultContainer');
const rescanBtn = document.getElementById('rescanBtn');
const saveResultBtn = document.getElementById('saveResultBtn');
const uploadBtn = document.getElementById('uploadBtn');
const fileInput = document.getElementById('fileInput');
// Start camera
async function startCamera() {
try {
stream = await navigator.mediaDevices.getUserMedia({
video: {
facingMode: 'environment',
width: { ideal: 1280 },
height: { ideal: 720 }
},
audio: false
});
cameraPreview.srcObject = stream;
cameraContainer.style.display = 'block';
resultContainer.style.display = 'none';
} catch (err) {
console.error("Error accessing camera:", err);
alert("Impossible d'accéder à la caméra. Veuillez vérifier les permissions.");
// Fallback to upload
uploadBtn.click();
}
}
// Capture photo
function capturePhoto() {
const canvas = document.createElement('canvas');
canvas.width = cameraPreview.videoWidth;
canvas.height = cameraPreview.videoHeight;
const ctx = canvas.getContext('2d');
// Draw image with crop to guide area
const guideSize = Math.min(cameraPreview.videoWidth * 0.8, cameraPreview.videoHeight * 0.5);
const x = (cameraPreview.videoWidth - guideSize) / 2;
const y = (cameraPreview.videoHeight - guideSize) / 2;
ctx.drawImage(cameraPreview, x, y, guideSize, guideSize, 0, 0, canvas.width, canvas.height);
// Stop camera
stopCamera();
// Show result
analyzeImage(canvas.toDataURL('image/jpeg'));
}
// Stop camera
function stopCamera() {
if (stream) {
stream.getTracks().forEach(track => track.stop());
stream = null;
}
}
// Analyze image (simulated with better card recognition)
function analyzeImage(imageData) {
// Hide camera and show result
cameraContainer.style.display = 'none';
resultContainer.style.display = 'block';
// Simulate card recognition with more realistic results
const sampleCards = [
{ rank: 'A', suit: '♠', suitClass: 'spade' },
{ rank: 'K', suit: '♥', suitClass: 'heart' },
{ rank: 'Q', suit: '♦', suitClass: 'diamond' },
{ rank: 'J', suit: '♣', suitClass: 'club' },
{ rank: 'T', suit: '♠', suitClass: 'spade' },
{ rank: '9', suit: '♥', suitClass: 'heart' }
];
// Randomly select two different cards
const card1 = sampleCards[Math.floor(Math.random() * sampleCards.length)];
let card2;
do {
card2 = sampleCards[Math.floor(Math.random() * sampleCards.length)];
} while (card1.rank === card2.rank && card1.suit === card2.suit);
// Update card displays
document.getElementById('card1').setAttribute('data-rank', card1.rank);
document.getElementById('card1').setAttribute('data-suit', card1.suit);
document.getElementById('card1').innerHTML = `${card1.rank}<span class="${card1.suitClass}">${card1.suit}</span>`;
document.getElementById('card2').setAttribute('data-rank', card2.rank);
document.getElementById('card2').setAttribute('data-suit', card2.suit);
document.getElementById('card2').innerHTML = `${card2.rank}<span class="${card2.suitClass}">${card2.suit}</span>`;
// Determine action based on cards (simplified poker logic)
let action, percentage;
if (card1.rank === 'A' || card2.rank === 'A') {
action = "Open Raise";
percentage = "92%";
} else if (card1.rank === card2.rank) {
action = "3-Bet";
percentage = "85%";
} else if (card1.suitClass === card2.suitClass) {
action = "Call";
percentage = "75%";
} else {
action = "Fold";
percentage = "60%";
}
document.querySelector('.text-green-400').textContent = `${action} (${percentage})`;
}
// Handle file upload
function handleFileUpload(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
// Hide camera and show result
cameraContainer.style.display = 'none';
resultContainer.style.display = 'block';
// Analyze the uploaded image
analyzeImage(e.target.result);
};
reader.readAsDataURL(file);
}
}
// Initialize app
document.addEventListener('DOMContentLoaded', function() {
// Start camera automatically
startCamera();
// Capture button
captureBtn.addEventListener('click', capturePhoto);
// Rescan button
rescanBtn.addEventListener('click', function() {
startCamera();
});
// Save result button
saveResultBtn.addEventListener('click', function() {
alert("Résultat sauvegardé dans votre historique");
});
// Upload button
uploadBtn.addEventListener('click', function() {
fileInput.click();
});
// File input change
fileInput.addEventListener('change', handleFileUpload);
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=NeverBlufff/teambpc" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>