{"id":30188130,"url":"https://github.com/phisgr/bidding-system-as-code","last_synced_at":"2025-08-12T16:43:52.633Z","repository":{"id":308070374,"uuid":"1031532465","full_name":"phiSgr/bidding-system-as-code","owner":"phiSgr","description":"Contract bridge bidding as code.","archived":false,"fork":false,"pushed_at":"2025-08-04T00:08:52.000Z","size":566,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-04T01:30:36.509Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phiSgr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-04T00:01:59.000Z","updated_at":"2025-08-04T00:33:32.000Z","dependencies_parsed_at":"2025-08-04T01:30:56.236Z","dependency_job_id":"1fba06ae-90a8-47f1-b0ad-6012836f8191","html_url":"https://github.com/phiSgr/bidding-system-as-code","commit_stats":null,"previous_names":["phisgr/bidding-system-as-code"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/phiSgr/bidding-system-as-code","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phiSgr%2Fbidding-system-as-code","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phiSgr%2Fbidding-system-as-code/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phiSgr%2Fbidding-system-as-code/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phiSgr%2Fbidding-system-as-code/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phiSgr","download_url":"https://codeload.github.com/phiSgr/bidding-system-as-code/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phiSgr%2Fbidding-system-as-code/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270099872,"owners_count":24527041,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-12T16:43:50.752Z","updated_at":"2025-08-12T16:43:52.601Z","avatar_url":"https://github.com/phiSgr.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bidding System As Code\n\nYour agreements don't end with filling in the convention card.\n\nThat neat little grid can't capture what happens\nafter a support double, or even after 2/1 GF -\ndoes the 2M rebid promise an extra card, or is that catch-all?\n\nWithout explicit agreements, you're both guessing[^1].\nYou need to write down what your bids actually mean. All of them.[^2]\nWhen you and partner remember different versions of your agreements,\nyou need a single source of truth detailed enough to settle the argument.\n\nYour convention card is nowhere near big enough for that.\n\n[^1]: If your guesses usually match your partner's,\nyou have implicit agreements - a mess for active ethics;\nif your guesses don't match, you give IMPs away.\nThe latter is better, to be honest.\n\n[^2]: The foreword to [Revision Club](https://bridgewithdan.com/wp-content/uploads/2019/07/revision_club_4th_ed.zip)\nmakes this argument at length. Worth reading even if you have zero interest in strong club systems.\n\n## Why Code\n\nI have long wanted to document EVERY method that I use in bridge bidding.\nPen and paper, plain text file, or word processors[^3] -\nevery attempt ended with the document collapsing under its complexity[^4].\n\n[^3]: Not Just MS Word or Google Docs, I got furthest with TeXmacs - criminally underrated software.\n\n[^4]: or my lack of willpower, idk\n\n#### What's so hard about writing bidding systems?\n\n- Versioning hell. You change one agreement and suddenly\n  can't remember if you're playing the Tuesday version or\n  the one from last month's disaster.\n\n- Messy similarity.\n  Bidding sequences are often similar but not identical.\n  They are usually described in one of two ways:\n  - Spell out every sequence in detail.\\\n    The differences can be overlooked when buried inside duplicative listings.\n  - Handwave with the word \"similarly\".\\\n    The reader (and maybe the writer as well!) might not fully consider the sequences,\n    especially where they differ.\n\n- Flattened bidding tree.\n  Bidding branches, text flows linearly.\n  Finding any specific sequence means a lot of scrolling.\n\nSwitching to code solves all that, and more:\n\n- Version controlled. `git` shows exactly what is modified and when. Automatic change log.\n  Imagine pointing to a commit and say \"we swapped these two bids 5 months ago\n  because you wanted to make the strong hand declarer.\"\n- Elegant symmetry.\n  In code, we concretely specify all sequences - see the Heeman example below.\n  Conditional logic explicitly highlights where they differ.[^5]\n  When the code is executed, we get all the sequences spelled out.\n  Two for the price of one.\n- Non-sequential reading.\n  Jump directly to definitions or usages of sequences without hunting through pages of text,\n  because [Code is HyperText](https://medium.com/@georgeleung_7777/code-is-hypertext-ecf11f93a531).\n- Separation of content and styling. You write your system in a clean [DSL](dsl/README.md)\n  ([domain-specific language](https://kotlinlang.org/docs/type-safe-builders.html));\n  it outputs a JSON tree for an HTML viewer.\n- IDE auto-formatting, as long as braces match. (BTW, fuck YAML)\n\n[^5]: A meticulous writer might do the same in prose,\nbut they'd be specifying differences in verbose natural language that\nyou'd have to execute in your head.\n\n## HTML Viewer\n\nFeatures:\n\n- Collapse and expand.\n- Colour-coding the bidder: blue and grey for NS; orange and red for EW.\n  No more confusion about whose bid it is in a deep sequence.\n- Context on hover: see the whole sequence at a glance, no matter how deep you are in the bidding tree.\n\nDemo: [Fantunes](https://phisgr.github.io/bridge/fantunes/),\n[Heeman](https://phisgr.github.io/bridge/heeman/),\n[Transfer Lebensohl](https://phisgr.github.io/bridge/xfer-leb/)\n\n### Examples\n\nThe [text file of the Fantunes system by Dan](https://bridgewithdan.com/wp-content/uploads/2019/07/Fantoni_Nunes.txt)\nis translated to [code](dsl/src/test/kotlin/fantunes/fantunes.kt).\nThe [output HTML viewer](https://phisgr.github.io/bridge/fantunes/) allows you to explore the system interactively.\n\nThe Fantunes example merely reformatted the text file in code.\nWe got a nice interactive viewer for the hard work,\nbut the power of code really shines through when we have similar sequences.\nFor example, Jacoby transfers for the two major suits can be written once:\n\n```kt\n\"1N\" - \"15-17 balanced\" {\n    \"2C\" - \"Stayman\"\n\n    // equivalent to writing\n    // \"2D\" - \"transfer, 5+H\" { ... }\n    // \"2H\" - \"transfer, 5+S\" { ... }\n    Major.suits.forEach { M -\u003e\n        \"2${M.red}\" - \"transfer, 5+$M\" {\n            \"2$M\" - {\n                \"2N\" - \"invite to both games\"\n                // ...\n            }\n        }\n    }\n}\n```\n\nFor a bigger example, see the [Heeman 1NT response structure](dsl/src/test/kotlin/heeman/heeman.kt),\nand compare that to [the PDF](http://www.jackbridge.com/pdf/eheeman.pdf).\nThis response structure cleverly uses similar sequences for similar hand shapes,\ngreatly reducing memory burden.\nFor example, by reaching 3C in 4 different ways, responder can show 5H4C, 5S4C, 4H5C, or 4S5C.\nIn code, this 4-fold symmetry is written only once. Any asymmetry becomes obvious:\n\n```kt\n/**\n * The four-fold symmetry sequence.\n * The sequence [isFast] if responder's first bid is a transfer to [M],\n * i.e. it does not go through 2C-2D.\n */\nprivate fun BiddingTree.symmetric(isFast: Boolean, M: Major) {\n    val majorHolding = \"${if (isFast) 4 else 5}c$M\"\n    val minorLength = if (isFast) 5 else 4\n\n    \"2N\" - \"$majorHolding inv to both games\"\n    \"3m\" - \"$majorHolding$minorLength+m, inv\"\n\n    // ...\n\n    val suitQuality = if (isFast) \"weak\" else \"good\"\n    \"4m\" - \"splinter, $suitQuality long $M\"\n    when (M) {\n        // no way to show spade splinter with long H\n        H if isFast -\u003e \"4S\" - \"undefined\"\n        // no way to show S suit quality when the splinter suit is H, as slow 4H is RKCB\n        S if isFast -\u003e \"4H\" - \"splinter, long $M\"\n        else -\u003e \"4${other(M)}\" - \"RKCB\"\n    }\n    \"4$M\" - \"$suitQuality long $M, slam inv\"\n}\n```\n\nThe `when` clause draws your attention to the fact that\nthere's no way to show the S suit quality when the splinter suit is H.\nI played Heeman for months without noticing this\nbecause it was buried in the repetitive listings.[^6]\n\nHere is the slow and fast branches for spades in the viewer:\\\n![Heeman Slow Spades](heeman_slow.png)\\\n![Heeman Fast Spades](heeman_fast.png)\n\n[^6]: A lesson we learned in software engineering:\n\"You basically can't pay people enough to carefully review dull code.\"\n\n## Licensing Note\n\nThe output HTML embeds software licensed under AGPLv3.\nRedistribution under restrictive terms may create compliance complexities\nbest avoided through open distribution.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphisgr%2Fbidding-system-as-code","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphisgr%2Fbidding-system-as-code","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphisgr%2Fbidding-system-as-code/lists"}