惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
WordPress大学
WordPress大学
Vercel News
Vercel News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
小众软件
小众软件
L
LangChain Blog
雷峰网
雷峰网
D
DataBreaches.Net
博客园 - 三生石上(FineUI控件)
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tor Project blog
NISL@THU
NISL@THU
Scott Helme
Scott Helme
量子位
S
Security Affairs
T
Threat Research - Cisco Blogs
博客园_首页
云风的 BLOG
云风的 BLOG
D
Docker
AWS News Blog
AWS News Blog
腾讯CDC
博客园 - 聂微东
The GitHub Blog
The GitHub Blog
U
Unit 42
Recent Announcements
Recent Announcements
Apple Machine Learning Research
Apple Machine Learning Research
G
Google Developers Blog
T
The Exploit Database - CXSecurity.com
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
L
LINUX DO - 热门话题
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The Last Watchdog
The Last Watchdog
C
Cybersecurity and Infrastructure Security Agency CISA
IT之家
IT之家
W
WeLiveSecurity
P
Privacy & Cybersecurity Law Blog
F
Full Disclosure
L
Lohrmann on Cybersecurity
The Hacker News
The Hacker News
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Y
Y Combinator Blog
S
Security @ Cisco Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Check Point Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
N
News and Events Feed by Topic
PCI Perspectives
PCI Perspectives
I
InfoQ

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Before the Algorithm: Building the Input Layer for My Poker Analysis Tool
ty215 · 2026-06-28 · via DEV Community

In my first post about this project I described repeated-poker-analysis: a small, abstract toolkit for studying repeated poker spots as a commitment-analysis problem. It is a research and learning project, not a poker solver and not real-money advice.

That post ended on the analysis side, with a hand-built toy game where committing to a fixed strategy beats the one-shot baseline. I planned to spend the next stretch on the algorithm. In practice I spent most of it on input, validation, and saving — the layer the algorithm sits on. This post is about that part, and about the abstract model growing a bit at the same time.

This describes the project on the feat/single-hand-form-edit-cli branch at the time of writing, so details may move after it is merged.

What changed since the last post

Last time, scenarios were small fixed examples and helper functions inside the code. To analyze anything new, I edited Python.

Two things changed. First, a scenario is now a JSON file: the tool reads it, checks it, builds the abstract game, runs the existing analysis pipeline, and can export the result. Second, the abstract model itself widened — I added more scenario modes, so the JSON can describe slightly richer hand and action structure than the single toy spot from the first post.

So this wasn't a stretch with no model work. It was widening the abstract model and the input formats together, while keeping both small enough to check.

Why the input layer came first

Analysis output is only as trustworthy as its input. If a scenario is silently malformed — a probability that doesn't sum to one, a missing matrix cell — then any EV or deadline the tool reports is meaningless, and I might not notice.

So before making the analysis bigger, I wanted the input to fail loudly when it's wrong instead of quietly producing a plausible-looking number. That meant firming up the input and validation layer first, even though it isn't the part I was looking forward to.

What a JSON scenario is

A scenario is a JSON description of one small abstract river spot: the pot and bet sizes, the rake rule, how showdowns resolve, a baseline strategy, and the repeated-game parameters. JSON is the source of truth — every other representation in the tool is derived from it and checked back against it.

Reading one through the current loader looks like this:

JSON scenario
 -> detect mode
 -> parse + build the abstract game
 -> (analysis pipeline, if requested)

The JSON is parsed and built into the actual game object before anything trusts it, so a broken scenario is rejected at the door.

The five scenario modes

I added the modes in order, each one allowing a little more abstract structure than the last:

  1. single-hand — one abstract hand bucket. Check/bet for one player, call/fold for the other. This is the mode the first post's toy game used.
  2. Hero-range-only — several Hero buckets with weights; the opponent still acts on a single information set.
  3. showdown-matrix — Hero and Villain buckets, with each matchup's result given directly as hero / villain / chop.
  4. equity-matrix — the same grid, but each cell is a Hero pot share between 0 and 1 instead of a discrete result. These numbers are supplied in the JSON; the tool does not evaluate real cards or compute equity.
  5. river betting-tree — one street with a few more actions: an IP stab after an OOP check, and a single IP raise line against an OOP bet. It's still a fixed one-street tree, with no re-raises, nested sizings, or street transitions.

The abstraction level is still high. There's no real card-range parsing, no real card evaluation, no external solver import, no solver-grade GTO calculation, no multiple streets, and no arbitrary nested betting trees.

I split this into five modes on purpose. The goal wasn't to make the model large quickly — it was to keep each step small enough that when something broke, I could tell which stage and which input shape caused it. So the model and input formats grew incrementally, but there's still groundwork to do before any of this becomes realistic analysis.

Why I built form models before the GUI

I want a GUI eventually, so editing a scenario doesn't mean hand-writing JSON. But before building any screens, I built a form model for each of the five modes.

A form model is a flat, edit-friendly representation of a scenario — the shape a GUI form would bind to. It doesn't replace the JSON; the JSON stays the source of truth. The form model just gives a future screen something convenient to read from and write to.

Two design choices mattered here:

  • The validator returns field-level messages instead of throwing. While editing, a form is often temporarily broken — a probability that doesn't sum to one yet, a half-typed value — and a GUI needs to show that next to the field rather than crash.
  • Invalid values are not quietly rounded to valid ones. If a field is wrong, it's surfaced as an error before saving, not silently "fixed." A scenario that passes validation is one that round-trips back through the parser and builder.

Building the form models for all five modes first let me check the data structures behind the screens before committing to any screen.

What the inspect / roundtrip / edit CLIs check

To confirm the form layer works without a GUI, there are three small developer-utility CLIs. They aren't user features; they're how I check the plumbing.

  • inspect_scenario_form.py reads a scenario through its form model, detects the mode, runs validation, and confirms it round-trips back through the parser and builder. It's a health check for the input layer.
  • roundtrip_scenario_form.py reads a scenario, runs it through the form model, and writes it back out — only if validation and the round-trip succeed. This is close to what a GUI "save" will eventually do.
  • edit_scenario_form.py reads a scenario, edits a few fields, validates, and saves. It's the minimal version of "change a field and save it," and for now it's single-hand only.

Inspecting the first post's toy game looks like this:

$ python scripts/inspect_scenario_form.py examples/scenarios/nuts_chop_steal_bet98.json
Scenario form inspection
scenario_id: nuts_chop_steal_bet98
mode: single-hand
form: SingleHandScenarioForm
validation: ok
round_trip_parse: ok
round_trip_build: ok

It's a boring output, which is what I wanted: it confirms the read → validate → round-trip path holds before I build a screen on top of it.

Working with AI as the codebase grew

I'm building this with AI assistance, and how I work with it changed as the code grew.

I went into this stretch expecting to get a lot done over a weekend. To keep quality up, though, I started having the assistant explain code back to me, adding more tests, and running a review pass before moving on. That slowed feature work down, and the stretch ended at the form layer rather than further along.

I don't think that was bad stalling. It's the scaffold I'll need to trust the analysis and the GUI later. The cost is that explaining, testing, and reviewing as I go uses far more tokens and takes longer than just generating code. It's still clearly faster than doing all of this alone from scratch — but on a project this size, the trade-off is something I now weigh.

Tests and verification

There are now over 1,000 tests. I want to be careful about what that means: it does not mean I'm verifying a large poker solver. It means I've accumulated checks on a small abstract model, its input/output paths, and boundary conditions — for example, that all five modes parse, that a CLI writes JSON and nothing else, that it won't overwrite a file unless told to, and that it writes nothing when validation fails.

That kind of check is most of the test count. It buys confidence in the plumbing, not in any real-world poker claim.

The harder question is still open: as the project grows, the amount I'd need to verify grows faster than I can read. I haven't solved that. I expect I'll have to validate from the outside — design the checks to be as exhaustive as I can and run many configurations — rather than reading every line.

Current limitations

At this stage the tool is still a small abstract toolkit. In particular, it does not have:

  • a real card-range parser or real hand evaluation,
  • any external solver import or solver-grade GTO output,
  • an arbitrary game-tree editor, multiple streets, or re-raise / multi-sizing / nested betting trees,
  • a GUI yet, or edit CLIs for the range / matrix / betting-tree modes (edit is single-hand only),
  • anything resembling real-money strategy advice, or any model of human learning speed or psychology.

The EV numbers it produces are outputs of a deliberately small model, not poker advice.

What I want to do next

The near-term goal is to make the tool easier to run and watch — to get from "abstract model that passes its checks" to "I can load a scenario, change it, and see the result" without editing Python.

Concretely, that means extending the edit flow beyond single-hand, and eventually a minimal GUI on top of the form models that are already in place. Alongside that, I still want to work out the verification approach for when the model grows, since that's the part I don't have a good answer for yet.

This stretch was mostly groundwork. It's not the part I was looking forward to, but the algorithm work I do want to do will be easier to trust because of it.

Links