package me.desht.chesscraft.results; import me.desht.chesscraft.ChessCraft; /** * * Implements a sort-of-ELO ladder. Similar algorithm for adjusting player scores. * */ public class Ladder extends ResultViewBase { private static final int INITIAL_POS = 1000; /** * Create a new Ladder object. */ public Ladder(Results handler) { super(handler, "ladder"); } /** * Add one result to the ladder. * * @param re The ResultEntry to add */ @Override public void addResult(ResultEntry re) { applyRatingChange(re); } private void applyRatingChange(ResultEntry re) { int ratingW = getScore(re.getPlayerWhite()); int ratingB = getScore(re.getPlayerBlack()); float prob = getProbability(Math.abs(ratingW - ratingB)); float probW = ratingW > ratingB ? prob : 1 - prob; float probB = 1 - probW; // System.out.println(String.format("add result: %s %s %s %.2f %.2f", re.playerWhite, re.playerBlack, re.pgnResult, probW, probB)); if (re.getPgnResult().equals("1-0")) { setScore(re.getPlayerWhite(), ratingW + Math.round(getKfactor(ratingW) * (1 - probW))); setScore(re.getPlayerBlack(), ratingB + Math.round(getKfactor(ratingB) * (0 - probB))); } else if (re.getPgnResult().equals("0-1")) { setScore(re.getPlayerWhite(), ratingW + Math.round(getKfactor(ratingW) * (0 - probW))); setScore(re.getPlayerBlack(), ratingB + Math.round(getKfactor(ratingB) * (1 - probB))); } else { setScore(re.getPlayerWhite(), ratingW + Math.round(getKfactor(ratingW) * (0.5f - probW))); setScore(re.getPlayerBlack(), ratingB + Math.round(getKfactor(ratingB) * (0.5f - probB))); } } /** * Calculate win probability based on ratings difference. * Taken from FIDE handbook, section 8.0. * * @param diff Ratings difference * @return Win probability for higher-rated player */ private float getProbability(int diff) { if (diff >= 0 && diff <= 3) { return 0.50f; } else if (diff >= 4 && diff <= 10) { return 0.51f; } else if (diff >= 11 && diff <= 17) { return 0.52f; } else if (diff >= 18 && diff <= 25) { return 0.53f; } else if (diff >= 26 && diff <= 32) { return 0.54f; } else if (diff >= 33 && diff <= 39) { return 0.55f; } else if (diff >= 40 && diff <= 46) { return 0.56f; } else if (diff >= 47 && diff <= 53) { return 0.57f; } else if (diff >= 54 && diff <= 61) { return 0.58f; } else if (diff >= 62 && diff <= 68) { return 0.59f; } else if (diff >= 69 && diff <= 76) { return 0.60f; } else if (diff >= 77 && diff <= 83) { return 0.61f; } else if (diff >= 84 && diff <= 91) { return 0.62f; } else if (diff >= 92 && diff <= 98) { return 0.63f; } else if (diff >= 99 && diff <= 106) { return 0.64f; } else if (diff >= 107 && diff <= 113) { return 0.65f; } else if (diff >= 114 && diff <= 121) { return 0.66f; } else if (diff >= 122 && diff <= 129) { return 0.67f; } else if (diff >= 130 && diff <= 137) { return 0.68f; } else if (diff >= 138 && diff <= 145) { return 0.69f; } else if (diff >= 146 && diff <= 153) { return 0.70f; } else if (diff >= 154 && diff <= 162) { return 0.71f; } else if (diff >= 163 && diff <= 170) { return 0.72f; } else if (diff >= 171 && diff <= 179) { return 0.73f; } else if (diff >= 180 && diff <= 188) { return 0.74f; } else if (diff >= 189 && diff <= 197) { return 0.75f; } else if (diff >= 198 && diff <= 206) { return 0.76f; } else if (diff >= 207 && diff <= 215) { return 0.77f; } else if (diff >= 216 && diff <= 225) { return 0.78f; } else if (diff >= 226 && diff <= 235) { return 0.79f; } else if (diff >= 236 && diff <= 245) { return 0.80f; } else if (diff >= 246 && diff <= 256) { return 0.81f; } else if (diff >= 257 && diff <= 267) { return 0.82f; } else if (diff >= 268 && diff <= 278) { return 0.83f; } else if (diff >= 279 && diff <= 290) { return 0.84f; } else if (diff >= 291 && diff <= 302) { return 0.85f; } else if (diff >= 303 && diff <= 315) { return 0.86f; } else if (diff >= 316 && diff <= 328) { return 0.87f; } else if (diff >= 329 && diff <= 344) { return 0.88f; } else if (diff >= 345 && diff <= 357) { return 0.89f; } else if (diff >= 358 && diff <= 374) { return 0.90f; } else if (diff >= 375 && diff <= 391) { return 0.91f; } else if (diff >= 392 && diff <= 411) { return 0.92f; } else if (diff >= 412 && diff <= 432) { return 0.93f; } else if (diff >= 433 && diff <= 456) { return 0.94f; } else if (diff >= 457 && diff <= 484) { return 0.95f; } else if (diff >= 485 && diff <= 517) { return 0.96f; } else if (diff >= 518 && diff <= 559) { return 0.97f; } else if (diff >= 560 && diff <= 619) { return 0.98f; } else if (diff >= 620 && diff <= 735) { return 0.99f; } else { return 1.0f; } } @Override protected int getInitialScore() { return ChessCraft.getInstance().getConfig().getInt("ladder.initial_position", INITIAL_POS); } private int getKfactor(int rating) { if (rating < 2000) { return 32; } else if (rating < 2400) { return 16; } else { return 8; } } }