statistics/src/main/java/cz/xelfi/quoridor/statistics/EloList.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 14 Sep 2010 08:56:13 +0200
changeset 264 d60370059c3c
parent 222 d783bb2a7956
permissions -rw-r--r--
Changing headers to GPLv3
     1 /*
     2  * Quoridor server and related libraries
     3  * Copyright (C) 2009-2010 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, either version 3 of the License.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. Look for COPYING file in the top folder.
    16  * If not, see http://www.gnu.org/licenses/.
    17  */
    18 
    19 package cz.xelfi.quoridor.statistics;
    20 
    21 import java.util.Map;
    22 import java.util.HashMap;
    23 import java.util.List;
    24 import java.util.Collections;
    25 import java.util.ArrayList;
    26 import javax.xml.bind.annotation.XmlElement;
    27 import javax.xml.bind.annotation.XmlAttribute;
    28 import javax.xml.bind.annotation.XmlElementWrapper;
    29 import javax.xml.bind.annotation.XmlRootElement;
    30 import javax.xml.bind.annotation.XmlAccessType;
    31 import javax.xml.bind.annotation.XmlAccessorType;
    32 /**
    33  *
    34  * @author Martin Rexa
    35  */
    36 @XmlRootElement
    37 @XmlAccessorType(XmlAccessType.FIELD)
    38 public class EloList {
    39     static int INITIAL_ELO = 1250;
    40     static int MAX_ELO_DIFF = 400;
    41     static int KVAL_START = 25;
    42     static int KVAL_FOLLOW = 10;
    43     static int KVAL_LIMIT = 30;
    44 
    45     Map<String, Double> players;
    46     Map<String, Integer> playerGames;
    47     long published = 0;
    48     boolean originalList;
    49 
    50 
    51     public EloList () {
    52         players = new HashMap<String, Double>();
    53         playerGames = new HashMap<String, Integer>();
    54         originalList = true;
    55     }
    56 
    57     public EloList(EloList src){
    58         this.players = new HashMap<String, Double>(src.players);
    59         this.playerGames = new HashMap<String, Integer>(src.playerGames);
    60         originalList = false;
    61     }
    62 
    63     public void setEndDate(long endDate){
    64         this.published = endDate;
    65     }
    66 
    67     public long getEndDate(){
    68         return this.published;
    69     }
    70 
    71     @XmlElementWrapper(name="elolist")
    72     @XmlElement(name="item")
    73     public List<EloEntry> getFinalList(){
    74         List<EloEntry> finalList = new ArrayList<EloEntry>();
    75         for (Map.Entry<String, Double> player : players.entrySet()){
    76             finalList.add(new EloEntry(player.getKey(), player.getValue(), playerGames.get(player.getKey())));
    77         }
    78         Collections.sort(finalList, EloEntry.BEST_FIRST);
    79         return finalList;
    80     }
    81 
    82     public EloList putResult(String winner, String looser){
    83         double wElo = getElo(winner);
    84         double lElo = getElo(looser);
    85 
    86         double eloDiff = wElo - lElo;
    87         if(eloDiff < - MAX_ELO_DIFF)
    88             eloDiff = - MAX_ELO_DIFF;
    89         if(eloDiff > MAX_ELO_DIFF)
    90             eloDiff = MAX_ELO_DIFF;
    91 
    92         double wDiff = Math.round(100 * getKVal(winner) * (1 - (1 / (1 + Math.pow(10, -eloDiff / MAX_ELO_DIFF)))));
    93         wDiff /= 100.0;
    94         double lDiff = Math.round(100 * getKVal(looser) * (0 - (1 / (1 + Math.pow(10, eloDiff / MAX_ELO_DIFF)))));
    95         lDiff /= 100.0;
    96 
    97         players.put(winner, wElo + wDiff);
    98         players.put(looser, lElo + lDiff);
    99         return this;
   100     }
   101     
   102     public double getElo(String player){
   103         Double elo = players.get(player);
   104         return (elo == null) ? INITIAL_ELO : elo;
   105     }
   106     
   107     private int getKVal(String player){
   108         Integer games = playerGames.get(player);
   109         int g = (games == null) ? 0 : games;
   110         // Side effect, method should not be called more times for the same game/player
   111         playerGames.put(player, g + 1);
   112         return g < KVAL_LIMIT ? KVAL_START : KVAL_FOLLOW;
   113     }
   114 
   115 }