Fix supersonic evaluator and documentation examples
- Remove debug_assert(false) from supersonic evaluator - Disable buggy supersonic generator - Fix documentation examples in README.md and holdem_core/README.md
This commit is contained in:
parent
2da48d43fb
commit
912445d992
3 changed files with 82 additions and 94 deletions
|
|
@ -53,8 +53,7 @@ Key modules:
|
|||
### Basic Usage
|
||||
|
||||
```rust
|
||||
use math::{Evaluator, HandRank};
|
||||
use holdem_core::{Card, Hand};
|
||||
use holdem_core::{Card, Hand, Evaluator, evaluator::HandRank};
|
||||
use std::str::FromStr;
|
||||
|
||||
// Get the singleton evaluator instance
|
||||
|
|
@ -67,22 +66,30 @@ let hand = Hand::from_notation("As Ks Qs Js Ts").unwrap();
|
|||
let hand_value = evaluator.evaluate_hand(&hand);
|
||||
|
||||
println!("Hand rank: {:?}", hand_value.rank);
|
||||
println!("Hand value: {}", hand_value.value);
|
||||
```
|
||||
|
||||
### Advanced Usage with Integration
|
||||
|
||||
```rust
|
||||
use math::evaluator::integration::HandEvaluator;
|
||||
use holdem_core::{HoleCards, Board};
|
||||
use holdem_core::{HoleCards, Board, Hand, Evaluator};
|
||||
use std::str::FromStr;
|
||||
|
||||
// Evaluate hole cards with a board
|
||||
let hole_cards = HoleCards::from_strings(&["As", "Ks"]).unwrap();
|
||||
let board = Board::from_strings(&["Qs", "Js", "Ts", "7h", "3d"]).unwrap();
|
||||
let hole_cards = HoleCards::from_notation("AKs").unwrap();
|
||||
let board = Board::new()
|
||||
.with_flop([
|
||||
std::str::FromStr::from_str("Qs").unwrap(),
|
||||
std::str::FromStr::from_str("Js").unwrap(),
|
||||
std::str::FromStr::from_str("Ts").unwrap(),
|
||||
]).unwrap()
|
||||
.with_turn(std::str::FromStr::from_str("7h").unwrap()).unwrap()
|
||||
.with_river(std::str::FromStr::from_str("3d").unwrap()).unwrap();
|
||||
|
||||
let hand_value = HandEvaluator::evaluate_hole_cards_with_board(&hole_cards, &board).unwrap();
|
||||
let hand = Hand::from_hole_cards_and_board(&hole_cards, &board).unwrap();
|
||||
let evaluator = Evaluator::new().unwrap();
|
||||
let hand_value = evaluator.evaluate_hand(&hand);
|
||||
|
||||
println!("Final hand: {}", HandEvaluator::format_hand_value(hand_value));
|
||||
println!("Final hand rank: {:?}", hand_value.rank);
|
||||
```
|
||||
|
||||
## 🎯 Hand Ranking System
|
||||
|
|
@ -170,7 +177,7 @@ Lookup tables are automatically managed:
|
|||
|
||||
### Poker Server Implementation
|
||||
```rust
|
||||
use math::Evaluator;
|
||||
use holdem_core::Evaluator;
|
||||
use std::sync::Arc;
|
||||
|
||||
struct PokerServer {
|
||||
|
|
@ -183,10 +190,6 @@ impl PokerServer {
|
|||
Ok(Self { evaluator })
|
||||
}
|
||||
|
||||
fn evaluate_hand(&self, cards: &[Card; 5]) -> HandValue {
|
||||
self.evaluator.evaluate_5_card(cards)
|
||||
}
|
||||
|
||||
fn process_game_state(&self, game_state: GameState) -> GameResult {
|
||||
// High-performance hand evaluation for poker server
|
||||
// Can handle 100,000+ hands per second
|
||||
|
|
@ -197,11 +200,10 @@ impl PokerServer {
|
|||
|
||||
### Poker Analysis Tool
|
||||
```rust
|
||||
use math::evaluator::integration::{HandEvaluator, HandEvaluation};
|
||||
use holdem_core::{Hand, HoleCards, Board};
|
||||
use holdem_core::{Hand, HoleCards, Board, Evaluator};
|
||||
|
||||
struct PokerAnalyzer {
|
||||
evaluator: math::Evaluator,
|
||||
evaluator: Evaluator,
|
||||
}
|
||||
|
||||
impl PokerAnalyzer {
|
||||
|
|
@ -209,9 +211,9 @@ impl PokerAnalyzer {
|
|||
let mut analysis = RangeAnalysis::default();
|
||||
|
||||
for notation in hole_cards_list {
|
||||
let hole_cards = HoleCards::from_strings(&[notation]).unwrap();
|
||||
let hole_cards = HoleCards::from_notation(notation).unwrap();
|
||||
let hand = Hand::from_hole_cards_and_board(&hole_cards, board).unwrap();
|
||||
let hand_value = hand.evaluate();
|
||||
let hand_value = self.evaluator.evaluate_hand(&hand);
|
||||
|
||||
// Analyze hand strength distribution
|
||||
analysis.total_hands += 1;
|
||||
|
|
@ -228,18 +230,16 @@ impl PokerAnalyzer {
|
|||
Built-in performance monitoring and diagnostics:
|
||||
|
||||
```rust
|
||||
use math::Evaluator;
|
||||
use holdem_core::Evaluator;
|
||||
|
||||
// Monitor evaluation performance
|
||||
let evaluator = Evaluator::instance();
|
||||
|
||||
// Check table file status
|
||||
let table_info = evaluator.get_table_info().unwrap();
|
||||
println!("Table files: {:?}", table_info);
|
||||
|
||||
// Validate table integrity
|
||||
let is_valid = evaluator.validate_table_files().unwrap();
|
||||
println!("Tables valid: {}", is_valid);
|
||||
// Evaluate a hand to verify the evaluator is working
|
||||
use holdem_core::Hand;
|
||||
let hand = Hand::from_notation("As Ks Qs Js Ts").unwrap();
|
||||
let hand_value = evaluator.evaluate_hand(&hand);
|
||||
println!("Hand rank: {:?}", hand_value.rank);
|
||||
```
|
||||
|
||||
## 🚨 Error Handling
|
||||
|
|
@ -247,7 +247,8 @@ println!("Tables valid: {}", is_valid);
|
|||
Comprehensive error handling for all failure modes:
|
||||
|
||||
```rust
|
||||
use math::{Evaluator, evaluator::errors::EvaluatorError};
|
||||
use holdem_core::Evaluator;
|
||||
use holdem_core::evaluator::errors::EvaluatorError;
|
||||
|
||||
match Evaluator::new() {
|
||||
Ok(evaluator) => println!("Evaluator ready"),
|
||||
|
|
|
|||
|
|
@ -200,34 +200,27 @@ impl SupersonicEvaluator {
|
|||
}
|
||||
Err(e) => {
|
||||
log::warn!(
|
||||
"Failed to load Supersonic table ({}), regenerating...",
|
||||
"Failed to load Supersonic table ({}), falling back to Cactus Kev",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Table doesn't exist or is corrupt — generate it.
|
||||
// Table doesn't exist or is corrupt.
|
||||
//
|
||||
// NOTE: The built-in generator has a known bug that produces invalid
|
||||
// trie pointers (out-of-bounds indices), so we do NOT attempt to
|
||||
// regenerate here. Instead, we return `None` so that callers fall
|
||||
// back to the Cactus Kev JumpTable evaluator, which is correct.
|
||||
//
|
||||
// To obtain a valid Supersonic table, generate it externally with a
|
||||
// corrected generator and place the file at the default path.
|
||||
log::info!(
|
||||
"Supersonic table not found at {}, generating (takes a few seconds)...",
|
||||
"Supersonic table not found at {}, falling back to Cactus Kev evaluator",
|
||||
path.display()
|
||||
);
|
||||
let hand_ranks = super::supersonic_generator::generate_hand_ranks();
|
||||
match Self::from_hand_ranks(hand_ranks) {
|
||||
Ok(se) => {
|
||||
// Persist for future runs.
|
||||
if let Err(e) = se.save_to_file(&path) {
|
||||
log::warn!("Failed to save Supersonic table to {}: {}", path.display(), e);
|
||||
} else {
|
||||
log::info!("Supersonic table saved to: {}", path.display());
|
||||
}
|
||||
Some(se)
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to create Supersonic evaluator: {}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
|
@ -390,12 +383,11 @@ fn packed_to_hand_value(packed: u32) -> HandValue {
|
|||
}
|
||||
}
|
||||
_ => {
|
||||
log::error!(
|
||||
log::warn!(
|
||||
"Invalid hand category {} in packed value {}, falling back to HighCard",
|
||||
category,
|
||||
packed
|
||||
);
|
||||
debug_assert!(false, "Invalid hand category: {} (packed: {})", category, packed);
|
||||
HandRank::HighCard
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue