Advertisement

← poker-tutor

Sources/PokerUI/Basics.swift

38.6 KB Download file
import Foundation
import PokerCoach

/// The things people who have played for years assume everyone knows.
///
/// Ken, 2026-08-02: "One area that I don't get is how to determine the size of the bet." That is
/// the first lesson, and it is the one that costs the most to not know — but it is not alone. A
/// table full of people who learned this by osmosis will never say any of it out loud, and the app
/// was quietly assuming it too: the coach can tell somebody they bet too much without ever having
/// told them what "too much" is measured against.
///
/// Rules these follow, which are the reason they are data rather than a wall of text in a view:
///
/// - Every lesson answers a question somebody would actually ask, in the words they would ask it.
/// - Every rule of thumb comes with the numbers worked through, because "bet two-thirds of the pot"
///   means nothing to somebody who has never seen it done with real chips on the table.
/// - Nothing here is presented as the truth. These are the defaults a competent player starts from
///   and then departs from with a reason, and each one says so — teaching them as laws would make
///   somebody worse the moment they met a spot the law does not cover.
/// - Plain English throughout. Where a word is unavoidable it is one the glossary defines, so the
///   suite catches it if the two ever drift apart.
public struct BasicLesson: Identifiable, Sendable, Equatable {
    public let id: String
    /// What somebody would actually ask. Shown as the lesson's title.
    public let question: String
    /// The answer in one sentence, before any of the reasoning.
    public let short: String
    /// The reasoning, a paragraph at a time.
    public let paragraphs: [String]
    /// The numbers worked through, where a rule of thumb needs them to mean anything.
    public let worked: String?
    /// The habit whose drill puts somebody in this exact spot, over and over, so the lesson can be
    /// practised rather than only read. Nothing new is built for it: the drills already deal an
    /// arranged table aimed at one situation, and these concepts ARE those situations seen from the
    /// other end — "how much do I raise" and "raising too little" are the same hands.
    ///
    /// Nil where honest practice is not possible yet. Reading how big a raise should be is worth
    /// something on its own; a button that promised practice and dealt ordinary hands would not be.
    public let practises: String?

    public init(id: String, question: String, short: String,
                paragraphs: [String], worked: String? = nil, practises: String? = nil) {
        self.id = id
        self.question = question
        self.short = short
        self.paragraphs = paragraphs
        self.worked = worked
        self.practises = practises
    }

    /// Everything the lesson says, for the sweeps that read the app's writing.
    public var allText: [String] { [question, short] + paragraphs + (worked.map { [$0] } ?? []) }
}

public enum Basics {

    /// The course for the game this product plays.
    public static var lessons: [BasicLesson] { lessons(for: LeakCatalogue.format) }

    public static func lessons(for format: CoachFormat) -> [BasicLesson] {
        switch format {
        case .tournament: return tournamentLessons
        case .cash: return cashLessons
        case .limit: return limitLessons
        }
    }

    /// The fixed-limit course: the cash course with the three no-limit lessons — the money behind,
    /// one pair and a stack, re-raised pots — replaced by the four things that are true only when
    /// a bet has one size. Each practises a limit habit.
    public static let limitLessons: [BasicLesson] =
        cashLessons.filter { !["money-behind", "one-pair-stack", "re-raised-pots",
                               // A limit bet has one size, so the three lessons about choosing one
                               // have nothing to teach here; `limit-two-bets` says what an open is.
                               "bet-size", "same-size", "open-size"].contains($0.id) } + [

        BasicLesson(
            id: "limit-price",
            question: "Why does everybody call so much at a limit table?",
            short: "Because a bet is a fraction of the pot, so a hand with cards to come nearly "
                 + "always has the price to see the next one.",
            paragraphs: [
                "At a limit table a bet has one size, and by the time somebody bets the flop the "
                + "pot already holds several of them. So the question a call asks is small: with "
                + "eight cards that make your hand — the two ends of a straight, or a flush draw — "
                + "you will get there about one time in three by the river, and the pot is offering "
                + "far better than that on every street.",

                "That is why the expensive mistakes at limit are folds, not calls. A draw let go for "
                + "one small bet on the flop gives up a pot you would have won often enough to pay "
                + "for every call you ever made with it. Even four cards to come — an inside "
                + "straight — is worth one bet when the pot is big.",

                "The rule: count the bets in the pot, count the cards that make your hand, and "
                + "fold a draw only when the pot is small and the cards are few. Both at once, or "
                + "keep going.",
            ],
            worked: "Blinds 50 and 100, so a bet is 100 on the flop. Four of you saw the flop for "
                  + "one bet each, and the flop gives you a flush draw. Somebody bets 100.\n\n"
                  + "The pot is 500 before your call. You pay 100 to win 500 — one in six, so you "
                  + "need to be right about 17% of the time. Nine cards make your flush, which "
                  + "is about 19% on the very next card and about 35% by the river. This is a "
                  + "call every time. With half the outs it is close on the next card alone and "
                  + "still right by the river.",
            practises: "limit-fold-to-price"),

        BasicLesson(
            id: "limit-raise",
            question: "If a raise never makes anybody fold, why raise at all?",
            short: "Because with the best hand every extra bet is paid by worse hands that were "
                 + "calling anyway — and last to act, a raise on the flop buys the turn card for free.",
            paragraphs: [
                "At no-limit a raise can win the pot on the spot. At limit it almost never does, "
                + "and that is exactly why it is worth making: the raise goes in against hands that "
                + "are not folding, so with the best hand you are paid two bets instead of one by "
                + "everybody who calls. Calling along with a hand that is likely best collects "
                + "half of what it should, and over a session that is most of the winnings.",

                "The other raise is the free card. Last to act on the flop with a real draw, raise "
                + "one small bet. About half the time everybody checks to you on the turn, where the "
                + "bet is twice the size — and then you have bought the turn card for one small bet "
                + "instead of a big one, and you can check it through if you miss.",

                "So at limit the aggressive play and the careful play are the same play: raise the "
                + "hands that are likely best, raise the big draws when you are last to speak, and "
                + "call with the rest.",
            ],
            worked: "Blinds 50 and 100. You are last to act on the flop with an open-ended "
                  + "straight draw, and the player first to act bets 100 into a pot of 400.\n\n"
                  + "Calling costs 100 now and, when they bet the turn, 200 more to see the river: "
                  + "300 for two cards. Raising costs 200 now; about half the time they check the "
                  + "turn and the river costs you nothing more, and the other half they bet and it "
                  + "costs 200 more. On the price alone that is the same 300 either way. What the "
                  + "raise adds is everything else: once in a while everybody folds and you win the "
                  + "pot outright, when the draw arrives there is an extra bet in the pot already, "
                  + "and when it misses you can check the river back.",
            practises: "limit-no-free-card"),

        BasicLesson(
            id: "limit-river",
            question: "When should I fold the river at a limit table?",
            short: "Rarely. By the river the pot holds ten or more bets and the last one is one "
                 + "more, so any hand with a real chance calls.",
            paragraphs: [
                "The river is where a limit pot is decided, and the arithmetic is lopsided: the pot "
                + "holds every bet from every street and the bet you face is one more. Paying one "
                + "bet to win ten means you need to be best only one time in eleven. A pair is "
                + "best more often than that against almost anybody who bets.",

                "So the fold that costs the most at limit is the river fold with a hand that had "
                + "a real chance. It feels careful. It hands over a pot that was yours one time "
                + "in three or four, for the price of one bet.",

                "The exception is a hand that cannot beat a bluff — no pair, nothing to come. That "
                + "call is a bet given away, because even the hands that are bluffing have you "
                + "beaten. Call the river with a pair and let go of nothing at all.",
            ],
            worked: "Blinds 50 and 100, so the river bet is 200. Two of you have bet and called "
                  + "all the way, and the pot is 1,600 when they bet the river.\n\n"
                  + "You pay 200 to win 1,800 — one in ten, so you need to be right about 10% "
                  + "of the time. With a pair of kings and an ace on the board, you are best far "
                  + "more often than that. Call.\n\n"
                  + "The same pot with king high and no pair: you win only when they are bluffing "
                  + "with worse than king high, which is almost never. Fold, and keep the bet.",
            practises: "limit-river-overfold"),

        BasicLesson(
            id: "limit-two-bets",
            question: "Which hands are worth two bets before the flop?",
            short: "The ones that play well against a raiser: pairs, a suited ace, two big cards. "
                 + "The rest fold, or raise if they are good enough.",
            paragraphs: [
                "Before the flop at limit, a hand is worth one bet far more often than at no-limit: "
                + "nobody can price you out, and a hand that plays well in a crowd is worth a call "
                + "behind callers. Two bets is different. Calling a raise cold — two bets with "
                + "nobody else in — says your hand was not good enough to re-raise and not good "
                + "enough to fold, and those hands finish second for a whole pot.",

                "Re-raising is for value, not for pushing people out: at limit they will not go. "
                + "So the third and fourth bets before the flop belong to the very top of the deck "
                + "— aces, kings, queens, ace-king — and putting them in with less pays two extra "
                + "bets to be behind.",

                "The habit to build: against one raise, ask whether the hand is one that plays "
                + "against a raiser. If it is, call. If it is a monster, raise. If it is neither, "
                + "it is a fold, however cheap two bets feels.",
            ],
            worked: "Blinds 50 and 100, so a raise makes it 200. The player two seats to your "
                  + "right raises, everybody else folds, and you look down at ten-eight of "
                  + "different suits.\n\n"
                  + "Two bets cold with a hand that has no pair, no suit and only a middling "
                  + "straight to hope for is a fold. Swap it for a pair of sevens or ace-jack of "
                  + "a suit and it is a call. Swap it for a pair of queens and it is a re-raise.",
            practises: "limit-cold-call"),
        ]

    /// The cash course: everything that is true a hundred big blinds deep, minus the short-stack
    /// lesson — nobody at a cash table is fifteen big blinds deep unless they chose to be — and
    /// with the three lessons the deep stack adds. Each of those practises a cash habit.
    public static let cashLessons: [BasicLesson] =
        // The short-stack lesson and the clock go: at a cash table the blinds never move and
        // nobody is fifteen big blinds deep unless they chose to be.
        tournamentLessons.filter { !["stack-depth", "the-clock"].contains($0.id) } + [

        BasicLesson(
            id: "money-behind",
            question: "Why call with a small pair when I am probably behind?",
            short: "Because the times it hits, the money still to be won is many times the price "
                 + "of the call.",
            paragraphs: [
                "A pair of fives against a raise is behind most of the time, and that is not the "
                + "point of it. About one time in eight it makes three of a kind on the flop, and "
                + "when it does, the hand that raised — a big pair, two big cards — often cannot "
                + "get away from it. The pot you win then is many times the pot you called into.",

                "So the question is never whether the pair is ahead now. It is whether the money "
                + "behind pays for the seven times in eight it misses and is thrown away. The rule "
                + "of thumb: for a small pair, the pot plus the money left to win should be about "
                + "twenty times the call. For two cards that fit together — nine-eight of a suit "
                + "— about twenty-five, because they hit less cleanly. And the money that counts "
                + "is the raiser's: only the player who raised can pay you off.",

                "That is why the same hand is a call at a cash table and a fold at a tournament "
                + "table where the stacks have got short: the cards did not change, the money "
                + "behind them did.",
            ],
            worked: "Blinds 50 and 100. Somebody raises to 300, everybody else folds, and you hold "
                  + "a pair of fives with 10,000 in front of you against a player who also has "
                  + "10,000.\n\n"
                  + "The pot is 450 and the call is 300. Money left to win: about 9,700, and with "
                  + "the pot that is more than thirty times the call, far past the twenty a small "
                  + "pair wants, so this is a call.\n\n"
                  + "The same pair, the same raise, but with 2,500 in front of you: 2,200 left to "
                  + "win, which with the pot is about nine times the call. Now it is a fold. "
                  + "Nothing about the fives changed.",
            practises: "missed-implied-odds"),

        BasicLesson(
            id: "one-pair-stack",
            question: "When is one pair worth my whole stack?",
            short: "Almost never, with a hundred big blinds in front of you. One pair wins small "
                 + "pots and loses big ones.",
            paragraphs: [
                "Top pair is a good hand. It is not a hundred-big-blind hand. When somebody is "
                + "willing to play for everything on the flop or the turn, one pair is very rarely "
                + "what they have — they have two pair, three of a kind, a straight, or a draw to "
                + "one. The hands that call your whole stack are the hands that beat one pair.",

                "So the shape of a winning hand with big stacks is this: bet one pair for one or two "
                + "small bets, get paid by worse, and stop the moment the pot stops being small. "
                + "The player who wins with one pair is the one who folds it when the third big "
                + "bet goes in.",

                "That is the whole reason a game with big stacks is played differently from one "
                + "where the stacks are a few bets tall: with a hundred blinds in front of you there "
                + "is room to be wrong, and room to fold.",
            ],
            worked: "Blinds 50 and 100, stacks of 10,000. You raise to 300 with ace-king, one "
                  + "player calls, the blinds fold, and the flop comes king, nine, four.\n\n"
                  + "You bet 500 and they raise to 1,600. Calling is fine: 1,100 more to win a pot "
                  + "of 3,950, and plenty of hands raise here that you beat.\n\n"
                  + "The turn is a two. You check and they bet 6,500 — nearly everything either of "
                  + "you has left, with 8,100 in front of you. Calling now puts most of your stack "
                  + "in with one pair against somebody who wants all of it. The hands that do this "
                  + "beat a pair of kings far more often than not. This is the fold that wins money.",
            practises: "stacked-off-one-pair"),

        BasicLesson(
            id: "re-raised-pots",
            question: "What changes when the pot gets re-raised before the flop?",
            short: "The pot gets big while the stacks stay the same, so there is much less room "
                 + "to play — and much less reason to call for a hand that needs to hit.",
            paragraphs: [
                "After a raise and a re-raise the pot is already a fifth of a stack, and one bet "
                + "on the flop commits most of the rest. Hands that like room — small pairs, two "
                + "cards that fit together — lose what they were worth, because the money behind "
                + "is no longer many times the call.",

                "That is why a small pair calls one raise and lets a re-raise go: against a raise "
                + "to three big blinds the money behind is thirty times the call, and against a "
                + "re-raise to ten it is nine. The pair did not get worse. The price did.",

                "The other side of it: with a genuinely strong hand a re-raised pot is where the "
                + "money is made, because one bet on the flop can win a stack. Big pairs and "
                + "ace-king want the pot re-raised. Everything else wants it kept small.",
            ],
            worked: "Blinds 50 and 100, stacks of 10,000. You raise to 300 with a pair of sixes "
                  + "and the player behind re-raises to 1,000.\n\n"
                  + "It is 700 more to call and the pot is 1,350 before you do. Money left to win: "
                  + "about 9,000, which with the pot is about fifteen times the call. A small pair "
                  + "wants twenty, and it wants it against one raise, not two — this is a fold.\n\n"
                  + "Change the sixes to a pair of kings and the same re-raise is exactly what you "
                  + "were hoping for.",
            practises: "set-mine-no-odds"),
    ]

    /// The tournament course: what the app shipped with.
    public static let tournamentLessons: [BasicLesson] = [

        BasicLesson(
            id: "bet-size",
            question: "How much should I bet?",
            short: "A share of what is already in the middle — usually between half and three "
                 + "quarters of it.",
            paragraphs: [
                "This is the one thing nobody explains, because everybody who plays already does it "
                + "without thinking. A bet is not an amount you pick because it feels right. It is "
                + "a share of the pot, and the pot is the only thing that decides what the number "
                + "should be.",

                "The reason is that your bet sets the price the other person is being offered. Bet "
                + "small and you are giving them a cheap look at the next card, which is exactly "
                + "what somebody chasing a draw wants. Bet big and you are charging them properly "
                + "— but you are also risking more of your own chips to win the same pot, and you "
                + "will get called by fewer hands you are already beating.",

                "Half the pot to three quarters of it is where most bets belong. Go smaller when "
                + "there is nothing much for them to chase and you want a weak hand to pay you. Go "
                + "bigger when the board is scary and you want to make chasing expensive. What you "
                + "should almost never do is bet a number unrelated to the pot, because that is "
                + "the one bet that is either far too cheap or far too dear without you knowing "
                + "which.",
            ],
            worked: "There is 300 in the middle and you want to bet.\n\n"
                  + "Half the pot is 150. Three quarters is 225. Either is a normal bet.\n\n"
                  + "Now think about what you are offering them. If you bet 150 into 300, they pay "
                  + "150 to win 450 — so they need to be good about one time in four to break even, "
                  + "and they will call with a lot. If you bet 225, they pay 225 to win 525, and "
                  + "they need to be right about three times in ten. That difference is the "
                  + "whole reason the size matters.",
            practises: "bet-sizing"),


        BasicLesson(
            id: "the-price",
            question: "Someone bet at me. How do I know if calling is worth it?",
            short: "Compare what you have to pay with what you would win, and be honest about how "
                 + "often you are actually best.",
            paragraphs: [
                "Every call is a price. You are paying a fixed amount now for a share of a pot you "
                + "might win later, and the only question is whether you will be right often enough "
                + "to cover it.",

                "Work the price out first, before you think about the cards at all. Add what is in "
                + "the middle to what they just bet, and compare it with what it costs you to stay "
                + "in. That gives you the share of the time you need to end up with the best hand.",

                "Then be honest about whether you get there that often. Most expensive calls are "
                + "not made by people who got the arithmetic wrong. They are made by people who did "
                + "the arithmetic and then decided they were probably ahead anyway.",
            ],
            worked: "There is 400 in the middle and they bet 100. You are being asked to pay 100 to "
                  + "win 500.\n\n"
                  + "That is one in six, so this call needs to be right about 17% of the time. "
                  + "That is a cheap price, and almost anything with a chance is worth a look.\n\n"
                  + "Now the same hand where they bet 400 into 400. You pay 400 to win 800 — one in "
                  + "three, so you need to be best about a third of the time. Same cards, same board, "
                  + "and it has gone from an easy call to one you will usually be losing money on.",
            practises: "station-flop"),


        BasicLesson(
            id: "open-size",
            question: "How much do I raise before the flop?",
            short: "About two and a half big blinds, plus one more for every person who has already "
                 + "put money in.",
            paragraphs: [
                "This one is close to a fixed rule, and it is worth just learning it. If nobody has "
                + "come in yet, raise to about two and a half times the big blind. That is enough "
                + "to make it a real decision for everyone behind you without committing you to "
                + "much when somebody wakes up with a monster.",

                "If people have already called in front of you, add roughly one big blind for each "
                + "of them. You are raising into a bigger pot and you want the same pressure, so "
                + "the raise has to grow with it.",

                "Two common mistakes sit either side of this. Raising the minimum gives everybody a "
                + "cheap ticket and tells them nothing they need to fear. Raising five or six times "
                + "the blind wins the blinds and nothing else, because the only people who continue "
                + "are the ones you did not want to hear from.",
            ],
            worked: "Blinds are 100 and 200.\n\n"
                  + "Nobody has come in: raise to about 500.\n\n"
                  + "Two people have called before you: raise to about 900 — the 500 you would have "
                  + "made it, plus 200 for each caller.",
            practises: "limping"),


        BasicLesson(
            id: "position",
            question: "Why does everyone go on about where you are sitting?",
            short: "Because whoever acts last has seen what everybody else did, and that is worth "
                 + "more than the cards.",
            paragraphs: [
                "The order of play is fixed, and it goes round the table. That means on every "
                + "round of betting somebody has to speak first with no information, and somebody "
                + "gets to speak last knowing what everyone else chose to do.",

                "Speaking last is an enormous advantage and it lasts the whole hand. You get to "
                + "bet when they show weakness, keep the pot small when you are unsure, and stop "
                + "putting money in the moment somebody tells you they are serious. Speaking first "
                + "means guessing at all of that, every single round.",

                "This is why the same two cards are worth playing from one seat and worth throwing "
                + "away from another. Nothing about the cards changed. What changed is how much "
                + "you will know each time it is your turn.",
            ],
            worked: "The seats are numbered on every screen in this app: seat 1 puts in the small "
                  + "blind, and the highest number is the dealer.\n\n"
                  + "At a full table, seats 3, 4 and 5 speak first and know least. Seats 8 and 9 "
                  + "speak last and know most.\n\n"
                  + "The blinds are the odd ones out: they act last before the flop, because they "
                  + "already have money in, and then first for the rest of the hand. That is why "
                  + "they are the hardest seats and the most expensive to play badly.",
            practises: "passed-steals"),


        BasicLesson(
            id: "which-hands",
            question: "Which hands should I actually play?",
            short: "Far fewer than feels natural from the early seats, and far more than feels "
                 + "natural from the last two.",
            paragraphs: [
                "There is no single list, because the answer depends on where you are sitting. The "
                + "useful version is a rough share: from the first seats you should be coming in "
                + "with about one hand in eight. From the dealer, closer to two in five.",

                "From early seats you have the whole table still to act behind you, so you want "
                + "hands that are simply strong: big pairs, and big cards that stay good when "
                + "somebody plays back at you. From late seats you will often win the pot without "
                + "anything at all, and you can afford hands that need help.",

                "The hands most people lose money on are not the terrible ones. They are the ones "
                + "that look respectable and are not — an ace with a small card next to it, two "
                + "middling cards of the same suit. They make second best hands, and second best "
                + "is what quietly costs the most.",
            ],
            worked: "From the first seats: pairs from about tens up, ace-king, ace-queen. Little "
                  + "else.\n\n"
                  + "From the dealer, with nobody in yet: any pair, any ace, two cards that work "
                  + "together like nine-eight, and most decent big cards.\n\n"
                  + "The gap between those two lists is the single biggest leak in most people's "
                  + "game, and it is entirely about where they were sitting.",
            practises: "too-many-hands"),


        BasicLesson(
            id: "raise-or-fold",
            question: "Is it alright to just call and see a flop?",
            short: "Usually not. If a hand is worth playing it is worth raising, and if it is not, "
                 + "throw it away.",
            paragraphs: [
                "Calling the big blind to have a look is the most natural thing in the world and it "
                + "is where an enormous amount of money goes. It is worth understanding why, "
                + "because on any given hand it never feels like a mistake.",

                "When you raise, you can win the pot immediately because everybody folds. When you "
                + "call, you cannot — you have guaranteed yourself a flop, given everybody behind "
                + "you a cheap ticket to come along, and told the table that your hand is not "
                + "strong enough to raise with.",

                "There are real exceptions. A big pile of chips in front of everybody, a table full "
                + "of people who never fold, a hand that wants a lot of company. But they are "
                + "exceptions somebody chooses on purpose, and the default is raise or fold.",
            ],
            worked: nil,
            practises: "limping"),


        BasicLesson(
            id: "stack-depth",
            question: "Why does my stack size change how I should play?",
            short: "Because a short stack has no room for clever betting — it goes all in or it "
                 + "folds.",
            paragraphs: [
                "How much you have in front of you, measured in big blinds, changes the game more "
                + "than almost anything else. It decides whether you have room to bet on three "
                + "separate rounds, or whether one raise puts your tournament on the line.",

                "With a hundred big blinds you have room to manoeuvre: raise small, see what "
                + "happens, get away from it cheaply when you are beaten. With fifteen there is no "
                + "manoeuvring left. Raise to two and a half and you have committed a sixth of "
                + "everything, and folding to the re-raise costs you more than you can afford.",

                "So the short-stack game is a different game with the same cards. You are looking "
                + "for hands you are happy to put everything in with, and you are getting them in "
                + "first rather than second — because being the one who moves in means they might "
                + "fold, and being the one who calls means they never will.",
            ],
            worked: "Blinds 100 and 200, and you have 3,000 — fifteen big blinds.\n\n"
                  + "A normal raise to 500 leaves you 2,500 behind. If somebody re-raises you are "
                  + "getting a price too good to fold and you have no idea where you are.\n\n"
                  + "Moving all in for 3,000 is the same hand played the only way it can be played "
                  + "well at that size. What looks like recklessness is what fifteen big blinds "
                  + "has already cost you in options.",
            practises: "no-shove"),


        BasicLesson(
            id: "flop-bet",
            question: "Everyone bets the flop after they raised. Why?",
            short: "Because most hands miss most flops, and the person who raised is the one who "
                 + "gets believed.",
            paragraphs: [
                "Three cards come down and, more often than not, they help nobody. If you were the "
                + "one who raised before the flop, you have already told a story about having a "
                + "strong hand, and betting again is simply carrying on with it. That is why it "
                + "works often enough to be nearly automatic.",

                "Which also means it is often a bluff, and everybody knows it. Making the bet is the "
                + "easy part; the skill worth having is deciding when to leave it alone. Betting "
                + "into three people who all called is very different from betting at one, and a "
                + "board that obviously helped whoever called is a board to check.",

                "And when you are the one facing it, remember what you have just read. The bet does "
                + "not mean they have it. It means they raised before the flop and are continuing "
                + "to say so.",
            ],
            worked: nil,
            practises: "no-cbet"),


        BasicLesson(
            id: "same-size",
            question: "Should I bet more when my hand is good?",
            short: "No — and betting big with good hands and small with bad ones is the single "
                 + "easiest thing to read at a table.",
            paragraphs: [
                "It is the most natural instinct there is: strong hand, big bet. The trouble is "
                + "that anybody paying attention will work it out within an hour, and from then on "
                + "you are playing with your cards face up.",

                "Your bet size should come from the situation — the size of the pot, the cards on "
                + "the board, how many people are still in — and not from how much you happen to "
                + "like your hand. Which means the same spot gets the same size whether you have "
                + "the best hand or nothing at all.",

                "That is also what makes bluffing possible. A bluff only works if it looks exactly "
                + "like the real thing, and it can only look exactly like the real thing if the "
                + "real thing has a size you also use when you are bluffing.",
            ],
            worked: nil,
            practises: "bet-sizing"),


        BasicLesson(
            id: "the-clock",
            question: "Can I not just wait for a good hand?",
            short: "No. The blinds go up on a timer, and waiting is itself a way of losing.",
            paragraphs: [
                "In a tournament the blinds rise whether you play or not. Every round costs you "
                + "money for sitting there, and the cost keeps growing. Patience is a virtue right "
                + "up until it is the thing killing you.",

                "The practical version: keep an eye on how many big blinds you have, not how many "
                + "chips. Chips go up and the number that matters goes down, because the blinds "
                + "went up faster. Somebody who has doubled their chips can easily be in more "
                + "trouble than they were an hour ago.",

                "As that number falls you have to play more hands, not fewer — which is the exact "
                + "opposite of what feels safe. Waiting for a hand worth your last ten big blinds "
                + "is how people finish just outside the money, having played beautifully and lost "
                + "anyway.",
            ],
            worked: "You start with 10,000 and blinds of 25 and 50 — two hundred big blinds, and "
                  + "all the room in the world.\n\n"
                  + "Two hours later you have 12,000, which feels like progress. But the blinds are "
                  + "400 and 800, so you have fifteen big blinds.\n\n"
                  + "You have more chips than you started with and far less time. That is the "
                  + "number to watch."),
    ]

    /// Every word of it, for the sweeps that check the app's writing.
    public static var allText: [String] { lessons.flatMap(\.allText) }

    // MARK: - Finding the lesson behind a verdict

    /// The lesson that explains a habit, if one has been written.
    ///
    /// The link already existed in the other direction — each lesson names the habit whose drill
    /// puts you in that spot — so this reads the same relationship backwards rather than inventing
    /// a second table that could disagree with the first.
    public static func lesson(forLeak id: String) -> BasicLesson? {
        lessons.first { $0.practises == id }
    }

    /// The lesson behind one decision the coach priced.
    ///
    /// Ken, 2026-08-22: "when you tell someone that their bet is not right, I find that i dont
    /// undersand why." He is right, and the gap was never the writing — "How much should I bet?"
    /// has been in the app since the basics landed, with the arithmetic worked through. It simply
    /// could not be reached from the one moment somebody wants it, which is being told they got it
    /// wrong. A verdict names the spot and the mistake; a habit is a spot and a mistake; a lesson
    /// names a habit. So the three already line up.
    ///
    /// This matters most for bet sizing, which is the habit the coach is deliberately never
    /// allowed to NAME — `canBeNamed` is false, because a sweep could not separate a player who
    /// sizes badly every time from one who never does. The cost of a single bad size is still
    /// priced and still shown. Which meant, until now, being told a bet was wrong by something
    /// that would never explain the rule it was marking you against.
    public static func lesson(spot: SpotKind, error: ErrorKind) -> BasicLesson? {
        guard let leak = LeakCatalogue.matching(spot: spot, error: error) else { return nil }
        return lesson(forLeak: leak.id)
    }
}