{"id":51322771,"url":"https://github.com/gannasong/stick-drift-detect","last_synced_at":"2026-07-01T15:02:45.778Z","repository":{"id":366539430,"uuid":"1276707202","full_name":"gannasong/stick-drift-detect","owner":"gannasong","description":"Pure, zero-dependency stick-drift verdict engine for the Gamepad API — the logic behind controllertester.co","archived":false,"fork":false,"pushed_at":"2026-06-22T08:14:31.000Z","size":5,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-22T10:14:59.864Z","etag":null,"topics":["controller","deadzone","game-controller","gamepad","gamepad-api","joystick","stick-drift"],"latest_commit_sha":null,"homepage":"https://controllertester.co","language":"JavaScript","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/gannasong.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":"2026-06-22T08:10:51.000Z","updated_at":"2026-06-22T08:14:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gannasong/stick-drift-detect","commit_stats":null,"previous_names":["gannasong/stick-drift-detect"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/gannasong/stick-drift-detect","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gannasong%2Fstick-drift-detect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gannasong%2Fstick-drift-detect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gannasong%2Fstick-drift-detect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gannasong%2Fstick-drift-detect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gannasong","download_url":"https://codeload.github.com/gannasong/stick-drift-detect/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gannasong%2Fstick-drift-detect/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35011257,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"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":["controller","deadzone","game-controller","gamepad","gamepad-api","joystick","stick-drift"],"created_at":"2026-07-01T15:02:44.917Z","updated_at":"2026-07-01T15:02:45.764Z","avatar_url":"https://github.com/gannasong.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# stick-drift-detect\n\nPure, zero-dependency **stick-drift detection** for the [Gamepad API](https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API). Feed it raw analog-stick `(x, y)` samples collected while the stick is **at rest**, and it returns a clear **`PASS` / `DRIFTING` / `FAIL`** verdict — not just raw numbers you have to interpret yourself.\n\nThis is the exact verdict engine behind **[Controller Tester](https://controllertester.co)** — a free, in-browser controller / gamepad tester. Try the full interactive version, no install:\n\n👉 **[controllertester.co/stick-drift-test](https://controllertester.co/stick-drift-test)**\n\n## Install\n\n```sh\nnpm install stick-drift-detect\n```\n\n## Usage\n\n```js\nimport { classifyStick, rollupController, Verdict } from 'stick-drift-detect';\n\n// Poll navigator.getGamepads()[i].axes for ~2s while the stick is untouched,\n// collecting raw (x, y) readings:\nconst leftStickSamples = [\n  [0.01, -0.02], [0.0, 0.01], [0.02, 0.0], /* ...30+ samples... */\n];\n\nconst left = classifyStick(leftStickSamples, /* axesPresent */ true);\n\nconsole.log(left.verdict); // 'PASS' | 'DRIFTING' | 'FAIL' | 'INVALID' | 'UNAVAILABLE'\nconsole.log(left.mMed);    // median resting magnitude — how far the stick sits off-center\n\n// Combine multiple sticks into one controller-level verdict (worst real verdict wins):\nconst overall = rollupController([left, right]);\nif (overall === Verdict.FAIL) console.log('This controller has stick drift.');\n```\n\n## How it works\n\n1. Each `(x, y)` sample is reduced to a magnitude with `Math.hypot(x, y)` — the distance of the stick from dead center. **No baseline subtraction**: subtracting a resting offset would hide the very drift you are trying to measure.\n2. The **median** magnitude over the window is the drift amount (`mMed`), robust to occasional spikes.\n3. A **spread** check (p90 − p10 of magnitudes) catches the case where the stick was actually moved during sampling and marks the run `INVALID`.\n4. The median is compared against thresholds:\n   - `mMed \u003c 0.10` → `PASS`\n   - `0.10 ≤ mMed \u003c 0.25` → `DRIFTING`\n   - `mMed ≥ 0.25` → `FAIL`\n\nThresholds are exported as `THRESHOLDS` and can be overridden per call.\n\n## API\n\n- `classifyStick(samples, axesPresent, thresholds?) → StickResult` — classify one stick.\n- `rollupController(stickResults) → Verdict` — worst real verdict across sticks.\n- `THRESHOLDS` — default tunable thresholds.\n- `Verdict` — the verdict string constants.\n\nFull TypeScript types are bundled.\n\n## License\n\nMIT — built for and by [controllertester.co](https://controllertester.co).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgannasong%2Fstick-drift-detect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgannasong%2Fstick-drift-detect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgannasong%2Fstick-drift-detect/lists"}