Pređi na sadržaj
Meni
← Nazad na blog

Kako izračunavamo Elo rejting u našoj kartaškoj igri

Illustration of two card players with Elo rating calculations floating above, showing rating change formulas and stats

Usklađivanje rejtinga u takmičarskoj kartaškoj igri nije jednostavno. Razvijamo prilagođen Elo sistem za igru inspiriranu Sedmom i Sedmicama, s posebnim mjerama učinka.

Šta je novo u Elo sistemu?

Dinamički faktor K određuje koliko brzo se rejting mijenja. Seven prilagođava K vašem trenutnom rejtingu:

  • Ispod 1200 Elo: K = 40, brža prilagodba novih igrača.
  • 1200–1800 Elo: K = 32, uobičajena prilagodba.
  • 1800–2200 Elo: K = 24, stabilnije promjene.
  • Iznad 2200 Elo: K = 16, vrlo stabilne promjene.

Bonusi prema učinku: promjena nije samo pobjeda ili poraz.

  • +0.05 za svaku rundu osvojenu sa 16 bodova, najviše +0.15.
  • +0.1 za svaku rundu osvojenu sa 24 boda, najviše +0.2.
  • +0.03 za svaku rundu osvojenu s četiri boda i posljednjim štihom, najviše +0.09.

Kazne za loše poteze: svaki loš potez donosi malu kaznu od –0.02, do ukupno –0.3.

Prilagodba bonusa: ako izgubite, ali dobro igrate, bonusi se i dalje primjenjuju, s 10% svoje vrijednosti.

Zašto ovaj pristup?

Želimo da Elo odražava kako pobjeđujete ili gubite, a ne samo rezultat. Dobar učinak pri porazu treba vrijediti, dok neoprezna pobjeda s mnogo loših poteza ne treba pretjerano povećavati rejting.

public static void CalculateNewRatings(
ref int ratingA,
ref int ratingB,
bool playerAWon,
int badMovesA,
int badMovesB,
int wonBy16A,
int wonBy16B,
int wonBy24A,
int wonBy24B,
int wonBy4AndLastA,
int wonBy4AndLastB
)
{
    // K determines how sensitive the Elo rating is to each match outcome.
    // Higher K means faster rating changes (good for new players),
    // lower K means more stable ratings (good for experienced players).
    int kA = GetKFactor(ratingA);
    int kB = GetKFactor(ratingB);

    // Bonus and malus coefficients
    const float BonusPer16 = 0.05f;
    const float BonusPer24 = 0.1f;
    const float BonusPer4AndLast = 0.03f;
    const float MalusPerBadMove = 0.02f;

    // Caps
    const float MaxBonus16 = 0.15f;
    const float MaxBonus24 = 0.2f;
    const float MaxBonus4AndLast = 0.09f;
    const float MaxMalus = 0.3f;

    float baseScoreA = playerAWon ? 1f : 0f;
    float baseScoreB = 1f - baseScoreA;

    // Bonus for player A (full if won, 1/10 if lost)
    float multiplierA = playerAWon ? 1f : 0.1f;
    float bonusA =
        Mathf.Min(wonBy16A * BonusPer16, MaxBonus16) +
        Mathf.Min(wonBy24A * BonusPer24, MaxBonus24) +
        Mathf.Min(wonBy4AndLastA * BonusPer4AndLast, MaxBonus4AndLast);
    bonusA *= multiplierA;

    // Bonus for player B (full if won, 1/10 if lost)
    float multiplierB = playerAWon ? 0.1f : 1f;
    float bonusB =
        Mathf.Min(wonBy16B * BonusPer16, MaxBonus16) +
        Mathf.Min(wonBy24B * BonusPer24, MaxBonus24) +
        Mathf.Min(wonBy4AndLastB * BonusPer4AndLast, MaxBonus4AndLast);
    bonusB *= multiplierB;

    float malusA = Mathf.Min(badMovesA * MalusPerBadMove, MaxMalus);
    float malusB = Mathf.Min(badMovesB * MalusPerBadMove, MaxMalus);

    float adjustedScoreA = Mathf.Clamp(baseScoreA + bonusA - malusA, 0f, 1f);
    float adjustedScoreB = Mathf.Clamp(baseScoreB + bonusB - malusB, 0f, 1f);

    double expectedA = 1.0 / (1.0 + Math.Pow(10, (ratingB - ratingA) / 400.0));
    double expectedB = 1.0 / (1.0 + Math.Pow(10, (ratingA - ratingB) / 400.0));

    //Debug.Log($"[ELO CALCULATION]");
    //Debug.Log($"Player A: baseScore={baseScoreA}, bonus={bonusA}, malus={malusA}, adjustedScore={adjustedScoreA}, expected={expectedA}");
    //Debug.Log($"Player B: baseScore={baseScoreB}, bonus={bonusB}, malus={malusB}, adjustedScore={adjustedScoreB}, expected={expectedB}");
    //Debug.Log($"Old Ratings - A: {ratingA}, B: {ratingB}");


    ratingA = (int)Math.Round(ratingA + kA * (adjustedScoreA - expectedA));
    ratingB = (int)Math.Round(ratingB + kB * (adjustedScoreB - expectedB));

    //Debug.Log($"New Ratings - A: {ratingA}, B: {ratingB}");
}

private static int GetKFactor(int rating)
{
    if (rating < 1200) return 40;       // Fast adaptation for new players
    if (rating < 1800) return 32;       // Balanced default for most players
    if (rating < 2200) return 24;       // More stable for advanced players
    return 16;                          // Very stable for top-ranked
}

Šta slijedi?

Ovaj sistem je eksperimentalan. Aktivno podešavamo koeficijente i možemo promijeniti:

  • Uticaj bonusa i kazni
  • Trenutak promjene vrijednosti K
  • Obradu timskih mečeva ili neriješenih rezultata

Želimo vaše povratne informacije! Djeluje li rejting pravedno? Jeste li nakon meča smatrali da promjena nije opravdana? Ostavite komentar ili nam se javite: vaše mišljenje pomaže unaprijediti sistem.

Leave a Comment

Scroll to Top