New:Microsoft Teams Notifications Are Now Available in Socket.Learn more →
Get Started

frc-opr

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

frc-opr

Compute FRC power ratings (OPR, DPR, CCWM) from match data by least squares. Typed, zero dependencies, browser and Node.

latest
Source
npmnpm
Version
0.3.0
Version published
Maintainers
1
Created
Source

frc-opr

frc-opr logo

CI License: MIT

Compute FRC power ratings (OPR, DPR, CCWM) from match data by least squares. Typed, zero runtime dependencies, runs in the browser and in Node.

Install

npm install frc-opr

30-second example

import { powerRatings } from "frc-opr";

const { opr, dpr, ccwm } = powerRatings([
  { red: ["111", "222", "333"], blue: ["444", "555", "666"], redScore: 88, blueScore: 64 },
  { red: ["111", "444", "555"], blue: ["222", "333", "666"], redScore: 95, blueScore: 71 },
  // ... the rest of the qualification matches
]);

opr.get("111");  // estimated points team 111 contributes
dpr.get("111");  // estimated points it allows the opponent
ccwm.get("111"); // contribution to winning margin (OPR minus DPR)

Why this exists

OPR and its relatives are the standard derived statistics in FRC scouting, computed by least squares over the alliance-membership matrix. Scouting tools are almost all web apps, but the only reusable implementations are Java and Python scripts, so teams paste ad hoc least-squares code into their frontends. frc-opr is the first TypeScript library for it: a correct, tested solve with no dependencies, usable directly in a dashboard.

Comparison

frc-oprJava / Python scriptsStatbotics API
LanguageTypeScriptJava, Pythonservice
Runs in the browseryesnon/a (network)
Works on your own match datayesyesno, serves its own
Zero dependenciesyesvariesn/a
OPR, DPR, CCWMyesvariesEPA and more

Statbotics is excellent for precomputed ratings over official events; frc-opr computes ratings locally from whatever matches you give it, including practice or custom data.

API

  • powerRatings(matches) returns { opr, dpr, ccwm }, each a Map from team key to rating.
  • defensivePowerRatings(matches) returns a Map<string, number> of DPR per team. Equivalent to the dpr field of powerRatings, but as a focused function when you only need DPR.
  • winningMarginRatings(matches) returns a Map<string, number> of CCWM per team. Equivalent to the ccwm field of powerRatings, but as a focused function when you only need CCWM. Guaranteed to equal OPR minus DPR elementwise (the linearity of the system ensures this).
  • powerRatingsRidge(matches, ridge) is the ridge-regularized (MMSE) variant: it stays solvable on early-event data that is not yet well determined and biases ratings toward zero, approaching powerRatings as ridge approaches 0.
  • fromTbaMatches(tbaMatches) converts The Blue Alliance match objects into Match values, skipping matches that have not been played.
  • solve(matrix, b), luDecompose(matrix), luSolve(factorization, b): the dense linear solver, exported for reuse.

A Match is { red: string[], blue: string[], redScore: number, blueScore: number }. Team keys are any non-empty strings.

DPR and CCWM in depth

DPR and CCWM solve the same normal-equations system as OPR, differing only in the right-hand side:

RatingRight-hand side per alliance appearance
OPRown alliance score
DPRopponent alliance score
CCWMown score minus opponent score (margin)

Because the margin is the difference of the other two right-hand sides, CCWM = OPR - DPR holds elementwise for every team. winningMarginRatings builds the margin right-hand side directly and verifies this identity in the test suite to within 1e-9.

The math

Each alliance appearance gives one equation: the sum of its members' ratings equals the alliance score (OPR) or the opponent score (DPR). That overdetermined system is solved through its normal equations, whose matrix is the symmetric team co-appearance matrix. OPR and DPR share that matrix, so it is factorized once. CCWM is OPR minus DPR, and the CCWM values over an event sum to zero. If the data is rank-deficient (too few matches to separate teams), powerRatings throws a clear error rather than returning unstable numbers.

Roadmap

  • Component ratings from labeled score breakdowns.

Examples

npm run example

Testing

npm test

Tests cover exact recovery of known ratings from consistent synthetic events, the CCWM = OPR - DPR identity, the zero-sum CCWM property, solver unit tests, and the rank-deficient error path.

Contributing

Issues and pull requests are welcome. See CONTRIBUTING.md.

License

MIT. See LICENSE.

Keywords

frc

FAQs

Package last updated on 17 Jun 2026

Related posts