id: 7a1820ec617d4ce5a58d7e736d4431aa
parent_id: 
item_type: 1
item_id: e69e6d992244485d9dacb5fdb3503a28
item_updated_time: 1780221450010
title_diff: "[{\"diffs\":[[1,\"Meerkat API Extension\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":21}]"
body_diff: "[{\"diffs\":[[1,\"# Meerkat API Extension\\\n\\\n## Wrapper Layer\\\n\\\nCreate a Rust-based wrapper around the Meerkat API.\\\n\\\nThis wrapper intercepts game state updates and allows the bot to make decisions before its turn.\\\n\\\n## Preemptive Action Queue\\\n\\\nImplement a queue for preemptive actions (e.g., fold immediately).\\\n\\\nWhen the game state updates, the wrapper checks the queue and submits actions if applicable.\\\n\\\n## Event-Driven Architecture\\\n\\\nUse an event-driven design to monitor game state changes (e.g., new cards dealt, opponent actions).\\\n\\\nTrigger bot decision-making logic based on these events.\\\n\\\n### Example Workflow\\\nThe bot receives a game state update (e.g., new cards dealt).\\\n\\\nThe wrapper checks if the bot has queued a preemptive action (e.g., fold).\\\n\\\nIf a preemptive action exists, the wrapper submits it to the Meerkat API.\\\n\\\nIf no preemptive action exists, the bot waits for its turn and acts normally.\\\n\\\n## Rust Implementation\\\n\\\n`struct MeerkatWrapper {\\\n    meerkat_api: MeerkatAPI,\\\n    preemptive_action: Option<Action>,\\\n}\\\n\\\nimpl MeerkatWrapper {\\\n    fn new(api: MeerkatAPI) -> Self {\\\n        Self {\\\n            meerkat_api: api,\\\n            preemptive_action: None,\\\n        }\\\n    }\\\n\\\n    fn queue_preemptive_action(&mut self, action: Action) {\\\n        self.preemptive_action = Some(action);\\\n    }\\\n\\\n    fn on_game_state_update(&mut self, state: GameState) {\\\n        if let Some(action) = self.preemptive_action.take() {\\\n            self.meerkat_api.submit_action(action);\\\n        } else {\\\n            // Normal turn-based logic\\\n            let decision = self.bot.make_decision(&state);\\\n            self.meerkat_api.submit_action(decision);\\\n        }\\\n    }\\\n}`\\\n\\\n`#[derive(Clone, Debug)]\\\npub enum Action {\\\n    Fold,\\\n    Call,\\\n    Raise(f64),\\\n}\\\n\\\npub struct MeerkatBot {\\\n    preemptive_action: Option<Action>,\\\n}\\\n\\\nimpl MeerkatBot {\\\n    pub fn new() -> Self {\\\n        Self {\\\n            preemptive_action: None,\\\n        }\\\n    }\\\n\\\n    pub fn queue_preemptive_action(&mut self, action: Action) {\\\n        self.preemptive_action = Some(action);\\\n    }\\\n\\\n    pub fn on_game_state_update(&mut self, game_info: GameInfo) -> Option<Action> {\\\n        if let Some(action) = self.preemptive_action.take() {\\\n            // Submit the preemptive action if it's the bot's turn\\\n            if game_info.current_player == self.player_id() {\\\n                return Some(action);\\\n            }\\\n        }\\\n\\\n        // Default decision-making logic\\\n        self.make_decision(&game_info)\\\n    }\\\n\\\n    fn player_id(&self) -> u32 {\\\n        // Return the bot's player ID\\\n        1 // Example\\\n    }\\\n\\\n    fn make_decision(&self, game_info: &GameInfo) -> Option<Action> {\\\n        // Implement decision-making logic here\\\n        None\\\n    }\\\n}`\\\n\\\n`fn main() {\\\n    let mut bot = MeerkatBot::new();\\\n\\\n    // Queue a preemptive action (e.g., fold immediately)\\\n    bot.queue_preemptive_action(Action::Fold);\\\n\\\n    // Simulate a game state update\\\n    let game_info = GameInfo {\\\n        table_info: TableInfo {\\\n            table_id: 1,\\\n            table_size: 6,\\\n            blinds: (1.0, 2.0),\\\n            players: vec![\\\n                PlayerInfo {\\\n                    id: 1,\\\n                    stack: 100.0,\\\n                    position: Position::Button,\\\n                    statistics: PlayerStatistics::default(),\\\n                },\\\n                // Add other players...\\\n            ],\\\n        },\\\n        game_state: GameState {\\\n            community_cards: vec![],\\\n            pot_size: 3.0,\\\n            current_bet: 2.0,\\\n            active_players: vec![1, 2, 3],\\\n        },\\\n        hand_id: 12345,\\\n        current_player: 1, // Bot's turn\\\n    };\\\n\\\n    // Handle the game state update\\\n    if let Some(action) = bot.on_game_state_update(game_info) {\\\n        println!(\\\"Bot action: {:?}\\\", action);\\\n    }\\\n}`\\\n\\\n## Representing Cards\\\nA standard deck has 52 cards, which can be represented using a single byte (u8). Each card can be encoded as follows:\\\n\\\n4 bits for the rank (2, 3, 4, ..., Ace).\\\n\\\n2 bits for the suit (Clubs, Diamonds, Hearts, Spades).\\\n\\\n### Card Encoding\\\n\\\n`#[derive(Debug, Clone, Copy, PartialEq, Eq)]\\\npub struct Card(u8);\\\n\\\nimpl Card {\\\n    pub const RANK_MASK: u8 = 0b1111; // 4 bits for rank\\\n    pub const SUIT_MASK: u8 = 0b110000; // 2 bits for suit\\\n\\\n    pub fn new(rank: u8, suit: u8) -> Self {\\\n        assert!(rank <= 13, \\\"Rank must be between 2 and 14 (Ace)\\\");\\\n        assert!(suit <= 3, \\\"Suit must be between 0 and 3\\\");\\\n        Self((suit << 4) | (rank & Self::RANK_MASK))\\\n    }\\\n\\\n    pub fn rank(&self) -> u8 {\\\n        self.0 & Self::RANK_MASK\\\n    }\\\n\\\n    pub fn suit(&self) -> u8 {\\\n        (self.0 & Self::SUIT_MASK) >> 4\\\n    }\\\n}`\\\n\\\n### Example Usage\\\n\\\n`let ace_of_spades = Card::new(14, 3); // Rank 14 (Ace), Suit 3 (Spades)\\\nprintln!(\\\"Rank: {}, Suit: {}\\\", ace_of_spades.rank(), ace_of_spades.suit());`\\\n\\\n## Representing Hands\\\nA hand consists of 2 cards (in Texas Hold'em). We can represent it as a tuple of two Card instances or as a single u16 for compactness.\\\n\\\n### Hand Representation\\\n\\\n`#[derive(Debug, Clone, Copy, PartialEq, Eq)]\\\npub struct Hand(Card, Card);\\\n\\\nimpl Hand {\\\n    pub fn new(card1: Card, card2: Card) -> Self {\\\n        Self(card1, card2)\\\n    }\\\n}`\\\n\\\n### Example Usage\\\n\\\n`let hand = Hand::new(Card::new(14, 3), Card::new(13, 2)); // Ace of Spades and King of Hearts`\\\n\\\n## Representing the Board\\\nThe board consists of up to 5 community cards (flop, turn, river). We can represent it as a fixed-size array of Card instances.\\\n\\\n### Board Representation\\\n\\\n`#[derive(Debug, Clone, PartialEq, Eq)]\\\npub struct Board([Option<Card>; 5]);\\\n\\\nimpl Board {\\\n    pub fn new() -> Self {\\\n        Self([None; 5])\\\n    }\\\n\\\n    pub fn add_card(&mut self, card: Card) -> Result<(), &'static str> {\\\n        for slot in self.0.iter_mut() {\\\n            if slot.is_none() {\\\n                *slot = Some(card);\\\n                return Ok(());\\\n            }\\\n        }\\\n        Err(\\\"Board is full\\\")\\\n    }\\\n}`\\\n\\\n### Example Usage\\\n\\\n`let mut board = Board::new();\\\nboard.add_card(Card::new(10, 0)).unwrap(); // 10 of Clubs\\\nboard.add_card(Card::new(9, 1)).unwrap(); // 9 of Diamonds\\\nprintln!(\\\"{:?}\\\", board);`\\\n\\\n## Integrating with the Meerkat API\\\nThe Meerkat API likely expects specific data structures for cards, hands, and the board. We can create conversion methods to map our efficient representations to the Meerkat API's format.\\\n\\\n### Conversion Methods\\\n\\\n`impl Card {\\\n    pub fn to_meerkat_format(&self) -> String {\\\n        let rank = match self.rank() {\\\n            2..=10 => self.rank().to_string(),\\\n            11 => \\\"J\\\".to_string(),\\\n            12 => \\\"Q\\\".to_string(),\\\n            13 => \\\"K\\\".to_string(),\\\n            14 => \\\"A\\\".to_string(),\\\n            _ => panic!(\\\"Invalid rank\\\"),\\\n        };\\\n        let suit = match self.suit() {\\\n            0 => \\\"C\\\", // Clubs\\\n            1 => \\\"D\\\", // Diamonds\\\n            2 => \\\"H\\\", // Hearts\\\n            3 => \\\"S\\\", // Spades\\\n            _ => panic!(\\\"Invalid suit\\\"),\\\n        };\\\n        format!(\\\"{}{}\\\", rank, suit)\\\n    }\\\n}\\\n\\\nimpl Hand {\\\n    pub fn to_meerkat_format(&self) -> (String, String) {\\\n        (self.0.to_meerkat_format(), self.1.to_meerkat_format())\\\n    }\\\n}\\\n\\\nimpl Board {\\\n    pub fn to_meerkat_format(&self) -> Vec<String> {\\\n        self.0.iter()\\\n            .filter_map(|card| card.as_ref().map(|c| c.to_meerkat_format()))\\\n            .collect()\\\n    }\\\n}`\\\n\\\n### Example Usage\\\n\\\n`let card = Card::new(14, 3); // Ace of Spades\\\nprintln!(\\\"Meerkat format: {}\\\", card.to_meerkat_format()); // Output: \\\"AS\\\"\\\n\\\nlet hand = Hand::new(Card::new(14, 3), Card::new(13, 2)); // Ace of Spades and King of Hearts\\\nprintln!(\\\"Meerkat format: {:?}\\\", hand.to_meerkat_format()); // Output: (\\\"AS\\\", \\\"KH\\\")\\\n\\\nlet mut board = Board::new();\\\nboard.add_card(Card::new(10, 0)).unwrap(); // 10 of Clubs\\\nboard.add_card(Card::new(9, 1)).unwrap(); // 9 of Diamonds\\\nprintln!(\\\"Meerkat format: {:?}\\\", board.to_meerkat_format()); // Output: [\\\"10C\\\", \\\"9D\\\"]`\\\n\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":7780}]"
metadata_diff: {"new":{"id":"e69e6d992244485d9dacb5fdb3503a28","parent_id":"2508f7a375a148eaa747c8f5c2147160","latitude":"48.20817430","longitude":"16.37381890","altitude":"0.0000","author":"","source_url":"","is_todo":0,"todo_due":0,"todo_completed":0,"source":"joplin-desktop","source_application":"net.cozic.joplin-desktop","application_data":"","order":0,"user_updated_time":1739426319815,"markup_language":1,"is_shared":0,"share_id":"","conflict_original_id":"","master_key_id":"","user_data":"","deleted_time":1780221450010},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-05-31T10:06:29.053Z
created_time: 2026-05-31T10:06:29.053Z
type_: 13