89 lines
4.0 KiB
Markdown
89 lines
4.0 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## Project Purpose
|
||
|
||
Poker analysis tool for GGPoker using a Logitech StreamCam pointed at a 2560×1440 monitor. Captures the game via webcam, reads cards via OCR and color detection, calculates equity via Monte Carlo simulation.
|
||
|
||
## Running the Scripts
|
||
|
||
```bash
|
||
# Live camera viewer with settings panel (trackbars)
|
||
python3 main.py
|
||
|
||
# Poker analyzer — board OCR + Monte Carlo equity
|
||
python3 analyzer.py # auto OCR hero cards
|
||
python3 analyzer.py Qd Qc # manually specify hero cards (rank+suit)
|
||
|
||
# Webcam scraper using dickreuter_poker backend
|
||
python3 webcam_scraper.py
|
||
```
|
||
|
||
## Architecture
|
||
|
||
```
|
||
main.py — Camera viewer with OpenCV trackbars. Loads/saves settings.json.
|
||
analyzer.py — Main analysis pipeline: webcam → crop → OCR → Monte Carlo → advice.
|
||
webcam_scraper.py — Adapter connecting webcam to dickreuter_poker TableScraper.
|
||
virtualbox/ — Stub module: dickreuter_poker imports virtualbox which isn't needed.
|
||
files/ — Card sprite sheet (table_card.png + card.json) for future template matching.
|
||
settings.json — Persisted camera settings (auto-tuned, do not edit manually).
|
||
tmp/ — All temporary files, snapshots, debug images go here.
|
||
```
|
||
|
||
### External dependency: dickreuter_poker
|
||
Located at `/home/isaevea/python/dickreuter_poker`. Added to `sys.path` at runtime.
|
||
- `poker.decisionmaker.montecarlo_numpy2.Evaluation` — Monte Carlo equity calculator (CPU/numpy, no GPU).
|
||
- `poker.scraper.table_scraper.TableScraper` — Table state scraper (card templates from `https://dickreuter.com:7778/`).
|
||
- `poker.tools.mongo_manager.MongoManager` — Fetches GGPoker table config from remote API. Table name: `"Official GGPoker 6player"`.
|
||
|
||
GUI modules of dickreuter_poker (PyQt6) are stubbed out in `webcam_scraper.py` via `sys.modules` injection.
|
||
|
||
## Camera Hardware
|
||
|
||
- **Device**: Logitech StreamCam → `/dev/video2` (index 2). `/dev/video0` is UVC Camera.
|
||
- **Optimal settings** (auto-tuned, saved in `settings.json`): focus=60 (manual), sharpness=192, exposure=500 (manual).
|
||
- Qt font issue fix: Liberation Sans fonts copied to `.venv/lib/python3.12/site-packages/cv2/qt/fonts/`.
|
||
- Window titles must be ASCII-only — Cyrillic in `cv2.namedWindow()` causes NULL pointer crash. Trackbar labels support Cyrillic.
|
||
|
||
## Webcam Coordinate System
|
||
|
||
All coordinate constants in `analyzer.py` are in the **1280×720 webcam frame**:
|
||
|
||
```python
|
||
BOARD_AREA = (220, 370, 330, 640) # y1,y2,x1,x2 — entire flop/turn/river area
|
||
HERO_L_AREA = (438, 478, 472, 530) # left hole card
|
||
HERO_R_AREA = (438, 478, 530, 585) # right hole card
|
||
```
|
||
|
||
These are camera-position-dependent. If camera moves, recalibrate by running a snapshot and checking `tmp/` images.
|
||
|
||
In `webcam_scraper.py`, the GGPoker window boundary:
|
||
```python
|
||
TABLE_X1, TABLE_Y1 = 15, 55
|
||
TABLE_X2, TABLE_Y2 = 760, 685
|
||
```
|
||
This crops the GGPoker client from the webcam frame and scales to 1500×1100 (dickreuter's `CROP_WIDTH × CROP_HEIGHT`).
|
||
|
||
## Card Detection
|
||
|
||
**Board cards** (`read_board_cards`): BOARD_AREA is divided into 3 equal columns. Top-left corner of each is OCR'd via Tesseract (`tessedit_char_whitelist=23456789TJQKA`). Suit detected by mean red channel (>100 → hearts/diamonds, else spades).
|
||
|
||
**Hero cards** (`read_hero_cards`): Color-based suit detection in HSV space — blue hue → ♦, green → ♣, red → ♥, dark → ♠. GGPoker uses emoji-style colored card backgrounds.
|
||
|
||
**Tessdata path**: `/home/isaevea/python/dickreuter_poker/tessdata/`
|
||
|
||
## Monte Carlo Card Format
|
||
|
||
`montecarlo_numpy2.Evaluation.run_evaluation(card1, card2, tablecards, iterations, player_amount)`
|
||
|
||
Cards encoded as `[rank, suit]` where rank: 2–14 (A=14), suit: 0=clubs, 1=diamonds, 2=hearts, 3=spades.
|
||
|
||
```python
|
||
RANK_MAP = {'2':2,...,'T':10,'J':11,'Q':12,'K':13,'A':14}
|
||
SUIT_MAP = {'c':0,'d':1,'h':2,'s':3}
|
||
```
|
||
|
||
Returns float equity (0.0–1.0). Typical: >0.65 → raise, >0.45 → call, <0.25 → fold.
|