# How React Doctor Calculates Its Internal Scoring Formula: The 100‑Point Penalty System

> Discover how React Doctor's 100-point penalty system calculates its internal scoring formula. Learn the exact point deductions for errors and warnings.

- Repository: [Million Software, Inc./react-doctor](https://github.com/millionco/react-doctor)
- Tags: internals
- Published: 2026-05-12

---

**React Doctor derives a 0‑100 health score by deducting 1.5 points for every distinct error rule and 0.75 points for every distinct warning rule from a perfect baseline of 100, rounding the result and mapping it to "Great", "Needs work", or "Critical" based on thresholds at 75 and 50.**

React Doctor (millionco/react-doctor) converts lint-style diagnostics into a quantitative codebase health metric. The **internal scoring formula** aggregates unique rule violations into a normalized score with a human-readable label, allowing developers to track project quality numerically.

## Step 1 – Deduplicating Violations with `collectUniqueRuleSets`

The scoring algorithm begins by normalizing diagnostics into unique rule identifiers to prevent duplicate penalties. In [`packages/react-doctor/src/utils/calculate-score-locally.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/utils/calculate-score-locally.ts), the `collectUniqueRuleSets` function (lines 26‑40) iterates through the diagnostics array and partitions them into two `Set` instances based on severity:

```typescript
const ruleKey = `${diagnostic.plugin}/${diagnostic.rule}`;
if (diagnostic.severity === "error") errorRules.add(ruleKey);
else warningRules.add(ruleKey);

```

This deduplication step ensures that violating the same rule multiple times only penalizes the score once per distinct rule.

## Step 2 – Calculating the Raw Score with `scoreFromRuleCounts`

Once unique violations are isolated, the `scoreFromRuleCounts` function (lines 44‑47) applies a penalty-based subtraction model. The algorithm imports constants from [`packages/react-doctor/src/constants.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/constants.ts): **ERROR_RULE_PENALTY** is set to `1.5` and **WARNING_RULE_PENALTY** to `0.75`, subtracted from a **PERFECT_SCORE** of `100`:

```typescript
const penalty = errorRuleCount * ERROR_RULE_PENALTY
              + warningRuleCount * WARNING_RULE_PENALTY;
const rawScore = PERFECT_SCORE - penalty;
const score = Math.max(0, Math.round(rawScore));

```

The final score is clamped to a minimum of `0` and rounded to the nearest integer, ensuring a clean 0‑100 output.

## Mapping Numeric Scores to Labels via `getScoreLabel`

After computing the integer score, React Doctor assigns a categorical label using the `getScoreLabel` function (lines 20‑24) in [`calculate-score-locally.ts`](https://github.com/millionco/react-doctor/blob/main/calculate-score-locally.ts). The mapping relies on two thresholds defined in [`constants.ts`](https://github.com/millionco/react-doctor/blob/main/constants.ts):

- **Score ≥ 75** (`SCORE_GOOD_THRESHOLD`) → `"Great"`
- **Score ≥ 50** (`SCORE_OK_THRESHOLD`) → `"Needs work"`
- **Otherwise** → `"Critical"`

This three-tier system transforms numeric technical debt into actionable priority levels.

## API‑First Execution with Local Fallback

While the local algorithm provides deterministic scoring, React Doctor prioritizes remote evaluation for consistency across versions. The `calculateScore` function in [`packages/react-doctor/src/utils/calculate-score.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/utils/calculate-score.ts) (lines 8‑10) orchestrates this by first attempting to POST stripped diagnostics to `SCORE_API_URL` via [`try-score-from-api.ts`](https://github.com/millionco/react-doctor/blob/main/try-score-from-api.ts).

If the API call succeeds and returns a valid `{score, label}` payload, that result is used immediately. If the network request fails or returns invalid data, React Doctor falls back to the local `calculateScoreLocally` implementation described above.

## Implementing the Scoring Formula in Your Code

To compute scores programmatically, import the primary utility and pass an array of diagnostic objects:

```typescript
import { calculateScore } from "react-doctor";

// diagnostics is an array of Diagnostic objects from a scan
const result = await calculateScore(diagnostics);

if (result) {
  console.log(`Score: ${result.score} – ${result.label}`);
}

```

For offline environments or when API access is restricted, invoke the local calculator directly:

```typescript
import { calculateScoreLocally } from "react-doctor";

const localResult = calculateScoreLocally(diagnostics);
console.log(`Offline score: ${localResult.score} – ${localResult.label}`);

```

## Summary

- React Doctor derives scores in [`packages/react-doctor/src/utils/calculate-score-locally.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/utils/calculate-score-locally.ts) using a **100‑point baseline** system.
- **Distinct rule penalties**: 1.5 points per error rule, 0.75 points per warning rule.
- The final score is **rounded** and **clamped** to a minimum of 0.
- **Thresholds** at 75 ("Great") and 50 ("Needs work") determine the categorical label.
- The `calculateScore` utility attempts remote scoring first, falling back to local calculation if the API fails.

## Frequently Asked Questions

### What is the mathematical formula used by React Doctor's scoring system?

The formula is `score = max(0, round(100 - (errorCount × 1.5) - (warningCount × 0.75)))`. This calculation occurs in the `scoreFromRuleCounts` function within [`packages/react-doctor/src/utils/calculate-score-locally.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/utils/calculate-score-locally.ts), where `errorCount` and `warningCount` represent unique rule violations only.

### How does React Doctor prevent the same rule from penalizing the score multiple times?

The `collectUniqueRuleSets` function uses JavaScript `Set` objects to track unique rule keys formatted as `${plugin}/${rule}`. Because Sets automatically discard duplicate entries, multiple diagnostics from the same rule only contribute once to either the `errorRules` or `warningRules` collection.

### Can I use React Doctor's scoring algorithm offline?

Yes. If the remote scoring API defined by `SCORE_API_URL` is unreachable, the `calculateScore` function automatically falls back to `calculateScoreLocally`. You can also import and call `calculateScoreLocally` directly to ensure deterministic scoring without any network dependency.

### Where are the penalty constants defined in the codebase?

All scoring constants—including `ERROR_RULE_PENALTY` (1.5), `WARNING_RULE_PENALTY` (0.75), `PERFECT_SCORE` (100), `SCORE_GOOD_THRESHOLD` (75), and `SCORE_OK_THRESHOLD` (50)—are defined in [`packages/react-doctor/src/constants.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/constants.ts) and referenced by the scoring utilities.