Added World Alias Regex setting

This allows grouping worlds together by matching a regex and avoiding thousands of lines if
some plugin generates worlds automatically.

Affects issues:
- Close #1656
This commit is contained in:
Risto Lahtela 2021-07-24 11:39:28 +03:00
parent a2cface3e0
commit 13cbca6639
6 changed files with 87 additions and 19 deletions

View File

@ -30,13 +30,12 @@ import com.djrapitops.plan.settings.locale.lang.HtmlLang;
import com.djrapitops.plan.utilities.logging.ErrorContext;
import com.djrapitops.plan.utilities.logging.ErrorLogger;
import dagger.Lazy;
import org.apache.commons.lang3.StringUtils;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@ -54,6 +53,8 @@ public class WorldAliasSettings {
private final Processing processing;
private final ErrorLogger errorLogger;
private List<String[]> regexRules;
@Inject
public WorldAliasSettings(
Lazy<PlanConfig> config,
@ -70,10 +71,35 @@ public class WorldAliasSettings {
percentageFormatter = () -> formatters.get().percentage();
}
private ConfigNode getAliasSection() {
private ConfigNode getAliasListNode() {
return config.get().get(DisplaySettings.WORLD_ALIASES);
}
private List<String[]> getRegexRules() {
if (regexRules == null) {
regexRules = new ArrayList<>();
for (String regexRule : config.get().getStringList("World_aliases.Regex")) {
regexRules.add(StringUtils.split(regexRule, ":", 2));
}
}
return regexRules;
}
private Optional<String> getAlias(String world) {
for (String[] regexRule : getRegexRules()) {
String alias = regexRule[0];
String regex = regexRule[1];
if (world.matches(regex)) {
return Optional.of(alias);
}
}
String alias = getAliasListNode().getString(world);
if (alias == null || alias.isEmpty()) {
return Optional.empty();
}
return Optional.of(alias);
}
/**
* Adds a new World to the config section.
* <p>
@ -83,9 +109,9 @@ public class WorldAliasSettings {
*/
public void addWorld(String world) {
if (world == null || world.isEmpty()) throw new IllegalArgumentException("Attempted to save empty world alias");
if (getAlias(world).isPresent()) return;
ConfigNode aliasSect = getAliasSection();
ConfigNode aliasSect = getAliasListNode();
String previousValue = aliasSect.getString(world);
if (previousValue == null || previousValue.isEmpty()) {
aliasSect.set(world, world);
@ -111,18 +137,17 @@ public class WorldAliasSettings {
entry -> entry.getValue().getTotal() // GMTimes.getTotal
));
ConfigNode aliases = getAliasSection();
Map<String, Long> playtimePerAlias = new HashMap<>();
for (Map.Entry<String, Long> entry : playtimePerWorld.entrySet()) {
String worldName = entry.getKey();
long playtime = entry.getValue();
if (worldName != null && !aliases.contains(worldName)) {
Optional<String> foundAlias = getAlias(worldName);
if (!foundAlias.isPresent()) {
addWorld(worldName);
}
String alias = aliases.getString(worldName);
String alias = foundAlias.orElse(worldName);
playtimePerAlias.put(alias, playtimePerAlias.getOrDefault(alias, 0L) + playtime);
}
@ -130,8 +155,6 @@ public class WorldAliasSettings {
}
public Map<String, GMTimes> getGMTimesPerAlias(WorldTimes worldTimes) {
ConfigNode aliases = getAliasSection();
Map<String, GMTimes> gmTimesPerAlias = new HashMap<>();
String[] gms = GMTimes.getGMKeyArray();
@ -140,11 +163,12 @@ public class WorldAliasSettings {
String worldName = entry.getKey();
GMTimes gmTimes = entry.getValue();
if (!aliases.contains(worldName)) {
Optional<String> foundAlias = getAlias(worldName);
if (!foundAlias.isPresent()) {
addWorld(worldName);
}
String alias = aliases.getString(worldName);
String alias = foundAlias.orElse(worldName);
GMTimes aliasGMTimes = gmTimesPerAlias.getOrDefault(alias, new GMTimes());
for (String gm : gms) {
@ -162,9 +186,8 @@ public class WorldAliasSettings {
}
WorldTimes worldTimes = foundWorldTimes.orElseGet(WorldTimes::new);
ConfigNode aliases = getAliasSection();
return worldTimes.getCurrentWorld()
.map(currentWorld -> "Current: " + (aliases.contains(currentWorld) ? aliases.getString(currentWorld) : currentWorld))
.map(currentWorld -> "Current: " + getAlias(currentWorld).orElse(currentWorld))
.orElse("Current: " + locale.get().getString(GenericLang.UNAVAILABLE));
}

View File

@ -57,6 +57,37 @@ public interface ConfigChange {
}
}
class MoveLevelDown implements ConfigChange {
final String oldPath;
final String newPath;
public MoveLevelDown(String oldPath, String newPath) {
this.oldPath = oldPath;
this.newPath = newPath;
}
@Override
public boolean hasBeenApplied(Config config) {
return !config.getNode(oldPath).isPresent() || config.getNode(newPath).isPresent();
}
@Override
public synchronized void apply(Config config) {
if (!config.moveChild(oldPath, "Temp." + oldPath)) {
throw new IllegalStateException("Failed to move config node from '" + oldPath + "' to 'Temp." + oldPath + "' while moving to '" + newPath + "'");
}
if (!config.moveChild("Temp." + oldPath, newPath)) {
throw new IllegalStateException("Failed to move config node from 'Temp." + oldPath + "' to '" + newPath + "' while moving from '" + oldPath + "'");
}
}
@Override
public String getAppliedMessage() {
return "Moved " + oldPath + " to " + newPath;
}
}
class Copied extends Removed {
final String newPath;

View File

@ -148,6 +148,8 @@ public class ConfigUpdater {
new ConfigChange.Removed("Database.H2.User"),
new ConfigChange.Removed("Database.H2.Password"),
new ConfigChange.Removed("Database.H2"),
new ConfigChange.MoveLevelDown("World_aliases", "World_aliases.List")
};
}

View File

@ -43,7 +43,7 @@ public class DisplaySettings {
public static final Setting<String> CMD_COLOR_MAIN = new StringSetting("Display_options.Command_colors.Main");
public static final Setting<String> CMD_COLOR_SECONDARY = new StringSetting("Display_options.Command_colors.Secondary");
public static final Setting<String> CMD_COLOR_TERTIARY = new StringSetting("Display_options.Command_colors.Highlight");
public static final Setting<ConfigNode> WORLD_ALIASES = new Setting<ConfigNode>("World_aliases", ConfigNode.class) {
public static final Setting<ConfigNode> WORLD_ALIASES = new Setting<ConfigNode>("World_aliases.List", ConfigNode.class) {
@Override
public ConfigNode getValueFrom(ConfigNode node) {
return node.getNode(path).orElseGet(() -> node.addNode(path));

View File

@ -180,7 +180,13 @@ Formatting:
# World aliases can be used to rename worlds and to combine multiple worlds into a group.
# -----------------------------------------------------
World_aliases:
world: world
# List of world names: aliases, case sensitive. Set alias of two worlds to same one to group them.
# Automatically generated, if regex matches world will not be added here.
List:
world: world
# List of - "alias:regex" rules, Set alias of multiple worlds that match regex to group them
Regex:
- "Alias for world:^abc$"
# -----------------------------------------------------
# These settings will make Plan write .js, .css, .json and .html files to some location on disk.
# Relative path will render to /plugins/Plan/path

View File

@ -185,7 +185,13 @@ Formatting:
# World aliases can be used to rename worlds and to combine multiple worlds into a group.
# -----------------------------------------------------
World_aliases:
world: world
# List of world names: aliases, case sensitive. Set alias of two worlds to same one to group them.
# Automatically generated, if regex matches world will not be added here.
List:
world: world
# List of - "alias:regex" rules, Set alias of multiple worlds that match regex to group them
Regex:
- "Alias for world:^abc$"
# -----------------------------------------------------
# These settings will make Plan write .js, .css, .json and .html files to some location on disk.
# Relative path will render to /plugins/Plan/path