/*
Copyright (C) 2008,2009 Martin Günther <mintar@gmx.de>
This file is part of GgpRatingSystem.
GgpRatingSystem is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GgpRatingSystem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GgpRatingSystem. If not, see <http://www.gnu.org/licenses/>.
*/
package ggpratingsystem;
import ggpratingsystem.output.CSVRatingsWriter;
import ggpratingsystem.output.CachingOutputBuilder;
import ggpratingsystem.output.DirectOutputBuilder;
import ggpratingsystem.output.GnuPlotRatingsWriter;
import ggpratingsystem.output.HtmlOutputBuilder;
import ggpratingsystem.output.OutputBuilder;
import ggpratingsystem.output.ValidatingOutputBuilder;
import ggpratingsystem.ratingsystems.RatingException;
import ggpratingsystem.ratingsystems.RatingFactory;
import ggpratingsystem.ratingsystems.RatingStrategy;
import ggpratingsystem.ratingsystems.RatingSystemType;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class holds the configuration of currently enabled
* - Strategies,
* - GameInfos, and
* - Ratings.
*
* Also, it acts as a factory for these classes.
*
* Finally, it is responsible for
* - updating GameInfos and
* - updating Ratings.
*
* Configuration acts as a facade to the whole GGP Subsystem,
* providing convenience methods for adding output builders etc.
*
* @author martin
*
*/
public class Configuration {
private static File outputDir = null;
private Map<RatingSystemType, List<OutputBuilder>> outputBuilders = new HashMap<RatingSystemType, List<OutputBuilder>>();
private Map<RatingSystemType, RatingStrategy> ratingSystems = new HashMap<RatingSystemType, RatingStrategy>();
private MatchSetReader matchSetReader;
private File previousRatings;
private PlayerSet playerSet;
private GameSet gameSet;
public Configuration() {
super();
this.playerSet = new PlayerSet();
this.gameSet = new GameSet();
}
public void addRatingSystem(RatingStrategy ratingSystem) {
ratingSystems.put(ratingSystem.getType(), ratingSystem);
}
/** Convenience method for adding a CSV Output Builder to a rating system.
* @param ignorePlayers */
public void addCSVOutputBuilder(RatingSystemType type, Set<Player> ignorePlayers) throws IOException {
Writer fileWriter = new FileWriter(new File(getOutputDir(),
getRatingSystem(type).idString() + ".csv"));
// one separate file for each RatingSystem
OutputBuilder csvOutputBuilder = new ValidatingOutputBuilder(
new DirectOutputBuilder(new CSVRatingsWriter(fileWriter), type));
OutputBuilder outputBuilder = new CachingOutputBuilder(
csvOutputBuilder, ignorePlayers);
outputBuilder.initialize(null);
addOutputBuilder(type, outputBuilder);
}
/** Convenience method for adding a Gnuplot Output Builder to a rating system.
* @param ignorePlayers */
public void addGnuplotOutputBuilder(RatingSystemType type, Set<Player> ignorePlayers) throws IOException {
Writer fileWriter = new FileWriter(new File(getOutputDir(),
getRatingSystem(type).idString() + ".dat"));
// one separate file for each RatingSystem
OutputBuilder gnuplotOutputBuilder = new ValidatingOutputBuilder(
new DirectOutputBuilder(new GnuPlotRatingsWriter(fileWriter), type));
OutputBuilder outputBuilder = new CachingOutputBuilder(
gnuplotOutputBuilder, ignorePlayers);
outputBuilder.initialize(null);
addOutputBuilder(type, outputBuilder);
}
public void addHtmlOutputBuilder(RatingSystemType type, Set<Player> ignorePlayers) throws IOException {
Writer fileWriter = new FileWriter(new File(getOutputDir(),
getRatingSystem(type).idString() + ".html"));
// one separate file for each RatingSystem
OutputBuilder htmlOutputBuilder = new ValidatingOutputBuilder(
new HtmlOutputBuilder(fileWriter, type));
OutputBuilder outputBuilder = new CachingOutputBuilder(
htmlOutputBuilder, ignorePlayers);
outputBuilder.initialize(null);
addOutputBuilder(type, outputBuilder);
}
public void addOutputBuilder(RatingSystemType type, OutputBuilder builder) {
if (!isEnabled(type)) {
throw new IllegalArgumentException("RatingSystemType " + type + " must be enabled before adding any OutputBuilders to it!");
}
List<OutputBuilder> builders = outputBuilders.get(type);
if (builders == null) {
builders = new LinkedList<OutputBuilder>();
outputBuilders.put(type, builders);
}
builders.add(builder);
}
public boolean isEnabled(RatingSystemType type) {
return ratingSystems.keySet().contains(type);
}
public Set<RatingSystemType> getEnabledRatingSystems() {
return ratingSystems.keySet();
}
public void run() throws IOException, RatingException {
// initialize the ratings
if (previousRatings != null) {
for (RatingStrategy ratingSystem : ratingSystems.values()) {
RatingSystemType type = ratingSystem.getType();
RatingFactory.initializeRatings(type, previousRatings, playerSet);
}
}
if (matchSetReader == null) {
throw new IllegalStateException("setMatchReader() must be called before calling run()!");
}
while (matchSetReader.hasNext()) {
MatchSet matchSet = matchSetReader.readMatchSet();
for (RatingStrategy ratingSystem : ratingSystems.values()) {
ratingSystem.update(matchSet);
RatingSystemType type = ratingSystem.getType();
List<OutputBuilder> builders = outputBuilders.get(type);
for (OutputBuilder builder : builders) {
builder.beginMatchSet(matchSet);
}
List<Match> matchList = matchSet.getMatches();
for (Match match : matchList) {
List<Player> playersInMatch = match.getPlayers();
for (Player player : playersInMatch) {
for (OutputBuilder builder : builders) {
builder.ratingUpdate(player.getRating(type));
}
}
}
for (OutputBuilder builder : builders) {
builder.endMatchSet(matchSet);
}
}
}
closeOutputBuilders();
}
public void closeOutputBuilders() {
for (List<OutputBuilder> builders : outputBuilders.values()) {
for (OutputBuilder builder : builders) {
builder.finish();
}
}
}
public RatingStrategy getRatingSystem(RatingSystemType type) {
return ratingSystems.get(type);
}
public void setMatchReader(MatchSetReader matchSetReader) {
this.matchSetReader = matchSetReader;
}
public void setPreviousRatings(File previousRatings) {
this.previousRatings = previousRatings;
}
public static void setOutputDir(File outputDir) throws IOException {
Configuration.outputDir = outputDir;
/* create output dir if it does not exist */
if (!outputDir.exists()) {
boolean success = outputDir.mkdirs();
if (!success) {
throw new IOException("Directory " + outputDir + " could not be created!");
}
}
}
public static File getOutputDir() {
if (outputDir == null) {
throw new IllegalStateException("outputDir must be set before accessing it!");
}
return outputDir;
}
public void setDebugLevel(Level level) {
Logger.getLogger("ggpratingsystem").setLevel(level);
}
public PlayerSet getPlayerSet() {
return playerSet;
}
public GameSet getGameSet() {
return gameSet;
}
}