{"id":41624189,"url":"https://github.com/cohstats/coh2stats","last_synced_at":"2026-04-11T18:17:30.922Z","repository":{"id":36997115,"uuid":"326416762","full_name":"cohstats/coh2stats","owner":"cohstats","description":"Statistics, usage charts and other useful information for a game Company of Heroes 2","archived":false,"fork":false,"pushed_at":"2026-01-19T15:48:19.000Z","size":54085,"stargazers_count":33,"open_issues_count":47,"forks_count":28,"subscribers_count":4,"default_branch":"master","last_synced_at":"2026-01-21T21:27:00.761Z","etag":null,"topics":["antd","cloud-functions","company-of-heroes-2","firebase","firestore","game","hacktoberfest","javascript","react","statistics","typescript"],"latest_commit_sha":null,"homepage":"https://coh2stats.com","language":"TypeScript","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/cohstats.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"ko_fi":"cohstats"}},"created_at":"2021-01-03T13:44:12.000Z","updated_at":"2025-05-21T15:06:44.000Z","dependencies_parsed_at":"2024-04-02T19:47:38.493Z","dependency_job_id":"a9ac2c88-907f-4d85-b459-676025c0b237","html_url":"https://github.com/cohstats/coh2stats","commit_stats":null,"previous_names":[],"tags_count":98,"template":false,"template_full_name":null,"purl":"pkg:github/cohstats/coh2stats","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cohstats%2Fcoh2stats","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cohstats%2Fcoh2stats/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cohstats%2Fcoh2stats/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cohstats%2Fcoh2stats/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cohstats","download_url":"https://codeload.github.com/cohstats/coh2stats/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cohstats%2Fcoh2stats/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28729411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T10:24:43.181Z","status":"ssl_error","status_checked_at":"2026-01-24T10:24:36.112Z","response_time":89,"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":["antd","cloud-functions","company-of-heroes-2","firebase","firestore","game","hacktoberfest","javascript","react","statistics","typescript"],"created_at":"2026-01-24T14:10:36.304Z","updated_at":"2026-04-11T18:17:30.915Z","avatar_url":"https://github.com/cohstats.png","language":"TypeScript","funding_links":["https://ko-fi.com/cohstats"],"categories":[],"sub_categories":[],"readme":"# COH2 CHARTS, PLAYER STATS, LEADERBOARDS\n\n![GitHub release (latest by date)](https://img.shields.io/github/v/release/cohstats/coh2stats)\n![Uptime Robot ratio (30 days)](https://img.shields.io/uptimerobot/ratio/m788579058-010f84f8b7e284e354b0946c?label=uptime%2030%20days)\n[![DeepScan grade](https://deepscan.io/api/teams/15780/projects/20479/branches/558227/badge/grade.svg)](https://deepscan.io/dashboard#view=project\u0026tid=15780\u0026pid=20479\u0026bid=558227)\n[![Discord](https://img.shields.io/discord/959118129240350740?style=flat\u0026label=Chat%20on%20Discord)](https://discord.gg/jRrnwqMfkr)\n\n### Website https://coh2stats.com/\n\nWith all the data, player cards, leaderboards, maps, stats, commanders, inte-bulletins and much more!\n\n### Desktop App [here](packages/app/README.md)\n\nFor current match details, player information and other features.\n\nThis project is set to create new usage charts for the game COH2.\nAnd also create web access to leaderboards, player cards and recent matches for players.\nThe author of the game doesn't provide any global statistics. And online leaderboards has been shutdown recently.\n\nThis project is inspired by coh2chart.com which has data\nonly for years 2016-2017 after which it was shut down.\n\n### Open source data\n\nFor open source data visit www.coh2stats.com/other/open-data\n\n_In case you will use the data, please mention the source and give a shout-out to the website coh2stats.com, thank you!_\n\n## Technical description\n\nThe project is created in Google Cloud with usage of Firebase.\nThe main language of the project is set to be JavaScript. Which will\nbe used on both FE and BE.\n\n- FE - JavaScript, React\n- BE - Serverless JS\n- DB - FireStore (NoSQL DB)\n\nGCP services to be used:\n\n- Firebase Hosting - For hosting the website\n- Firebase Firestore - NoSQL Database\n- Firebase Cloud functions - Is the main backend for crawling and data processing\n- [GCP Pub/Sub](https://cloud.google.com/pubsub/docs/overview) - For messaging between the functions\n- GCP Storage - For storing extra data\n\nThing to consider:\n\n- There is a large amount of matches, we store them in the FireStore, however\n  once you store the match. You don't do any changes to it, therefore it would be\n  better to store them in the [BigQuery](https://cloud.google.com/bigquery/) where\n  we could run our analysis more easily and it would be Faster and Cheaper.\n\n### CI/CD\n\nOnly web package is automatically deploy. Cloud functions\nneed to be done manually for now.\n\n#### Prod\n\nTagged versions are automatically deployed to https://coh2stats.com/\n\n#### Dev\n\n`master` branch is automatically deployed to https://dev.coh2stats.com\n\n### Development\n\nThe repository is yarn workspace. Use `yarn` to manage this.\nDo `yarn install` from the project root to install dependencies.\n\nTo run beautifier and linting:\n`yarn fix`\n\nUse Node version 16.x or as described in `/packages/functions/package.json`\n\n#### Web\n\n- To start local web dev: `yarn web dev`\n- Test: `yarn web test` (located in `packages/web/src/tests`)\n- Build: `yarn web build`\n\n#### Docker\n\nThe project includes a Dockerfile at the root for containerized deployment:\n\n```bash\n# Build the Docker image\nyarn docker:build\n# or\ndocker build -t coh2stats-web .\n\n# Run the container\nyarn docker:run\n# or\ndocker run -p 3000:3000 coh2stats-web\n```\n\nThe Dockerfile handles the Yarn workspaces monorepo structure and uses the root `yarn.lock` file.\n\n#### Functions\n\nBE has been moved to repo `coh2-stats-be`\n\n### Patch update steps for text bulletin / commander data\n\n1. Run script `bulletinsAndCommanders.py` with correct path to your COH2 folder\n2. Run script `fixCommanderImages.py` to fix the generated commanderData.json file\n3. Copy the generated files `*ServerData.json` into `packages/functions/src/libs/data/`\n   - bulletinServerData.json\n   - commanderServerData.json\n4. Copy the generates files `*Data.json` into `packages/web/src/coh/data/`\n   - bulletinData.json\n   - commanderData.json\n5. Run formatter by using commander `yarn fix`\n6. Observe the changes\n7. Update the `packages/web/src/config.tsx` with the right date / patch name\n\n### Images for maps\n\nProvided by [Janne252](https://github.com/Janne252) https://github.com/Janne252/coh2-replay-discord-bot/tree/master/data/scenario-preview-images  \nFor mass reformats from .png to .webp - use Infraview https://www.irfanview.com/ (best image utility)\n\n### Crawler process\n\nDiagram:\nhttps://lucid.app/documents/embeddedchart/ec7ffc19-50c4-4104-bcf9-287e2af3ac62\n\n~Crawler process is set to run every day. There is a huge amount of data\nso we need to do it everyday to avoid big stress on the Relic API.~\n\n**The crawling is design in a way which should not stress the Relic API (aka\nslowly).**\n\n~The crawler process should run everyday. Most likely ~5 AM UTC. As that\nshould be the time with least players (EU, US asleep). But we will treat\nthis date as a date -1 day data.~\n\n~~##### 1. We request top 200 players from all leaderboards~~\n\n~~This gives us 5200 positions. It's done by cloud function `getCOHLadders`.\nWe can request by 200 chunks from the API =\u003e 26 Relic API calls.  \nThis operation takes around 30 seconds.~~\n\n~~##### 2. Filter only unique players~~\n\n~~We extract the Steam IDs, only unique players are kept.~~\n~~This gives us ~2900 players for the top 5200 positions.~~\n\n##### 3. Send player ids to Pub/Sub que\n\nWe send the player Steam IDs as a messages to the que called `\"download-matches\"`\nEach message has array of IDs. The current chunk is set to X.\n~~TODO: Experiment with the best chunk size.~~ We want the chunk size\nto be pretty big because we can filter the duplicates only in\none chunk. (We filter the rest when we hit the DB but we want to\navoid unnecessary writes to the DB)\n\n##### 4. Pub/Sub que `\"download-matches\"` is consumed\n\nThe que is consumed by cloud functions `getPlayerMatches`.\nThe main benefit of the que is that any service of our application\ncan send a message into it. Making sure the match is saved.\n~~Only 2-3 instances of the function are allowed. To slow down the processing.~~\nWe had to limit it to 1 function. We were getting errors \"Too many requests\"\nfrom the API.\n\nThe function takes the array of the IDs and downloads the matches\nof each player in sequence (again not to stress the API).\n\nThis takes around 45-85 seconds. Usually ~350-500ms per player. However\nthere are anomalies which can go up to 5-6 seconds per player.\n\nThis makes the amount of players API calls. (~2900)\nThe process takes around 25 minutes.\n\n##### 5. Matches are filtered and modified\n\nWe filter matches only from the previous day (The API returns all player matches).\nWe try to filter any duplicated matches (1 match is shown that many times as it has players).\nThis is designed not to do extra writes to the DB with the data we already have.\nThis saves us DB reads and writes.\n\nWe remove any extra fields we don't care about.\n\n##### 6. Matches are saved to the DB\n\nAll matches are saved in the FireStore under collection /matches\nThe ID of the document is the ID of the match which ensures nothing\ncan be duplicated.\n\n##### 7. Analysis is run\n\nWe can get matches for particular day and run analysis on them.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcohstats%2Fcoh2stats","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcohstats%2Fcoh2stats","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcohstats%2Fcoh2stats/lists"}