Skip to content

A flexible and efficient TypeScript library for ranking items based on pairwise comparisons using an Elo-like rating system.

License

Notifications You must be signed in to change notification settings

SouthBridgeAI/eloranker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

7 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Ranker

A robust and flexible TypeScript library for ranking items based on pairwise comparisons using an advanced Elo-like rating system.

Table of Contents

Features

  • ๐Ÿš€ Easy-to-use API for managing rankable items and their comparisons
  • โš™๏ธ Highly configurable ranking parameters
  • ๐Ÿง  Intelligent calculation of optimal next comparison
  • ๐Ÿ“Š Comprehensive progress tracking for ranking stability
  • ๐Ÿ“ˆ Detailed item statistics and historical data
  • ๐Ÿ”ง Full TypeScript support with type definitions
  • ๐Ÿงฎ Transparent mathematical model with customizable parameters

Installation

Install Ranker using npm:

npm install ranker

Or using yarn:

yarn add ranker

Quick Start

Get up and running with Ranker in just a few lines of code:

import { Ranker, RankableItem, ComparisonResult } from "eloranker";

// Initialize items
const initialItems: RankableItem[] = [
  { id: "item1", initialRating: 1500 },
  { id: "item2", initialRating: 1500 },
  { id: "item3", initialRating: 1500 },
];

// Create a new Ranker instance
const ranker = new Ranker(initialItems, { kFactor: 32 });

// Add a comparison result
const result: ComparisonResult = {
  itemId1: "item1",
  itemId2: "item2",
  result: "win",
  timestamp: Date.now(),
};

const ratingDelta = ranker.addComparisonResult(result);
console.log(`Rating change: ${ratingDelta}`);

// Get current rankings
const rankings = ranker.getRankings();
console.log("Current rankings:", rankings);

Configuration

Customize Ranker's behavior with the following configuration options:

RankerConfig

Parameter Type Default Description
kFactor number 32 Determines the maximum rating change per comparison
minimumComparisons number 20 Minimum comparisons before considering an item's ranking stable
defaultInitialRating number 1500 Starting rating for new items
minRating number 0 Minimum possible rating for any item

Example configuration:

const ranker = new Ranker(initialItems, {
  kFactor: 24,
  minimumComparisons: 30,
  defaultInitialRating: 1600,
  minRating: 100,
});

Effects of Parameters

  • kFactor: Higher values make the system more responsive but potentially volatile. Lower values provide more stability but slower adaptation.
  • minimumComparisons: Increasing this value requires more data for stability, potentially increasing accuracy but increasing number of comparisons.
  • defaultInitialRating: Adjust based on prior knowledge about the general strength of new items.
  • minRating: Prevents extremely low ratings, which may be desirable in some applications.

Progress Tracking

Monitor ranking stability with the getProgress method:

const progress = ranker.getProgress({
  ratingChangeThreshold: 5,
  stableComparisonsThreshold: 10,
});
console.log(`Ranking progress: ${progress * 100}%`);

ProgressParams

Parameter Type Description
ratingChangeThreshold number Maximum allowed rating change for stability
stableComparisonsThreshold number Number of recent comparisons to check
  • Lower ratingChangeThreshold increases accuracy but slows stabilization.
  • Higher stableComparisonsThreshold increases confidence but takes longer to achieve.

API Reference

Ranker Class

Constructor

constructor(initialItems: RankableItem[], config: Partial<RankerConfig>)

Methods

Method Description Return Type
addItem(id: string, initialRating?: number) Add a new item to the ranking system void
removeItem(id: string) Remove an item from the ranking system void
addComparisonResult(result: ComparisonResult) Add a new comparison result number (rating delta)
getNextComparison() Get the optimal next comparison [string, string] | null
getItemStats(id: string) Get statistics for a specific item RankableItem
getRankings() Get current rankings of all items RankableItem[]
getItemCount() Get the total number of items number
getAllItems() Get all items in the system RankableItem[]
getProgress(params: ProgressParams) Get the current progress/stability of rankings number
getItemHistory(id: string) Get rating history for an item Array<{ rating: number; timestamp: number }>

Types

type RankableItem = {
  id: string;
  initialRating: number;
  currentRating: number;
  comparisons: number;
  wins: number;
  losses: number;
  ties: number;
  lastComparisonTime: number | null;
  ratingHistory: Array<{ rating: number; timestamp: number }>;
};

type ComparisonResult = {
  itemId1: string;
  itemId2: string;
  result: "win" | "loss" | "tie";
  timestamp: number;
  metadata?: any;
};

type RankerConfig = {
  kFactor: number;
  minimumComparisons: number;
  defaultInitialRating: number;
  minRating: number;
};

type ProgressParams = {
  ratingChangeThreshold: number;
  stableComparisonsThreshold: number;
};

Advanced Usage

Batch Processing

For systems with many items, implement batched processing:

const allItems = ranker.getAllItems();
const batchSize = 100;

for (let i = 0; i < allItems.length; i += batchSize) {
  const batch = allItems.slice(i, i + batchSize);
  // Process batch...
}

Rating Delta Analysis

Use the rating delta to trigger events or updates:

const SIGNIFICANT_CHANGE_THRESHOLD = 50;

const ratingDelta = ranker.addComparisonResult(result);
if (ratingDelta > SIGNIFICANT_CHANGE_THRESHOLD) {
  console.log("Significant ranking change detected!");
  // Trigger updates, notifications, etc.
}

Mathematical Foundation

Ranker uses an advanced Elo-like rating system. Here are the key equations:

  1. Expected Score Calculation:

    The expected score for player A when competing against player B is:

    $E(A) = \frac{1}{1 + 10^{(R_B - R_A) / 400}}$

    Where $R_A$ and $R_B$ are the current ratings of players A and B.

  2. Rating Update:

    After a comparison, ratings are updated using:

    $R_{new} = R_{old} + K \cdot (S - E)$

    Where:

    • $R_{new}$ is the new rating
    • $R_{old}$ is the old rating
    • $K$ is the k-factor (configurable)
    • $S$ is the actual score (1 for win, 0.5 for tie, 0 for loss)
    • $E$ is the expected score from step 1
  3. Rating Delta:

    The rating delta returned by addComparisonResult is:

    $\Delta = |R_{new_A} - R_{old_A}| + |R_{new_B} - R_{old_B}|$

    This represents the total change in ratings for both items.

These equations ensure:

  • Winning against a higher-rated opponent yields a larger rating increase.
  • Losing against a lower-rated opponent results in a larger rating decrease.
  • The k-factor controls the maximum possible change from a single comparison.

Contributing

We welcome contributions to Ranker! Here's how you can help:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

About

A flexible and efficient TypeScript library for ranking items based on pairwise comparisons using an Elo-like rating system.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published