preferans-rating-js

preferans user rating

This project is maintained by prefko

prefko

preferans-rating-js

build status codacy coverage dependencies npm Greenkeeper badge

A TypeScript/JavaScript library for calculating player rating changes in Preferans card games. This library implements a sophisticated rating algorithm that considers player performance, existing ratings, and game-specific parameters (bula) to determine fair rating adjustments after each game.

Documentation

TypeDoc documentation

Bula vs Final Score

It’s important to understand the distinction between “bula” and “final score” in Preferans:

Bula:

Final Score Calculation: The final score used in rating calculations is much more complex than just the final bula. It involves:

The score parameter in this library represents the final calculated score after all these complex scoring rules are applied, not the raw bula value.

Usage

const PrefRating = require("preferans-rating-js");

// Example: Three players with different ratings and final calculated scores
const player1 = {
    username: 'Pedja',
    rating: 1200,    // Current rating before the game
    score: -500      // Final calculated score (negative = good performance)
};

const player2 = {
    username: 'Marko', 
    rating: 1150,
    score: 40        // Final calculated score (positive = poor performance)
};

const player3 = {
    username: 'Johnny',
    rating: 1100,
    score: 460       // Final calculated score (positive = poor performance)
};

// Note: In Preferans scoring, final scores typically sum to zero: -500 + 40 + 460 = 0
const startingBula = 30; // The initial bula value for all players

// Calculate rating changes
const rating = new PrefRating(player1, player2, player3, startingBula);

// Get the results
const result = rating.rating;
console.log(result);
/*
Output:
{
  bula: 30,
  p1: { username: 'Pedja', score: -500, oldRating: 1200, rating: 1173, change: -27 },
  p2: { username: 'Marko', score: 40, oldRating: 1150, rating: 1152, change: 2 },
  p3: { username: 'Johnny', score: 460, oldRating: 1100, rating: 1125, change: 25 }
}
*/

API

Constructor

new PrefRating(player1, player2, player3, bula)

Parameters:

Returns: PrefRating instance

Properties

Detailed Example

To grasp the complex scoring system, consider this detailed example with a starting bula of 30:

Players: Pedja, Marko, Johnny

Final Papers:

Calculations:

Result:

Explanation:

Rating Algorithm

The rating system is inspired by chess ELO but adapted for 3-player games. The algorithm considers three main factors:

Step 1: Calculate D Values (Score Performance)

D₁₂ = (Player1.score - Player2.score) / bula
D₁₃ = (Player1.score - Player3.score) / bula  
D₂₃ = (Player2.score - Player3.score) / bula

This measures actual performance differences, normalized by game length (bula).

Step 2: Calculate T Values (Rating Expectations)

T₁₂ = (Player2.rating - Player1.rating) × 2.8 / 100
T₁₃ = (Player3.rating - Player1.rating) × 2.8 / 100
T₂₃ = (Player3.rating - Player2.rating) × 2.8 / 100

This represents expected performance based on rating differences. The constant 2.8 is the “magic number” that scales rating differences.

Step 3: Calculate N Values (Performance Bonus)

N₁₂ = (Player1.score < Player2.score) ? -bula/100 : +bula/100
N₁₃ = (Player1.score < Player3.score) ? -bula/100 : +bula/100
N₂₃ = (Player2.score < Player3.score) ? -bula/100 : +bula/100

This gives a small bonus/penalty based on who performed better (remember: lower score = better in Preferans).

Step 4: Combine and Average

C₁₂ = D₁₂ + T₁₂ + N₁₂
C₁₃ = D₁₃ + T₁₃ + N₁₃  
C₂₃ = D₂₃ + T₂₃ + N₂₃

Player1.change = round((C₁₂ + C₁₃) / 2)
Player2.change = round((-C₁₂ + C₂₃) / 2)
Player3.change = round((-C₁₃ + -C₂₃) / 2)

Example Calculation (Pedja/Marko/Johnny):

Key Insight: Pedja had the best performance (-500 score) but lost rating points because his high initial rating (1200) created high expectations that even his excellent performance couldn’t fully meet.

Differences from Chess ELO:

  1. 3 Players: Each player’s change considers performance against both opponents
  2. No Draws: Scores are always different (theoretically ties possible but extremely rare)
  3. Base Rating: Uses 1000 instead of chess’s 1200
  4. Score Normalization: Performance scaled by bula (game length)

Installation

npm install preferans-rating-js

Requirements