Skip to content

Commit

Permalink
initial version of preflop strategy manager
Browse files Browse the repository at this point in the history
  • Loading branch information
dickreuter committed Jan 21, 2024
1 parent 142f2ac commit d69361a
Show file tree
Hide file tree
Showing 8 changed files with 354 additions and 85 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/release win.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Binary Release Windows

on: [push, pull_request]
on:
workflow_dispatch:

jobs:
build:
Expand Down
8 changes: 4 additions & 4 deletions poker/tools/mongo_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
import requests
from PIL import Image
from fastapi.encoders import jsonable_encoder
from requests.exceptions import JSONDecodeError

from poker.tools.helper import COMPUTER_NAME, get_config, get_dir
from poker.tools.singleton import Singleton
from requests.exceptions import JSONDecodeError

TABLES_COLLECTION = 'tables'

Expand Down Expand Up @@ -78,11 +78,11 @@ def update_tensorflow_model(self, table_name: str, hdf5_file: bytes, model_str:

def load_table_nn_weights(self, table_name: str):
log.info("Downloading neural network weights for card recognition with tolerance...")
weights_str = requests.post(URL + "get_tensorflow_weights", params={'table_name': table_name}).json()
try:
weights_str = requests.post(URL + "get_tensorflow_weights", params={'table_name': table_name}).json()
weights = base64.b64decode(weights_str)
except TypeError:
log.error("No Trained Neural Network found. The cards need to be trained first.")
except Exception as e:
log.error(f"No Trained Neural Network found. The cards need to be trained first. {e}")
return

with open(get_dir('codebase') + '/loaded_model.h5', 'wb') as fh:
Expand Down
6 changes: 5 additions & 1 deletion website/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,8 @@
align-items: center;
justify-content: center;
padding: 2em;
}
}

.main-content {
margin-top: 90px; /* Adjust this value based on your navbar's height */
}
23 changes: 11 additions & 12 deletions website/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import ReactGA from 'react-ga'
import { BrowserRouter } from "react-router-dom"
import './App.css'
import NavBar from './routes/NavBar'
import Routing from "./routes/Routing"
import { useEffect } from 'react'

import ReactGA from "react-ga";
import { BrowserRouter } from "react-router-dom";
import "./App.css";
import NavBar from "./routes/NavBar";
import Routing from "./routes/Routing";
import { useEffect } from "react";

const TRACKING_ID = "UA-7794836-7"; // OUR_TRACKING_ID
ReactGA.initialize(TRACKING_ID);


function App() {

useEffect(() => {
ReactGA.pageview(window.location.pathname + window.location.search);
}, []);
Expand All @@ -20,10 +17,12 @@ function App() {
<>
<BrowserRouter>
<NavBar />
<Routing />
<div className="main-content">
<Routing />
</div>
</BrowserRouter>
</>
)
);
}

export default App
export default App;
248 changes: 248 additions & 0 deletions website/src/components/strategy_editor/PreFlopStrategy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
import axios from "axios";
import React, { useEffect, useState } from "react";
import { API_URL } from "../../views/config";

// Subcomponent for each hand scenario row
const HandScenarioRow = ({
hand,
scenario,
position,
strategies,
onStrategyChange,
}) => {
const [call, setCall] = useState(0);
const [raise, setRaise] = useState(0);

// Update call and raise when strategies or position changes
useEffect(() => {
const posStrategy = strategies[position]?.[hand]?.[scenario];
setCall(posStrategy?.call || 0);
setRaise(posStrategy?.raise || 0);
}, [hand, scenario, position, strategies]);

const handleCallChange = (e) => {
const newCall = Math.max(
0,
Math.min(100, parseInt(e.target.value, 10) || 0)
);
onStrategyChange(hand, scenario, newCall, raise);
};

const handleRaiseChange = (e) => {
const newRaise = Math.max(
0,
Math.min(100, parseInt(e.target.value, 10) || 0)
);
onStrategyChange(hand, scenario, call, newRaise);
};

const fold = 100 - call - raise;

return (
<>
<td>
<input
type="number"
value={call}
onChange={handleCallChange}
min="0"
max="100"
/>
%
</td>
<td>
<input
type="number"
value={raise}
onChange={handleRaiseChange}
min="0"
max="100"
/>
%
</td>
<td>{`${fold}%`}</td>
</>
);
};

// Main component
const PreFlopStrategyEditor = () => {
const [position, setPosition] = useState("0");
const [strategies, setStrategies] = useState({});

useEffect(() => {
const fetchPreflopValues = async () => {
try {
const response = await axios.get(
`${API_URL}/get_preflop_values/default`
);
setStrategies(response.data.preflop_values || {});
} catch (error) {
console.error("Error fetching preflop values:", error);
// Handle the error
}
};

fetchPreflopValues();
}, []);

const handleStrategyChange = (hand, scenario, call, raise) => {
setStrategies((prevStrategies) => ({
...prevStrategies,
[position]: {
...prevStrategies[position],
[hand]: {
...prevStrategies[position]?.[hand],
[scenario]: { call, raise },
},
},
}));
};

const handlePositionChange = (e) => {
setPosition(e.target.value);
};

// Function to save all strategies for all positions
const saveStrategy = async () => {
try {
const response = await axios.post(`${API_URL}/save_preflop_values`, {
table_name: "default", // This could be a dynamic name based on your application logic
preflop_values: strategies, // Sending the entire strategies object
});

if (response.data.message) {
console.log(response.data.message);
// Optionally, display a success message to the user
}
} catch (error) {
console.error("Error saving preflop values:", error);
// Optionally, display an error message to the user
}
};

const scenarios = ["noCalls", "previousCalls", "previousRaises"];
const hands = [
"AA",
"KK",
"QQ",
"JJ",
"TT",
"99",
"88",
"77",
"66",
"55",
"44",
"33",
"22",
"AKs",
"AQs",
"AJs",
"ATs",
"A9s",
"A8s",
"A7s",
"A6s",
"A5s",
"A4s",
"A3s",
"A2s",
"KQs",
"KJs",
"KTs",
"K9s",
"K8s",
"K7s",
"K6s",
"K5s",
"K4s",
"K3s",
"QJs",
"QTs",
"Q9s",
"JTs",
"J9s",
"J8s",
"T9s",
"T8s",
"T7s",
"98s",
"97s",
"96s",
"87s",
"86s",
"85s",
"76s",
"75s",
"74s",
"65s",
"64s",
"63s",
"54s",
"53s",
"52s",
"43s",
"42s",
"AKo",
"AJo",
"ATo",
"KQo",
"KJo",
"QJo",
];

return (
<div>
<label>
Position:
<select value={position} onChange={handlePositionChange}>
{Array.from({ length: 10 }, (_, i) => (
<option key={i} value={String(i)}>
{i}
</option>
))}
</select>
</label>
<button onClick={saveStrategy}>Save</button>
<table>
<thead>
<tr>
<th>Hand</th>
<th colSpan="3">No calls or raises</th> {/* Colspan of 3 for the scenario grouping */}
<th colSpan="3">1 or more calls</th> {/* Colspan of 3 for the scenario grouping */}
<th colSpan="3">1 or more raises</th> {/* Colspan of 3 for the scenario grouping */}
</tr>
<tr>
{scenarios.map((scenario) => (
<React.Fragment key={scenario}>
<th>Call</th>
<th>Raise</th>
<th>Fold</th>
</React.Fragment>
))}
</tr>
</thead>
<tbody>
{hands.map((hand) => (
<tr key={hand}>
<td>{hand}</td>
{scenarios.map((scenario) => (
<HandScenarioRow
key={`${hand}-${scenario}`}
hand={hand}
scenario={scenario}
position={position}
strategies={strategies}
onStrategyChange={handleStrategyChange}
/>
))}
</tr>
))}
</tbody>
</table>
</div>
);
};

export default PreFlopStrategyEditor;
Loading

0 comments on commit d69361a

Please sign in to comment.