Skip to content

Report attainable coverage on tournament leaderboards - #5124

Draft
cemreinanc wants to merge 3 commits into
mainfrom
claude/attainable-coverage-3757
Draft

Report attainable coverage on tournament leaderboards#5124
cemreinanc wants to merge 3 commits into
mainfrom
claude/attainable-coverage-3757

Conversation

@cemreinanc

@cemreinanc cemreinanc commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR introduces the concept of "attainable coverage" to the scoring system, which represents the maximum coverage a forecaster could achieve on a question based on when it actually closed relative to its scheduled close time. This allows the system to fairly evaluate coverage on questions that resolve early.

Key Changes

  • New get_attainable_coverage() method on Question model that calculates the fraction of the scheduled forecasting window during which a question was actually open:

    • Returns 1.0 for questions that stay open until/past their scheduled close time
    • Returns < 1.0 for questions that close early (e.g., resolve before scheduled close)
    • Calculated as: (effective_close_time - open_time) / (scheduled_close_time - open_time)
  • Updated Contribution tracking to include attainable_coverage field alongside existing coverage field, populated only for successfully resolved questions

  • Enhanced coverage metrics in project contributions display:

    • Individual question coverage now shows both actual and attainable coverage: "X% (Y%)"
    • Added three new summary metrics:
      • Total Coverage: Average coverage across resolved questions
      • Total Attainable Coverage: Average attainable coverage across resolved questions
      • Effective Coverage: Question-weighted ratio of actual to attainable coverage
    • Updated column header from "coverage" to "Coverage (max)" for clarity
  • Updated leaderboard max_coverage calculation to use weighted attainable coverage instead of just question weights, ensuring coverage is measured against what was actually achievable

  • Added comprehensive test coverage for the new get_attainable_coverage() method with multiple scenarios (full window, early close, exact scheduled close)

  • Updated UI labels and help text in English translations to explain the new attainable coverage concept

Implementation Details

  • The attainable_coverage is only populated for successfully resolved questions (excludes ambiguous/unknown resolutions)
  • A helper function _get_attainable_coverage() ensures consistent logic across the codebase
  • The effective coverage metric uses weighted sums to account for question importance
  • Null/undefined coverage values are formatted as "-" for better UX

https://claude.ai/code/session_01NmzezEyuu7d2sX214hZWqZ

Summary by CodeRabbit

  • New Features
    • Added maximum, attainable, and effective coverage metrics to contribution views.
    • Per-question coverage now reflects the portion of the forecasting window when questions were available.
    • Added explanations for question-level and tournament-level coverage calculations.
  • Bug Fixes
    • Improved coverage calculations for resolved questions, including weighting and actual close times.
    • Updated leaderboard and contribution data to support attainable coverage when applicable.

The leaderboard coverage column now divides total coverage by the total
*attainable* coverage instead of by the raw question count. Questions that
close early (e.g. resolve before their scheduled close time) have a maximum
attainable coverage below 100%, so coverage is now measured against what was
actually attainable.

- Add Question.get_attainable_coverage() =
  (effective_close_time - open_time) / (scheduled_close_time - open_time).
- LeaderboardSerializer.get_max_coverage now sums attainable coverage weighted
  by question weight over successfully resolved questions.
- Expose attainable_coverage per contribution.
- "My Score" section: the Coverage column becomes "Coverage (max)" showing your
  coverage and the max attainable in parentheses, and the totals now show total
  coverage, total attainable coverage, and effective coverage (which matches the
  leaderboard value).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmzezEyuu7d2sX214hZWqZ
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c4c6a1a3-b3b2-49bd-b410-15cae0766b00

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Coverage calculations now account for early question closure. Scoring data exposes attainable coverage, and the contributions UI displays total, attainable, effective, and maximum coverage with updated explanations.

Changes

Coverage metrics

Layer / File(s) Summary
Attainable coverage calculation
questions/models.py, tests/unit/test_questions/test_models.py
Question.get_attainable_coverage() calculates the fraction of the scheduled window that a question remained open. Tests cover full and half-window availability.
Scoring data propagation
scoring/utils.py, scoring/serializers.py
Contributions include nullable attainable coverage. Leaderboard maximum coverage uses weighted attainable coverage for successful resolutions.
Contribution coverage display
front_end/src/types/scoring.ts, front_end/src/app/(main)/(leaderboards)/contributions/components/project_contributions.tsx, front_end/messages/en.json
The UI displays total, attainable, effective, and maximum coverage. Localization adds labels and explanations for the new metrics.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Question
  participant ScoringUtils
  participant LeaderboardSerializer
  participant ContributionsUI
  Question->>ScoringUtils: Calculate attainable coverage
  ScoringUtils->>LeaderboardSerializer: Include weighted coverage data
  LeaderboardSerializer-->>ContributionsUI: Serialize contribution metrics
  ContributionsUI->>ContributionsUI: Display total, attainable, effective, and maximum coverage
Loading

Possibly related issues

Possibly related PRs

  • Metaculus/metaculus#4537 — Both changes implement attainable or maximum coverage calculations and update coverage UI and localization.
  • Metaculus/metaculus#4681 — Both changes modify LeaderboardSerializer.get_max_coverage to use question coverage weights.

Suggested reviewers: hlbmtc, lsabor

Poem

A rabbit watched the questions close,
And measured time through every rose.
“Now attainable scores are clear,
With effective coverage hopping near!”
The leaderboard shines bright—
Metrics sorted just right.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: reporting attainable coverage on tournament leaderboards.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/attainable-coverage-3757

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cemreinanc
cemreinanc marked this pull request as draft August 8, 2026 07:28

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@front_end/messages/en.json`:
- Around line 927-929: Update the effectiveCoverageInfo translation to state
that both total coverage and total attainable coverage are weighted by each
question’s question_weight before division, while preserving the leaderboard
equivalence description.

In
`@front_end/src/app/`(main)/(leaderboards)/contributions/components/project_contributions.tsx:
- Around line 114-120: Update the attainable_coverage display branch in the
project contributions component to pass contribution.coverage directly to
formatPercent instead of coercing nullish values to 0. Preserve the existing
attainable coverage formatting and render null coverage as the formatter’s "-"
fallback.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 93321de6-2d38-40b5-bc0c-b2dec11b1b3b

📥 Commits

Reviewing files that changed from the base of the PR and between 983ccda and 48e4fcc.

📒 Files selected for processing (7)
  • front_end/messages/en.json
  • front_end/src/app/(main)/(leaderboards)/contributions/components/project_contributions.tsx
  • front_end/src/types/scoring.ts
  • questions/models.py
  • scoring/serializers.py
  • scoring/utils.py
  • tests/unit/test_questions/test_models.py

Comment thread front_end/messages/en.json Outdated
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

🚀 Preview Environment

Your preview environment is ready!

Resource Details
🌐 Preview URL https://metaculus-pr-5124-claude-attainable-coverage-375-preview.mtcl.cc
📦 Docker Image ghcr.io/metaculus/metaculus:claude-attainable-coverage-3757-f3e89d4
🗄️ PostgreSQL NeonDB branch preview/pr-5124-claude-attainable-coverage-375
Redis Fly Redis mtc-redis-pr-5124-claude-attainable-coverage-375

Details

  • Commit: f3e89d49739ef74134b6089f33b4cd4ed6e5e60c
  • Branch: claude/attainable-coverage-3757
  • Fly App: metaculus-pr-5124-claude-attainable-coverage-375

ℹ️ Preview Environment Info

Isolation:

  • PostgreSQL and Redis are fully isolated from production
  • Each PR gets its own database branch and Redis instance
  • Changes pushed to this PR will trigger a new deployment

Limitations:

  • Background workers and cron jobs are not deployed in preview environments
  • If you need to test background jobs, use Heroku staging environments

Cleanup:

  • This preview will be automatically destroyed when the PR is closed

The effectiveCoverageInfo help text described dividing unweighted sums, but
both sums are weighted by question weight. The weighting is required for the
value to match the tournament leaderboard, which computes coverage as
sum(coverage * question_weight) / sum(attainable_coverage * question_weight).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NmzezEyuu7d2sX214hZWqZ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants