{"id":42649283,"url":"https://github.com/rbtying/shengji","last_synced_at":"2026-01-29T07:19:22.725Z","repository":{"id":37085538,"uuid":"250462206","full_name":"rbtying/shengji","owner":"rbtying","description":"An online version of shengji (a.k.a. tractor) and zhaopengyou (a.k.a. Finding Friends)","archived":false,"fork":false,"pushed_at":"2025-09-13T00:27:35.000Z","size":3732,"stargazers_count":93,"open_issues_count":25,"forks_count":47,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-09-13T01:09:18.944Z","etag":null,"topics":["card-games","finding-friends","shengji","tractor","zhaopengyou"],"latest_commit_sha":null,"homepage":"https://robertying.com/shengji/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rbtying.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-03-27T06:53:35.000Z","updated_at":"2025-09-13T00:27:37.000Z","dependencies_parsed_at":"2024-01-20T22:30:02.660Z","dependency_job_id":"22c2990f-391f-4b4b-bcc9-97f39687724e","html_url":"https://github.com/rbtying/shengji","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/rbtying/shengji","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rbtying%2Fshengji","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rbtying%2Fshengji/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rbtying%2Fshengji/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rbtying%2Fshengji/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rbtying","download_url":"https://codeload.github.com/rbtying/shengji/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rbtying%2Fshengji/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28869181,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-29T06:56:44.678Z","status":"ssl_error","status_checked_at":"2026-01-29T06:56:35.794Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["card-games","finding-friends","shengji","tractor","zhaopengyou"],"created_at":"2026-01-29T07:19:22.086Z","updated_at":"2026-01-29T07:19:22.714Z","avatar_url":"https://github.com/rbtying.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# What is this?\n\n升级 is a popular Chinese trick-taking playing card game, also known as tractor, finding friends, fighting for 100 points, 80 points, etc. Rules are available\n[here](https://robertying.com/shengji/rules.html). Due to the COVID-19\nshelter-in-place, I've been unable to play the this game in person... so\nI figured an online version would be worthwhile.\n\n# Usage:\n\n```\ncd frontend \u0026\u0026 yarn build \u0026\u0026 cd .. \u0026\u0026 cd backend \u0026\u0026 cargo run\n```\n\nThe server is a self-contained static binary and does not terminate TLS. It\nlistens on 127.0.0.1:3030, and should only be exposed to an external network\nbehind a proxy that supports both HTTP and WebSocket protocols (only tested\nwith `nginx`).\n\n## Environment Variables\n\n- `CORS_ALLOWED_ORIGINS`: Comma-separated list of allowed origins for CORS requests to the `/api/rpc` endpoint (e.g., `\"https://example.com,https://app.example.com\"`). Set to `\"*\"` to allow any origin (not recommended for production). If not set, defaults to allowing common localhost origins for development (`http://localhost:3000,http://localhost:3030,http://127.0.0.1:3000,http://127.0.0.1:3030`).\n\n# Development\n\n```\ncd frontend \u0026\u0026 yarn watch\ncd backend \u0026\u0026 cargo run --features dynamic\n```\n\n## Syncing types from Rust to Typescript\n\nThere are shared types in the Rust backend and the Typescript frontend; the `frontend/json-schema-bin/src/main.rs` file dumps the Rust types to JSON Schema, and the `yarn types` command will generate the Typescript types.\n\n```\nyarn types \u0026\u0026 yarn prettier --write \u0026\u0026 yarn lint --fix\n```\n\n## Generating JSON\nA mapping of card data is generated from the server. It's checked in at\n`src/generated/cards.json`. To update it, start up the server and run\n\n```\nyarn download-cards-json\n```\n\n## Prettier\nTo format frontend code:\n\n```\n# Dry-run/check\nyarn prettier --check\n\n# Fix files, will overwrite files\nyarn prettier --write\n```\n\n## Lint\nTo run tslint:\n\n```\ncd frontend \u0026\u0026 yarn lint\n```\n\nAnd clippy:\n```\ncargo clippy\n```\n\n## Tests\nTo run tests:\n\n### Frontend:\n```\ncd frontend \u0026\u0026 yarn test\n```\n\n### Backend:\n```\ncargo test\n```\n\n# Technical details\nThe entire state of each game is stored in the memory of the server process.\nRestarting the game kicks all players, and games are automatically closed when\nall players have disconnected. The bulk of the game logic is implemented in the\nserver, but players are expected to keep each other in check -- the server does\nnot validate moves in their entirety.\n\nFor simplicity, the game is written in Rust and Javascript, linking in Axum as\nthe WebSocket/HTTP server implementation and using React from a CDN.\n\n# Known issues\n- No mobile support\n- Incomplete validity checking for forced-plays\n- No player limit per game\n- No overall player limit\n\n# Play online!\n\n[https://robertying.com/shengji/](https://robertying.com/shengji/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frbtying%2Fshengji","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frbtying%2Fshengji","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frbtying%2Fshengji/lists"}