()
35 | val pbs = acmap.getJSONArray(key)
36 | for(i in pbs.indices)
37 | pbList.add(pbs.getString(i))
38 | res[key] = pbList
39 | }
40 | }
41 | logger.info("获取vjudge用户${vjname}共${res.size}个oj的纪录")
42 | return res
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/jskills/Guard.java:
--------------------------------------------------------------------------------
1 | package jskills;
2 |
3 | /**
4 | * Verifies argument contracts.
5 | *
6 | * These are used until I figure out how to do this better in Java
7 | */
8 | public class Guard {
9 |
10 | /**
11 | * No instances allowed
12 | */
13 | private Guard() { }
14 |
15 | public static void argumentNotNull(Object value, String parameterName) {
16 | if (value == null) {
17 | throw new NullPointerException(parameterName);
18 | }
19 | }
20 |
21 | public static void argumentIsValidIndex(int index, int count, String parameterName) {
22 | if ((index < 0) || (index >= count)) {
23 | throw new IndexOutOfBoundsException(parameterName);
24 | }
25 | }
26 |
27 | public static void argumentInRangeInclusive(double value, double min, double max, String parameterName) {
28 | if ((value < min) || (value > max)) {
29 | throw new IndexOutOfBoundsException(parameterName);
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/IPlayer.java:
--------------------------------------------------------------------------------
1 | package jskills;
2 |
3 | public interface IPlayer { }
4 |
--------------------------------------------------------------------------------
/src/main/java/jskills/ISupportPartialPlay.java:
--------------------------------------------------------------------------------
1 | package jskills;
2 |
3 | /**
4 | * Indicates support for allowing partial play (where a player only plays a part
5 | * of the time).
6 | */
7 | public interface ISupportPartialPlay {
8 | /**
9 | * Indicates the percent of the time the player should be weighted where 0.0
10 | * indicates the player didn't play and 1.0 indicates the player played 100%
11 | * of the time.
12 | */
13 | public double getPartialPlayPercentage();
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/jskills/ISupportPartialUpdate.java:
--------------------------------------------------------------------------------
1 | package jskills;
2 |
3 | /**
4 | * Indicates support for allowing partial update (where a player only gets part
5 | * of the calculated skill update).
6 | */
7 | public interface ISupportPartialUpdate {
8 | /**
9 | * Indicated how much of a skill update a player should receive where 0.0
10 | * represents no update and 1.0 represents 100% of the update.
11 | */
12 | public double getPartialUpdatePercentage();
13 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/ITeam.java:
--------------------------------------------------------------------------------
1 | package jskills;
2 |
3 | import java.util.Map;
4 |
5 | public interface ITeam extends Map {
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/jskills/PairwiseComparison.java:
--------------------------------------------------------------------------------
1 | package jskills;
2 |
3 | import java.util.TreeMap;
4 |
5 | /**
6 | * Represents a comparison between two players.
7 | *
8 | * The actual values for the enum were chosen so that the also correspond to the
9 | * multiplier for updates to means.
10 | */
11 | public enum PairwiseComparison{
12 | WIN(1),
13 | DRAW(0),
14 | LOSE(-1);
15 |
16 | public final int multiplier;
17 |
18 | PairwiseComparison(int multiplier) { this.multiplier = multiplier; }
19 |
20 | private static TreeMap revmap = new TreeMap();
21 | static { for (PairwiseComparison pc : PairwiseComparison.values())
22 | revmap.put(pc.multiplier, pc);
23 | }
24 |
25 | public static PairwiseComparison fromMultiplier(int multiplier) {
26 | return revmap.get(multiplier);
27 | }
28 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/PartialPlay.java:
--------------------------------------------------------------------------------
1 | package jskills;
2 |
3 | public class PartialPlay {
4 |
5 | public static double getPartialPlayPercentage(Object player) {
6 | // If the player doesn't support the interface, assume 1.0 == 100%
7 | if (player instanceof ISupportPartialPlay) {
8 | double partialPlayPercentage = ((ISupportPartialPlay) player)
9 | .getPartialPlayPercentage();
10 |
11 | // HACK to get around bug near 0
12 | final double smallestPercentage = 0.0001;
13 | if (partialPlayPercentage < smallestPercentage) {
14 | partialPlayPercentage = smallestPercentage;
15 | }
16 |
17 | return partialPlayPercentage;
18 | }
19 | return 1.0;
20 | }
21 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/RankSorter.java:
--------------------------------------------------------------------------------
1 | package jskills;
2 |
3 | import java.util.*;
4 |
5 | /**
6 | * Helper class to sort ranks in non-decreasing order.
7 | */
8 | public class RankSorter {
9 |
10 | /**
11 | * Returns a list of all the elements in items, sorted in non-descending
12 | * order, according to itemRanks. Uses a stable sort, and also sorts
13 | * itemRanks (in place)
14 | *
15 | * @param items
16 | * The items to sort according to the order specified by ranks.
17 | * @param itemRanks
18 | * The ranks for each item where 1 is first place.
19 | * @return the items sorted according to their ranks
20 | */
21 | public static List sort(Collection items, int[] itemRanks) {
22 | Guard.argumentNotNull(items, "items");
23 | Guard.argumentNotNull(itemRanks, "itemRanks");
24 |
25 | int lastObserverdRank = 0;
26 | boolean needToSort = false;
27 |
28 | for (int currentRank : itemRanks) {
29 | // We're expecting ranks to go up (e.g. 1, 2, 2, 3, ...)
30 | // If it goes down, then we've got to sort it.
31 | if (currentRank < lastObserverdRank) {
32 | needToSort = true;
33 | break;
34 | }
35 |
36 | lastObserverdRank = currentRank;
37 | }
38 |
39 | // Don't bother doing more work, it's already in a good order
40 | if (!needToSort) return new ArrayList(items);
41 |
42 | // Get the existing items as an indexable list.
43 | List itemsInList = new ArrayList(items);
44 |
45 | // item -> rank
46 | final Map itemToRank = new HashMap();
47 | for (int i = 0; i < itemsInList.size(); i++)
48 | itemToRank.put(itemsInList.get(i), itemRanks[i]);
49 |
50 | Collections.sort(itemsInList, new Comparator() {
51 | public int compare(T o1, T o2) {
52 | return itemToRank.get(o1).compareTo(itemToRank.get(o2));
53 | }
54 | });
55 |
56 | Arrays.sort(itemRanks);
57 | return itemsInList;
58 | }
59 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/SkillCalculator.java:
--------------------------------------------------------------------------------
1 | package jskills;
2 |
3 | import jskills.numerics.Range;
4 |
5 | import java.util.Collection;
6 | import java.util.EnumSet;
7 | import java.util.Map;
8 |
9 | /**
10 | * Base class for all skill calculator implementations.
11 | */
12 | public abstract class SkillCalculator {
13 |
14 | public enum SupportedOptions { PartialPlay, PartialUpdate }
15 |
16 | private final EnumSet supportedOptions;
17 | private final Range playersPerTeamAllowed;
18 | private final Range totalTeamsAllowed;
19 |
20 | protected SkillCalculator(EnumSet supportedOptions,
21 | Range totalTeamsAllowed,
22 | Range playerPerTeamAllowed) {
23 | this.supportedOptions = supportedOptions;
24 | this.totalTeamsAllowed = totalTeamsAllowed;
25 | this.playersPerTeamAllowed = playerPerTeamAllowed;
26 | }
27 |
28 | public boolean isSupported(SupportedOptions option) {
29 | return supportedOptions.contains(option);
30 | }
31 |
32 | /**
33 | * Calculates new ratings based on the prior ratings and team ranks.
34 | *
35 | * @param gameInfo Parameters for the game.
36 | * @param teams A mapping of team players and their ratings.
37 | * @param teamRanks The ranks of the teams where 1 is first place. For a tie, repeat the number (e.g. 1, 2, 2)
38 | * @return All the players and their new ratings.
39 | */
40 | public abstract Map calculateNewRatings(GameInfo gameInfo,
41 | Collection teams, int... teamRanks);
42 |
43 | /**
44 | * Calculates the match quality as the likelihood of all teams drawing.
45 | *
46 | * @param gameInfo Parameters for the game.
47 | * @param teams A mapping of team players and their ratings.
48 | * @return The quality of the match between the teams as a percentage (0% = bad, 100% = well matched).
49 | */
50 | public abstract double calculateMatchQuality(GameInfo gameInfo, Collection teams);
51 |
52 | protected void validateTeamCountAndPlayersCountPerTeam(Collection teams) {
53 | validateTeamCountAndPlayersCountPerTeam(teams, totalTeamsAllowed, playersPerTeamAllowed);
54 | }
55 |
56 | private static void validateTeamCountAndPlayersCountPerTeam(Collection teams,
57 | Range totalTeams,
58 | Range playersPerTeam) {
59 | Guard.argumentNotNull(teams, "teams");
60 | int countOfTeams = 0;
61 | for (ITeam currentTeam : teams) {
62 | if (!playersPerTeam.isInRange(currentTeam.size())) {
63 | throw new IllegalArgumentException();
64 | }
65 | countOfTeams++;
66 | }
67 |
68 | if (!totalTeams.isInRange(countOfTeams)) {
69 | throw new IllegalArgumentException();
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/Team.java:
--------------------------------------------------------------------------------
1 | package jskills;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collection;
5 | import java.util.HashMap;
6 | import java.util.List;
7 |
8 | /**
9 | * Helper class for working with a single team.
10 | */
11 | public class Team extends HashMap implements ITeam {
12 |
13 | /** Generated UID for serialization **/
14 | private static final long serialVersionUID = -5274158841312594600L;
15 |
16 | /**
17 | * Constructs a new team.
18 | */
19 | public Team() { }
20 |
21 | /**
22 | * Constructs a Team and populates it with the specified player.
23 | *
24 | * @param player The player to add.
25 | * @param rating The rating of the player.
26 | */
27 | public Team(IPlayer player, Rating rating) { addPlayer(player, rating); }
28 |
29 | /**
30 | * Adds the player to the team.
31 | *
32 | * @param player The player to add.
33 | * @param rating The rating of the player
34 | * @return The instance of the team (for chaining convenience).
35 | */
36 | public Team addPlayer(IPlayer player, Rating rating) {
37 | put(player, rating);
38 | return this;
39 | }
40 |
41 | /**
42 | * Concatenates multiple teams into a list of teams.
43 | *
44 | * @param teams The teams to concatenate together.
45 | * @return A sequence of teams.
46 | */
47 | public static Collection concat(ITeam... teams) {
48 | List teamslist = new ArrayList();
49 | for (ITeam team : teams) teamslist.add(team);
50 | return teamslist;
51 | }
52 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/TrueSkillCalculator.java:
--------------------------------------------------------------------------------
1 | package jskills;
2 |
3 | import jskills.trueskill.FactorGraphTrueSkillCalculator;
4 |
5 | import java.util.Collection;
6 | import java.util.Map;
7 |
8 | /**
9 | * Calculates a TrueSkill rating using {@link FactorGraphTrueSkillCalculator}.
10 | */
11 | public class TrueSkillCalculator {
12 |
13 | /** Static usage only **/ private TrueSkillCalculator() {}
14 | // Keep a singleton around
15 | private static final SkillCalculator calculator = new FactorGraphTrueSkillCalculator();
16 |
17 | /**
18 | * Calculates new ratings based on the prior ratings and team ranks.
19 | *
20 | * @param gameInfo Parameters for the game.
21 | * @param teams A mapping of team players and their ratings.
22 | * @param teamRanks The ranks of the teams where 1 is first place. For a tie, repeat the number (e.g. 1, 2, 2)
23 | * @return All the players and their new ratings.
24 | */
25 | public static Map calculateNewRatings(GameInfo gameInfo, Collection teams, int... teamRanks) {
26 | // Just punt the work to the full implementation
27 | return calculator.calculateNewRatings(gameInfo, teams, teamRanks);
28 | }
29 |
30 | /**
31 | * Calculates the match quality as the likelihood of all teams drawing.
32 | *
33 | * @param gameInfo Parameters for the game.
34 | * @param teams A mapping of team players and their ratings.
35 | * @return The match quality as a percentage (between 0.0 and 1.0).
36 | */
37 | public static double calculateMatchQuality(GameInfo gameInfo, Collection teams) {
38 | // Just punt the work to the full implementation
39 | return calculator.calculateMatchQuality(gameInfo, teams);
40 | }
41 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/elo/EloRating.java:
--------------------------------------------------------------------------------
1 | package jskills.elo;
2 |
3 | import jskills.Rating;
4 |
5 | /**
6 | * An Elo rating represented by a single number (mean).
7 | */
8 | public class EloRating extends Rating {
9 | public EloRating(double rating) { super(rating, 0); }
10 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/elo/FideEloCalculator.java:
--------------------------------------------------------------------------------
1 | package jskills.elo;
2 |
3 | import jskills.GameInfo;
4 |
5 | /**
6 | * Including ELO's scheme as a simple comparison. See
7 | * http://en.wikipedia.org/wiki/Elo_rating_system#Theory for more details
8 | */
9 | public class FideEloCalculator extends TwoPlayerEloCalculator {
10 |
11 | public FideEloCalculator() { this(new FideKFactor()); }
12 |
13 | public FideEloCalculator(FideKFactor kFactor) { super(kFactor); }
14 |
15 | @Override
16 | protected double getPlayerWinProbability(GameInfo gameInfo, double playerRating, double opponentRating) {
17 | double ratingDifference = opponentRating - playerRating;
18 |
19 | return 1.0 /
20 | (1.0 + Math.pow(10.0, ratingDifference / (2 * gameInfo.getBeta())));
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/elo/FideKFactor.java:
--------------------------------------------------------------------------------
1 | package jskills.elo;
2 |
3 | /** @see http://ratings.fide.com/calculator_rtd.phtml for details **/
4 | public class FideKFactor extends KFactor {
5 |
6 | public FideKFactor() { super(-1.); }
7 |
8 | public double getValueForRating(double rating) {
9 | if (rating < 2400) return 15;
10 | return 10;
11 | }
12 |
13 | /** Indicates someone who has played less than 30 games. **/
14 | public static class Provisional extends FideKFactor {
15 |
16 | public Provisional() { super(); }
17 |
18 | @Override
19 | public double getValueForRating(double rating) { return 25; }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/elo/GaussianEloCalculator.java:
--------------------------------------------------------------------------------
1 | package jskills.elo;
2 |
3 | import jskills.GameInfo;
4 | import jskills.numerics.GaussianDistribution;
5 |
6 | public class GaussianEloCalculator extends TwoPlayerEloCalculator {
7 | // From the paper
8 | private static final KFactor StableKFactor = new KFactor(24);
9 |
10 | public GaussianEloCalculator() { super(StableKFactor); }
11 |
12 | @Override
13 | protected double getPlayerWinProbability(GameInfo gameInfo,
14 | double playerRating, double opponentRating) {
15 | double ratingDifference = playerRating - opponentRating;
16 |
17 | // See equation 1.1 in the TrueSkill paper
18 | return GaussianDistribution.cumulativeTo(
19 | ratingDifference / (Math.sqrt(2) * gameInfo.getBeta()));
20 | }
21 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/elo/GaussianKFactor.java:
--------------------------------------------------------------------------------
1 | package jskills.elo;
2 |
3 | import jskills.GameInfo;
4 |
5 | public class GaussianKFactor extends KFactor {
6 | // From paper
7 | static final double StableDynamicsKFactor = 24.0;
8 |
9 | public GaussianKFactor() { super(StableDynamicsKFactor); }
10 |
11 | public GaussianKFactor(GameInfo gameInfo, double latestGameWeightingFactor) {
12 | super(latestGameWeightingFactor * gameInfo.getBeta()
13 | * Math.sqrt(Math.PI));
14 | }
15 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/elo/KFactor.java:
--------------------------------------------------------------------------------
1 | package jskills.elo;
2 |
3 | public class KFactor {
4 | private final double value;
5 |
6 | public KFactor(double exactKFactor) { value = exactKFactor; }
7 |
8 | public double getValueForRating(double rating) { return value; }
9 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/factorgraphs/DefaultVariable.java:
--------------------------------------------------------------------------------
1 | package jskills.factorgraphs;
2 |
3 | public class DefaultVariable extends Variable {
4 |
5 | public DefaultVariable() { super(null, "Default"); }
6 |
7 | @Override
8 | public void setValue(TValue value) {
9 | throw new UnsupportedOperationException();
10 | }
11 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/factorgraphs/Factor.java:
--------------------------------------------------------------------------------
1 | package jskills.factorgraphs;
2 |
3 | import java.util.*;
4 |
5 | import static jskills.Guard.argumentIsValidIndex;
6 |
7 | public abstract class Factor {
8 |
9 | protected final List> messages = new ArrayList>();
10 |
11 | private final Map, Variable> messageToVariableBinding =
12 | new HashMap, Variable>();
13 |
14 | private final String name;
15 | protected final List> variables = new ArrayList>();
16 |
17 | protected Factor(String name) { this.name = "Factor[" + name + "]"; }
18 |
19 | /** Returns the log-normalization constant of that factor **/
20 | public abstract double getLogNormalization();
21 |
22 | /** Returns the number of messages that the factor has **/
23 | public int getNumberOfMessages() { return messages.size(); }
24 |
25 | protected List> getVariables() {
26 | return Collections.unmodifiableList(variables);
27 | }
28 |
29 | protected List> getMessages() {
30 | return Collections.unmodifiableList(messages);
31 | }
32 |
33 | /** Update the message and marginal of the i-th variable that the factor is connected to **/
34 | public double updateMessage(int messageIndex) {
35 | argumentIsValidIndex(messageIndex, messages.size(), "messageIndex");
36 | return updateMessage(messages.get(messageIndex), messageToVariableBinding.get(messages.get(messageIndex)));
37 | }
38 |
39 | protected double updateMessage(Message message, Variable variable) {
40 | throw new UnsupportedOperationException();
41 | }
42 |
43 | /** Resets the marginal of the variables a factor is connected to **/
44 | public void ResetMarginals() {
45 | for(Variable variable : messageToVariableBinding.values())
46 | variable.resetToPrior();
47 | }
48 |
49 | /**
50 | * Sends the ith message to the marginal and returns the log-normalization
51 | * constant
52 | **/
53 | public double sendMessage(int messageIndex) {
54 | argumentIsValidIndex(messageIndex, messages.size(), "messageIndex");
55 |
56 | Message message = messages.get(messageIndex);
57 | Variable variable = messageToVariableBinding.get(message);
58 | return sendMessage(message, variable);
59 | }
60 |
61 | protected abstract double sendMessage(Message message, Variable variable);
62 |
63 | public abstract Message createVariableToMessageBinding(Variable variable);
64 |
65 | protected Message createVariableToMessageBinding(Variable variable, Message message) {
66 | messages.add(message);
67 | messageToVariableBinding.put(message, variable);
68 | variables.add(variable);
69 |
70 | return message;
71 | }
72 |
73 | @Override
74 | public String toString() { return name != null ? name : super.toString(); }
75 | }
--------------------------------------------------------------------------------
/src/main/java/jskills/factorgraphs/FactorGraph.java:
--------------------------------------------------------------------------------
1 | package jskills.factorgraphs;
2 |
3 | public abstract class FactorGraph> { }
--------------------------------------------------------------------------------
/src/main/java/jskills/factorgraphs/FactorGraphLayer.java:
--------------------------------------------------------------------------------
1 | package jskills.factorgraphs;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collection;
5 | import java.util.List;
6 |
7 | public abstract class FactorGraphLayer, TValue,
8 | TBaseVariable extends Variable, TInputVariable extends Variable, TFactor extends Factor,
9 | TOutputVariable extends Variable> extends FactorGraphLayerBase {
10 |
11 | private final List localFactors;
12 | private final List