npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

frc-opr

v0.3.0

Published

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

Readme

frc-opr

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-opr | Java / Python scripts | Statbotics API | |---|:---:|:---:|:---:| | Language | TypeScript | Java, Python | service | | Runs in the browser | yes | no | n/a (network) | | Works on your own match data | yes | yes | no, serves its own | | Zero dependencies | yes | varies | n/a | | OPR, DPR, CCWM | yes | varies | EPA 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:

| Rating | Right-hand side per alliance appearance | |--------|----------------------------------------| | OPR | own alliance score | | DPR | opponent alliance score | | CCWM | own 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.