package hudson.plugins.cigame; import java.io.IOException; import java.util.Collection; import java.util.Comparator; import java.util.TreeSet; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.Action; import hudson.model.BuildListener; import hudson.model.User; import hudson.plugins.cigame.model.RuleBook; import hudson.plugins.cigame.model.ScoreCard; import hudson.scm.ChangeLogSet; import hudson.scm.ChangeLogSet.Entry; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Notifier; public class GamePublisher extends Notifier { @Override public GameDescriptor getDescriptor() { return (GameDescriptor) super.getDescriptor(); } @Override public boolean needsToRunAfterFinalized() { return true; } @Override public Action getProjectAction(AbstractProject<?, ?> project) { return null; } @Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { perform(build, getDescriptor().getRuleBook(), getDescriptor().getNamesAreCaseSensitive()); return true; } /** * Calculates score from the build and rule book and adds a Game action to the build. * @param build build to calculate points for * @param ruleBook rules used in calculation * @param usernameIsCasesensitive user names in Hudson are case insensitive. * @return true, if any user scores were updated; false, otherwise * @throws IOException thrown if there was a problem setting a user property */ boolean perform(AbstractBuild<?, ?> build, RuleBook ruleBook, boolean usernameIsCasesensitive) throws IOException { ScoreCard sc = new ScoreCard(); sc.record(build, ruleBook); ScoreCardAction action = new ScoreCardAction(sc, build); build.getActions().add(action); return updateUserScores(build.getChangeSet(), sc.getTotalPoints(), usernameIsCasesensitive); } /** * Add the score to the users that have committed code in the change set * * @param changeSet the change set, used to get users * @param score the score that the build was worth * @param usernameIsCasesensitive user names in Hudson are case insensitive. * @throws IOException thrown if the property could not be added to the user object. * @return true, if any user scores was updated; false, otherwise */ private boolean updateUserScores(ChangeLogSet<? extends Entry> changeSet, double score, boolean usernameIsCasesensitive) throws IOException { Collection<User> players = new TreeSet<User>(usernameIsCasesensitive ? null : new UsernameCaseinsensitiveComparator()); if (score != 0) { for (Entry entry : changeSet) { players.add(entry.getAuthor()); } for (User user : players) { UserScoreProperty property = user.getProperty(UserScoreProperty.class); if (property == null) { property = new UserScoreProperty(); user.addProperty(property); } if (property.isParticipatingInGame()) { property.setScore(property.getScore() + score); } user.save(); } } return (!players.isEmpty()); } public class UsernameCaseinsensitiveComparator implements Comparator<User> { public int compare(User arg0, User arg1) { return arg0.getId().compareToIgnoreCase(arg1.getId()); } } public BuildStepMonitor getRequiredMonitorService() { return BuildStepMonitor.BUILD; } }