在之前的博文中简单介绍了ELO Rating系统,依照其思想,博主写了一个对NBA球队的评分系统,代码如下
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import javax.sound.sampled.Line;
public class NBAEloRating {
//根据结果更新A和B的分数
public static void updateRatingScore(Team teamA, Team teamB, Boolean result){
final double DEFAULT_ELO_K_FACTOR = 24.0;
double exceptionA = 1 / (1 + Math.pow(10, (teamB.getRatingScore() - teamA.getRatingScore())/400));
double exceptionB = 1 - exceptionA;
double scoreA = -1;
double scoreB = -1;
if (result){
scoreA = 1;
scoreB = 0;
}else {
scoreA = 0;
scoreB = 1;
}
double newArating = teamA.getRatingScore() + DEFAULT_ELO_K_FACTOR * (scoreA - exceptionA);
double newBrating = teamB.getRatingScore() + DEFAULT_ELO_K_FACTOR * (scoreB - exceptionB);
teamA.setRatingScore(newArating);
teamB.setRatingScore(newBrating);
}
//输出每个球队的评分
public static void printRating(ArrayList<Team> teams){
for (int i = 0; i < teams.size(); i++){
System.out.print(teams.get(i).getTeamName() + ":");
System.out.print(teams.get(i).getRatingScore());
System.out.println();
}
}
public static void main(String[] args) throws IOException{
ArrayList<Team> teams = computeRatingScore();
String predictionFilePath = "res\\prediction";
prediction(teams, predictionFilePath);
}
//根据已有的评分,预测比赛结果
private static void prediction(ArrayList<Team> teams,
String predictionFilePath) throws IOException {
String outputPath = "output\\prediction";
BufferedReader in = new BufferedReader(new FileReader(predictionFilePath));
String game = in.readLine();
String output = "";
while(game != null){
String temp[] = game.split(" ");
int teamA = findTeamNo(teams, temp[0]);
int teamB = findTeamNo(teams, temp[1]);
double teamAWinPro = computeProbability(teams.get(teamA), teams.get(teamB));
output += game + " " + teamAWinPro + " " + (1 - teamAWinPro) + "\r\n";
game = in.readLine();
}
File f = new File(outputPath);
if(!f.exists()){
f.createNewFile();
}
FileWriter fw = new FileWriter(f.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(output);
bw.close();
}
private static double computeProbability(Team teamA, Team teamB) {
return 1 / (1 + Math.pow(10, (teamB.getRatingScore() - teamA.getRatingScore())/400));
}
public static ArrayList<Team> computeRatingScore() throws IOException{
ArrayList<Team> teams = initailize();
String dataFilePath = "res\\scoredata";
BufferedReader in = new BufferedReader(new FileReader(dataFilePath));
String result = in.readLine();
while(result != null){
String temp[] = result.split(" ");
int teamA = findTeamNo(teams, temp[0]);
int teamB = findTeamNo(teams, temp[1]);
boolean rslt = getResult(temp[2]);
updateRatingScore(teams.get(teamA), teams.get(teamB), rslt);
result = in.readLine();
}
sortByRatingScore(teams);
printRating(teams);
return teams;
}
private static void sortByRatingScore(ArrayList<Team> teams) {
Collections.sort(teams, new Comparator<Team>(){
@Override
public int compare(Team arg0, Team arg1) {
double scoreA = arg0.getRatingScore();
double scoreB = arg1.getRatingScore();
if (scoreA < scoreB)
return 1;
else {
return -1;
}
}
});
}
private static boolean getResult(String string) {
String tmp[] = string.split(":");
int teamA = Integer.parseInt(tmp[0]);
int teamB = Integer.parseInt(tmp[1]);
if (teamA > teamB)
return true;
else {
return false;
}
}
private static int findTeamNo(ArrayList<Team> teams, String teamName) {
int teamNo = 0;
while(!teamName.equals(teams.get(teamNo).getTeamName())){
teamNo++;
}
return teamNo;
}
//初始化所有球队的评分
private static ArrayList<Team> initailize() throws IOException {
ArrayList<Team> teams = new ArrayList<>();
String teamListFilePath = "res\\teamlist";
BufferedReader in = new BufferedReader(new FileReader(teamListFilePath));
String teamName = in.readLine();
while (teamName != null){
Team team = new Team(teamName, 1500);
teams.add(team);
teamName = in.readLine();
}
return teams;
}
}
public class Team {
private String teamName;
private double ratingScore;
public Team(String teamName, double ratingScore) {
super();
this.teamName = teamName;
this.ratingScore = ratingScore;
}
public String getTeamName() {
return teamName;
}
public void setTeamName(String teamName) {
this.teamName = teamName;
}
public double getRatingScore() {
return ratingScore;
}
public void setRatingScore(double ratingScore) {
this.ratingScore = ratingScore;
}
}
球队的历史交锋数据保存在scoredata文件中,这个是用爬虫程序抓取出来的,如果想要实现如上的预测系统可以自己写一个爬虫程序,抓取出数据的格式为:
球队A 球队B 比分
譬如:
小牛 马刺 80:99