diff --git a/core/src/main/java/tc/oc/pgm/command/MapPoolCommand.java b/core/src/main/java/tc/oc/pgm/command/MapPoolCommand.java index 4651835695..cbf5f74066 100644 --- a/core/src/main/java/tc/oc/pgm/command/MapPoolCommand.java +++ b/core/src/main/java/tc/oc/pgm/command/MapPoolCommand.java @@ -73,19 +73,18 @@ public void pool( int resultsPerPage = all ? maps.size() : 8; int pages = all ? 1 : (maps.size() + resultsPerPage - 1) / resultsPerPage; - Component mapPoolComponent = - TextFormatter.paginate( - text() - .append(translatable("pool.name")) - .append(text(" (", NamedTextColor.DARK_AQUA)) - .append(text(mapPool.getName(), NamedTextColor.AQUA)) - .append(text(")", NamedTextColor.DARK_AQUA)) - .build(), - page, - pages, - NamedTextColor.DARK_AQUA, - NamedTextColor.AQUA, - false); + Component mapPoolComponent = TextFormatter.paginate( + text() + .append(translatable("pool.name")) + .append(text(" (", NamedTextColor.DARK_AQUA)) + .append(text(mapPool.getName(), NamedTextColor.AQUA)) + .append(text(")", NamedTextColor.DARK_AQUA)) + .build(), + page, + pages, + NamedTextColor.DARK_AQUA, + NamedTextColor.AQUA, + false); Component title = TextFormatter.horizontalLineHeading(source, mapPoolComponent, NamedTextColor.BLUE, 250); @@ -96,7 +95,7 @@ public void pool( if (chance && votes != null) { double maxWeight = 0, currWeight; for (MapInfo map : votes.getMaps()) { - chances.put(map, currWeight = votes.mapPicker.getWeight(null, map, votes.getMapScore(map))); + chances.put(map, currWeight = votes.mapPicker.getWeight(null, map, votes.getVoteData(map))); maxWeight += currWeight; } double finalMaxWeight = maxWeight; @@ -106,23 +105,19 @@ public void pool( int nextPos = mapPool instanceof Rotation ? ((Rotation) mapPool).getNextPosition() : -1; if (order && votes != null) { - maps = - maps.stream() - .sorted( - Comparator.comparingDouble(chance ? chances::get : votes::getMapScore).reversed()) - .collect(Collectors.toList()); + maps = maps.stream() + .sorted(Comparator.comparingDouble(chance ? chances::get : votes::getMapScore) + .reversed()) + .collect(Collectors.toList()); } new PrettyPaginatedComponentResults(title, resultsPerPage) { @Override public Component format(MapInfo map, int index) { index++; - TextComponent.Builder entry = - text() - .append( - text( - index + ". ", - nextPos == index ? NamedTextColor.DARK_AQUA : NamedTextColor.WHITE)); + TextComponent.Builder entry = text() + .append(text( + index + ". ", nextPos == index ? NamedTextColor.DARK_AQUA : NamedTextColor.WHITE)); if (votes != null && scores) entry.append( text(SCORE_FORMAT.format(votes.getMapScore(map)) + " ", NamedTextColor.YELLOW)); @@ -156,14 +151,13 @@ public void pools( int resultsPerPage = 8; int pages = (mapPools.size() + resultsPerPage - 1) / resultsPerPage; - Component paginated = - TextFormatter.paginate( - translatable("pool.title"), - page, - pages, - NamedTextColor.DARK_AQUA, - NamedTextColor.AQUA, - true); + Component paginated = TextFormatter.paginate( + translatable("pool.title"), + page, + pages, + NamedTextColor.DARK_AQUA, + NamedTextColor.AQUA, + true); Component formattedTitle = TextFormatter.horizontalLineHeading(source, paginated, NamedTextColor.BLUE); @@ -171,30 +165,27 @@ public void pools( new PrettyPaginatedComponentResults(formattedTitle, resultsPerPage) { @Override public Component format(MapPool mapPool, int index) { - Component arrow = - text( - "» ", - poolManager.getActiveMapPool().equals(mapPool) - ? NamedTextColor.GREEN - : NamedTextColor.WHITE); - - Component maps = - text() - .append(text(" (", NamedTextColor.DARK_AQUA)) - .append(translatable("map.title", NamedTextColor.DARK_GREEN)) - .append(text(": ", NamedTextColor.DARK_GREEN)) - .append(text(mapPool.getMaps().size(), NamedTextColor.WHITE)) - .append(text(")", NamedTextColor.DARK_AQUA)) - .build(); - - Component players = - text() - .append(text(" (", NamedTextColor.DARK_AQUA)) - .append(translatable("match.info.players", NamedTextColor.AQUA)) - .append(text(": ", NamedTextColor.AQUA)) - .append(text(mapPool.getPlayers(), NamedTextColor.WHITE)) - .append(text(")", NamedTextColor.DARK_AQUA)) - .build(); + Component arrow = text( + "» ", + poolManager.getActiveMapPool().equals(mapPool) + ? NamedTextColor.GREEN + : NamedTextColor.WHITE); + + Component maps = text() + .append(text(" (", NamedTextColor.DARK_AQUA)) + .append(translatable("map.title", NamedTextColor.DARK_GREEN)) + .append(text(": ", NamedTextColor.DARK_GREEN)) + .append(text(mapPool.getMaps().size(), NamedTextColor.WHITE)) + .append(text(")", NamedTextColor.DARK_AQUA)) + .build(); + + Component players = text() + .append(text(" (", NamedTextColor.DARK_AQUA)) + .append(translatable("match.info.players", NamedTextColor.AQUA)) + .append(text(": ", NamedTextColor.AQUA)) + .append(text(mapPool.getPlayers(), NamedTextColor.WHITE)) + .append(text(")", NamedTextColor.DARK_AQUA)) + .build(); return text() .append(arrow) @@ -223,11 +214,10 @@ public void setPool( if (newPool == null) throw exception("pool.noPoolMatch"); if (newPool.equals(poolManager.getActiveMapPool())) { - sender.sendMessage( - translatable( - "pool.matching", - NamedTextColor.GRAY, - text(newPool.getName(), NamedTextColor.LIGHT_PURPLE))); + sender.sendMessage(translatable( + "pool.matching", + NamedTextColor.GRAY, + text(newPool.getName(), NamedTextColor.LIGHT_PURPLE))); return; } @@ -268,17 +258,15 @@ public void skip( ((Rotation) pool).advance(positions); - Component message = - text() - .append(text("[", NamedTextColor.WHITE)) - .append(translatable("pool.name", NamedTextColor.GOLD)) - .append(text("] [", NamedTextColor.WHITE)) - .append(text(pool.getName(), NamedTextColor.AQUA)) - .append(text("]", NamedTextColor.WHITE)) - .append( - translatable( - "pool.skip", NamedTextColor.GREEN, text(positions, NamedTextColor.AQUA))) - .build(); + Component message = text() + .append(text("[", NamedTextColor.WHITE)) + .append(translatable("pool.name", NamedTextColor.GOLD)) + .append(text("] [", NamedTextColor.WHITE)) + .append(text(pool.getName(), NamedTextColor.AQUA)) + .append(text("]", NamedTextColor.WHITE)) + .append( + translatable("pool.skip", NamedTextColor.GREEN, text(positions, NamedTextColor.AQUA))) + .build(); sender.sendMessage(message); } @@ -291,11 +279,10 @@ public void voteNext( @Flag(value = "open", aliases = "o") boolean forceOpen, @Argument("map") @FlagYielding MapInfo map) { boolean voteResult = poll.toggleVote(map, player); - Component voteAction = - translatable( - voteResult ? "vote.for" : "vote.abstain", - voteResult ? NamedTextColor.GREEN : NamedTextColor.RED, - map.getStyledName(MapNameStyle.COLOR)); + Component voteAction = translatable( + voteResult ? "vote.for" : "vote.abstain", + voteResult ? NamedTextColor.GREEN : NamedTextColor.RED, + map.getStyledName(MapNameStyle.COLOR)); player.sendMessage(voteAction); poll.sendBook(player, forceOpen); } @@ -318,26 +305,12 @@ public void rot( @Argument("page") @Default("1") @Range(min = "1") int page, @Flag(value = "all", aliases = "a") boolean all, String[] rawArgs) { - wrapLegacy( - "pool", - sender, - rawArgs, - () -> { - if (poolManager.getActiveMapPool().getType() != MapPoolType.ORDERED) - throw exception("pool.noRotation"); - - pool( - sender, - source, - poolManager, - page, - MapPoolType.ORDERED, - null, - false, - false, - false, - all); - }); + wrapLegacy("pool", sender, rawArgs, () -> { + if (poolManager.getActiveMapPool().getType() != MapPoolType.ORDERED) + throw exception("pool.noRotation"); + + pool(sender, source, poolManager, page, MapPoolType.ORDERED, null, false, false, false, all); + }); } @Command("rots [page]") @@ -391,14 +364,10 @@ public void resetRot( MapPool resetRot = poolManager.getAppropriateDynamicPool(match).orElseThrow(() -> exception("pool.noDynamic")); - wrapLegacy( - "setpool", - sender, - rawArgs, - () -> { - if (resetRot.getType() != MapPoolType.ORDERED) throw exception("pool.noRotation"); - setPool(sender, source, match, poolManager, resetRot, timeLimit, matchLimit); - }); + wrapLegacy("setpool", sender, rawArgs, () -> { + if (resetRot.getType() != MapPoolType.ORDERED) throw exception("pool.noRotation"); + setPool(sender, source, match, poolManager, resetRot, timeLimit, matchLimit); + }); } private void wrapLegacy(String replace, Audience sender, String[] rawArgs, Runnable task) { diff --git a/core/src/main/java/tc/oc/pgm/rotation/pools/DisabledMapPool.java b/core/src/main/java/tc/oc/pgm/rotation/pools/DisabledMapPool.java index 1bf425f6d5..e75472ecbb 100644 --- a/core/src/main/java/tc/oc/pgm/rotation/pools/DisabledMapPool.java +++ b/core/src/main/java/tc/oc/pgm/rotation/pools/DisabledMapPool.java @@ -5,8 +5,8 @@ import tc.oc.pgm.rotation.MapPoolManager; public class DisabledMapPool extends MapPool { - DisabledMapPool(MapPoolManager manager, ConfigurationSection section, String name) { - super(null, name, manager, section); + DisabledMapPool(String name, MapPoolManager manager, ConfigurationSection section) { + super(null, name, manager, section, MapParser.parse(name, section)); } @Override diff --git a/core/src/main/java/tc/oc/pgm/rotation/pools/MapParser.java b/core/src/main/java/tc/oc/pgm/rotation/pools/MapParser.java new file mode 100644 index 0000000000..ae7d581f9a --- /dev/null +++ b/core/src/main/java/tc/oc/pgm/rotation/pools/MapParser.java @@ -0,0 +1,101 @@ +package tc.oc.pgm.rotation.pools; + +import static tc.oc.pgm.api.map.MapSource.DEFAULT_VARIANT; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.bukkit.configuration.ConfigurationSection; +import tc.oc.pgm.api.PGM; +import tc.oc.pgm.api.map.MapInfo; +import tc.oc.pgm.api.map.MapLibrary; +import tc.oc.pgm.api.map.VariantInfo; + +public class MapParser { + private final MapLibrary maps = PGM.get().getMapLibrary(); + private final String poolName; + private final List variantIds; + private final ArrayList mapList = new ArrayList<>(); + private final Map weights = new HashMap<>(); + + public static MapParser parse(String poolName, ConfigurationSection section) { + var parser = new MapParser(poolName, section.getStringList("variants")); + if (section.contains("maps")) parser.parseSection(section, 1d); + return parser; + } + + private MapParser(String poolName, List variants) { + this.poolName = poolName; + if (variants != null) { + int def = variants.indexOf(DEFAULT_VARIANT); + if (def >= 0) variants = variants.subList(0, def); + if (variants.isEmpty()) variants = null; + } + this.variantIds = variants; + } + + public List getMaps() { + return mapList; + } + + public double getWeight(MapInfo info) { + return weights.getOrDefault(info, 1d); + } + + private void parseSection(ConfigurationSection parent, double parentWeight) { + Set keys; + double weight; + if (parent.contains("maps")) { + keys = Set.of("maps"); + weight = parent.getDouble("weight", parentWeight); + } else { + keys = parent.getKeys(false); + weight = parentWeight; + } + keys.forEach(k -> { + if (parent.isConfigurationSection(k)) parseSection(parent.getConfigurationSection(k), weight); + else parseMapList(parent.getStringList(k), weight); + }); + } + + private void parseMapList(List mapNames, double weight) { + if (mapNames == null) return; + + mapList.ensureCapacity(mapList.size() + mapNames.size()); + + for (String mapName : mapNames) { + MapInfo map = maps.getMap(mapName); + if (map != null) { + map = getVariant(map); + weights.computeIfAbsent(map, k -> { + mapList.add(k); + return weight; + }); + } else { + PGM.get() + .getLogger() + .warning( + "[MapPool] [" + poolName + "] " + mapName + " not found in map repo. Ignoring..."); + } + } + } + + private MapInfo getVariant(MapInfo map) { + if (variantIds == null || !map.getVariantId().equals(DEFAULT_VARIANT)) return map; + + Map variants = map.getVariants(); + for (String varId : variantIds) { + VariantInfo variant = variants.get(varId); + if (variant == null) continue; + MapInfo variantMap = maps.getMapById(variant.getId()); + if (variantMap != null) return variantMap; + // Should never happen + PGM.get() + .getLogger() + .warning("[MapPool] Failed to get map " + variant.getId() + ". Moving on..."); + } + return map; + } +} diff --git a/core/src/main/java/tc/oc/pgm/rotation/pools/MapPool.java b/core/src/main/java/tc/oc/pgm/rotation/pools/MapPool.java index 7ca5c29f75..9e1ed48cfd 100644 --- a/core/src/main/java/tc/oc/pgm/rotation/pools/MapPool.java +++ b/core/src/main/java/tc/oc/pgm/rotation/pools/MapPool.java @@ -1,19 +1,13 @@ package tc.oc.pgm.rotation.pools; -import static tc.oc.pgm.api.map.MapSource.DEFAULT_VARIANT; import static tc.oc.pgm.util.text.TextParser.parseDuration; import java.time.Duration; -import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import org.bukkit.configuration.ConfigurationSection; -import tc.oc.pgm.api.PGM; import tc.oc.pgm.api.map.MapInfo; -import tc.oc.pgm.api.map.MapLibrary; import tc.oc.pgm.api.map.MapOrder; -import tc.oc.pgm.api.map.VariantInfo; import tc.oc.pgm.api.match.Match; import tc.oc.pgm.rotation.MapPoolManager; @@ -30,7 +24,12 @@ public abstract class MapPool implements MapOrder, Comparable { protected final boolean dynamic; - MapPool(MapPoolType type, String name, MapPoolManager manager, ConfigurationSection section) { + MapPool( + MapPoolType type, + String name, + MapPoolManager manager, + ConfigurationSection section, + MapParser maps) { this( type, name, @@ -39,7 +38,7 @@ public abstract class MapPool implements MapOrder, Comparable { section.getInt("players"), section.getBoolean("dynamic", true), parseDuration(section.getString("cycle-time", "-1s")), - buildMapList(section.getStringList("maps"), section.getStringList("variants"), name)); + maps.getMaps()); } MapPool( @@ -58,53 +57,7 @@ public abstract class MapPool implements MapOrder, Comparable { this.players = players; this.dynamic = dynamic; this.cycleTime = cycleTime; - this.maps = maps; - } - - private static List buildMapList( - List mapNames, List variants, String poolName) { - if (mapNames == null) return new ArrayList<>(); - if (variants != null) { - int def = variants.indexOf(DEFAULT_VARIANT); - if (def >= 0) variants = variants.subList(0, def); - if (variants.isEmpty()) variants = null; - } - - List mapList = new ArrayList<>(mapNames.size()); - MapLibrary maps = PGM.get().getMapLibrary(); - - for (String mapName : mapNames) { - MapInfo map = maps.getMap(mapName); - if (map != null) { - mapList.add(getVariant(maps, map, variants)); - } else { - PGM.get() - .getLogger() - .warning( - "[MapPool] [" + poolName + "] " + mapName + " not found in map repo. Ignoring..."); - } - } - - return Collections.unmodifiableList(mapList); - } - - private static MapInfo getVariant(MapLibrary maps, MapInfo map, List variantIds) { - if (variantIds == null || !map.getVariantId().equals(DEFAULT_VARIANT)) return map; - - Map variants = map.getVariants(); - for (String varId : variantIds) { - VariantInfo variant = variants.get(varId); - if (variant == null) continue; - MapInfo variantMap = maps.getMapById(variant.getId()); - if (variantMap != null) { - return variantMap; - } else { - PGM.get() - .getLogger() - .warning("[MapPool] Failed to get map " + variant.getId() + ". Moving on..."); - } - } - return map; + this.maps = Collections.unmodifiableList(maps); } public MapPoolType getType() { diff --git a/core/src/main/java/tc/oc/pgm/rotation/pools/MapPoolType.java b/core/src/main/java/tc/oc/pgm/rotation/pools/MapPoolType.java index 7b6dc1dcaa..4a75fa3779 100644 --- a/core/src/main/java/tc/oc/pgm/rotation/pools/MapPoolType.java +++ b/core/src/main/java/tc/oc/pgm/rotation/pools/MapPoolType.java @@ -40,9 +40,9 @@ public static MapPool buildPool( MapPoolType type = of(typeStr); if (type == null) { PGM.get().getLogger().severe("Invalid map pool type for " + key + ": '" + typeStr + "'"); - return new DisabledMapPool(manager, section, key); + return new DisabledMapPool(key, manager, section); } - return type.factory.build(type, key, manager, section); + return type.factory.build(type, key, manager, section, MapParser.parse(key, section)); } @NotNull @@ -53,6 +53,10 @@ public Iterator iterator() { private interface PoolFactory { MapPool build( - MapPoolType type, String name, MapPoolManager manager, ConfigurationSection section); + MapPoolType type, + String name, + MapPoolManager manager, + ConfigurationSection section, + MapParser maps); } } diff --git a/core/src/main/java/tc/oc/pgm/rotation/pools/RandomMapPool.java b/core/src/main/java/tc/oc/pgm/rotation/pools/RandomMapPool.java index 15960f4401..75009d4254 100644 --- a/core/src/main/java/tc/oc/pgm/rotation/pools/RandomMapPool.java +++ b/core/src/main/java/tc/oc/pgm/rotation/pools/RandomMapPool.java @@ -11,9 +11,13 @@ public class RandomMapPool extends MapPool { private final RandomMapOrder order; public RandomMapPool( - MapPoolType type, String name, MapPoolManager manager, ConfigurationSection section) { - super(type, name, manager, section); - this.order = new RandomMapOrder(maps); + MapPoolType type, + String name, + MapPoolManager manager, + ConfigurationSection section, + MapParser maps) { + super(type, name, manager, section, maps); + this.order = new RandomMapOrder(this.maps); } @Override diff --git a/core/src/main/java/tc/oc/pgm/rotation/pools/Rotation.java b/core/src/main/java/tc/oc/pgm/rotation/pools/Rotation.java index e4a1ab653f..a0a68035da 100644 --- a/core/src/main/java/tc/oc/pgm/rotation/pools/Rotation.java +++ b/core/src/main/java/tc/oc/pgm/rotation/pools/Rotation.java @@ -14,8 +14,12 @@ public class Rotation extends MapPool { private int position; public Rotation( - MapPoolType type, String name, MapPoolManager manager, ConfigurationSection section) { - super(type, name, manager, section); + MapPoolType type, + String name, + MapPoolManager manager, + ConfigurationSection section, + MapParser maps) { + super(type, name, manager, section, maps); @Nullable MapInfo nextMap = PGM.get().getMapLibrary().getMap(manager.getNextMapForPool(name)); if (nextMap != null) this.position = getMapPosition(nextMap); diff --git a/core/src/main/java/tc/oc/pgm/rotation/pools/VotingPool.java b/core/src/main/java/tc/oc/pgm/rotation/pools/VotingPool.java index b0dc0af2fd..8700f85bb0 100644 --- a/core/src/main/java/tc/oc/pgm/rotation/pools/VotingPool.java +++ b/core/src/main/java/tc/oc/pgm/rotation/pools/VotingPool.java @@ -2,6 +2,7 @@ import java.time.Duration; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -18,6 +19,7 @@ import tc.oc.pgm.rotation.MapPoolManager; import tc.oc.pgm.rotation.vote.MapPoll; import tc.oc.pgm.rotation.vote.MapVotePicker; +import tc.oc.pgm.rotation.vote.VoteData; import tc.oc.pgm.util.math.Formula; public class VotingPool extends MapPool { @@ -30,17 +32,22 @@ public class VotingPool extends MapPool { public final MapVotePicker mapPicker; // The current rating of maps. Eventually should be persisted elsewhere. - private final Map mapScores = new HashMap<>(); + private final Map mapScores; private MapPoll currentPoll; public VotingPool( - MapPoolType type, String name, MapPoolManager manager, ConfigurationSection section) { - super(type, name, manager, section); + MapPoolType type, + String name, + MapPoolManager manager, + ConfigurationSection section, + MapParser parser) { + super(type, name, manager, section, parser); this.constants = new VoteConstants(section, maps.size()); - this.mapPicker = MapVotePicker.of(manager, constants, section); - for (MapInfo map : maps) mapScores.put(map, constants.defaultScore()); + Map ms = new HashMap<>(); + maps.forEach(m -> ms.put(m, new VoteData(parser.getWeight(m), constants.defaultScore()))); + this.mapScores = Collections.unmodifiableMap(ms); } public VotingPool( @@ -55,7 +62,9 @@ public VotingPool( super(type, name, manager, enabled, players, dynamic, cycleTime, maps); this.constants = new VoteConstants(new MemoryConfiguration(), maps.size()); this.mapPicker = MapVotePicker.of(manager, constants, null); - for (MapInfo map : maps) mapScores.put(map, constants.defaultScore()); + Map ms = new HashMap<>(); + maps.forEach(m -> ms.put(m, new VoteData(1, constants.defaultScore()))); + this.mapScores = Collections.unmodifiableMap(ms); } public MapPoll getCurrentPoll() { @@ -63,26 +72,30 @@ public MapPoll getCurrentPoll() { } public double getMapScore(MapInfo map) { - return mapScores.get(map); + return mapScores.get(map).getScore(); + } + + public VoteData getVoteData(MapInfo map) { + VoteData data = mapScores.get(map); + if (data == null) data = new VoteData(1, constants.defaultScore()); + return data; } /** Ticks scores for all maps, making them go slowly towards DEFAULT_WEIGHT. */ private void tickScores(Match match) { // If the current map isn't from this pool, ignore ticking if (!mapScores.containsKey(match.getMap())) return; - mapScores.replaceAll((mapScores, value) -> value > constants.defaultScore() - ? Math.max(value - constants.scoreDecay(), constants.defaultScore()) - : Math.min(value + constants.scoreRise(), constants.defaultScore())); - mapScores.put( - match.getMap(), constants.scoreAfterPlay().applyAsDouble(new Context(match.getDuration()))); + mapScores.forEach((mapScores, value) -> value.tickScore(constants)); + mapScores + .get(match.getMap()) + .setScore(constants.scoreAfterPlay().applyAsDouble(new Context(match.getDuration()))); } private void updateScores(Map> votes) { double voters = votes.values().stream().flatMap(Collection::stream).distinct().count(); if (voters == 0) return; // Literally no one voted - votes.forEach((m, v) -> - mapScores.computeIfPresent(m, (a, b) -> constants.afterVoteScore(v.size() / voters))); + votes.forEach((m, v) -> getVoteData(m).setScore(constants.afterVoteScore(v.size() / voters))); } @Override diff --git a/core/src/main/java/tc/oc/pgm/rotation/vote/MapVotePicker.java b/core/src/main/java/tc/oc/pgm/rotation/vote/MapVotePicker.java index e532bbb162..1a40c6c691 100644 --- a/core/src/main/java/tc/oc/pgm/rotation/vote/MapVotePicker.java +++ b/core/src/main/java/tc/oc/pgm/rotation/vote/MapVotePicker.java @@ -76,7 +76,7 @@ private MapVotePicker( * @param scores maps and their respective scores * @return list of maps to include in the vote */ - public List getMaps(VotePoolOptions options, Map scores) { + public List getMaps(VotePoolOptions options, Map scores) { if (options.shouldOverride()) return getMaps(new ArrayList<>(), options.getCustomVoteMapsWeighted()); @@ -84,7 +84,7 @@ public List getMaps(VotePoolOptions options, Map score return getMaps(maps, scores); } - protected List getMaps(@Nullable List selected, Map scores) { + protected List getMaps(@Nullable List selected, Map scores) { if (selected == null) selected = new ArrayList<>(); List unmodifiable = Collections.unmodifiableList(selected); @@ -98,10 +98,10 @@ protected List getMaps(@Nullable List selected, Map selected, Map mapScores) { + protected MapInfo getMap(List selected, Map mapScores) { NavigableMap cumulativeScores = new TreeMap<>(); double maxWeight = 0; - for (Map.Entry map : mapScores.entrySet()) { + for (Map.Entry map : mapScores.entrySet()) { double weight = getWeight(selected, map.getKey(), map.getValue()); if (weight > MINIMUM_WEIGHT) cumulativeScores.put(maxWeight += weight, map.getKey()); } @@ -115,20 +115,20 @@ protected MapInfo getMap(List selected, Map mapScores) * * @param selected The list of selected maps so far * @param map The map being considered - * @param score The score of the map, from player votes + * @param data The vote data of the map, from player votes and config * @return random weight for the map */ - public double getWeight(@Nullable List selected, @NotNull MapInfo map, double score) { - if ((selected != null && selected.contains(map)) || score <= constants.scoreMinToVote()) - return 0; + public double getWeight(@Nullable List selected, @NotNull MapInfo map, VoteData data) { + if ((selected != null && selected.contains(map)) + || data.getScore() <= constants.scoreMinToVote()) return 0; var context = new MapVoteContext( - score, + data.getScore(), getRepeatedGamemodes(selected, map), map.getMaxPlayers().stream().mapToInt(i -> i).sum(), manager.getActivePlayers(null)); - return Math.max(modifier.applyAsDouble(context), 0); + return Math.max(modifier.applyAsDouble(context) * data.getWeight(), 0); } private double getRepeatedGamemodes(List selected, MapInfo map) { diff --git a/core/src/main/java/tc/oc/pgm/rotation/vote/VoteData.java b/core/src/main/java/tc/oc/pgm/rotation/vote/VoteData.java new file mode 100644 index 0000000000..9868cb8234 --- /dev/null +++ b/core/src/main/java/tc/oc/pgm/rotation/vote/VoteData.java @@ -0,0 +1,36 @@ +package tc.oc.pgm.rotation.vote; + +import tc.oc.pgm.rotation.pools.VotingPool; + +public class VoteData { + private final double weight; + private double score; + + public VoteData(double weight, double score) { + this.score = score; + this.weight = weight; + } + + public void setScore(double score) { + this.score = score; + } + + public VoteData withScore(double score) { + setScore(score); + return this; + } + + public double getWeight() { + return weight; + } + + public double getScore() { + return score; + } + + public void tickScore(VotingPool.VoteConstants constants) { + this.score = score > constants.defaultScore() + ? Math.max(score - constants.scoreDecay(), constants.defaultScore()) + : Math.min(score + constants.scoreRise(), constants.defaultScore()); + } +} diff --git a/core/src/main/java/tc/oc/pgm/rotation/vote/VotePoolOptions.java b/core/src/main/java/tc/oc/pgm/rotation/vote/VotePoolOptions.java index 734e0fc31b..800dc23171 100644 --- a/core/src/main/java/tc/oc/pgm/rotation/vote/VotePoolOptions.java +++ b/core/src/main/java/tc/oc/pgm/rotation/vote/VotePoolOptions.java @@ -69,8 +69,8 @@ public Set getCustomVoteMaps() { return Collections.unmodifiableSet(customVoteMaps.keySet()); } - public Map getCustomVoteMapsWeighted() { + public Map getCustomVoteMapsWeighted() { return customVoteMaps.keySet().stream() - .collect(Collectors.toMap(map -> map, score -> VotingPool.DEFAULT_SCORE)); + .collect(Collectors.toMap(map -> map, score -> new VoteData(1, VotingPool.DEFAULT_SCORE))); } }