From aed57f5cb6df6f349ae08560c4c9dc8cf2e8da12 Mon Sep 17 00:00:00 2001 From: Andreas Troelsen Date: Sun, 1 Nov 2020 11:45:57 +0100 Subject: [PATCH] Introduce slugs in arenas and classes. Whitespace and punctuation in identifiers is a fairly big source of issues in areas like permissions and commands where whitespace isn't directly supported (or at least makes things needlessly difficult). This commit introduces the concept of a "slug" in arenas and classes, giving them a _consistent_ `kebab-case` name for use in such places, but it does not implement their use anywhere. Slugs are expected to be the solution to problems like the one posed in issue #647. At the time of writing, we're only concerned with simple stuff like removing periods, commas, parentheses and replacing underscores and spaces with dashes. If it turns out that people have unanticipatedly problematic arena and class names, we may have to expand the slug definition rules or allow for custom slugs. --- .../com/garbagemule/MobArena/ArenaClass.java | 11 +++++ .../com/garbagemule/MobArena/ArenaImpl.java | 8 ++++ .../garbagemule/MobArena/framework/Arena.java | 2 + .../com/garbagemule/MobArena/util/Slugs.java | 18 ++++++++ .../garbagemule/MobArena/util/SlugsTest.java | 45 +++++++++++++++++++ 5 files changed, 84 insertions(+) create mode 100644 src/main/java/com/garbagemule/MobArena/util/Slugs.java create mode 100644 src/test/java/com/garbagemule/MobArena/util/SlugsTest.java diff --git a/src/main/java/com/garbagemule/MobArena/ArenaClass.java b/src/main/java/com/garbagemule/MobArena/ArenaClass.java index 45e1c48..dace8df 100644 --- a/src/main/java/com/garbagemule/MobArena/ArenaClass.java +++ b/src/main/java/com/garbagemule/MobArena/ArenaClass.java @@ -3,6 +3,7 @@ package com.garbagemule.MobArena; import com.garbagemule.MobArena.framework.Arena; import com.garbagemule.MobArena.framework.ArenaMaster; import com.garbagemule.MobArena.things.Thing; +import com.garbagemule.MobArena.util.Slugs; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -16,6 +17,7 @@ import java.util.stream.IntStream; public class ArenaClass { private String configName, lowercaseName; + private String slug; private Thing helmet, chestplate, leggings, boots, offhand; private List armor; private List items; @@ -32,6 +34,7 @@ public class ArenaClass */ public ArenaClass(String name, Thing price, boolean unbreakableWeapons, boolean unbreakableArmor) { this.configName = name; + this.slug = Slugs.create(name); this.lowercaseName = name.toLowerCase().replace(" ", ""); this.items = new ArrayList<>(); @@ -54,6 +57,14 @@ public class ArenaClass return configName; } + /** + * Get the slug version of the arena class name. + * @return the slugified class name + */ + public String getSlug() { + return slug; + } + /** * Get the lowercase class name. * @return the lowercase class name diff --git a/src/main/java/com/garbagemule/MobArena/ArenaImpl.java b/src/main/java/com/garbagemule/MobArena/ArenaImpl.java index df45dd7..d81824b 100644 --- a/src/main/java/com/garbagemule/MobArena/ArenaImpl.java +++ b/src/main/java/com/garbagemule/MobArena/ArenaImpl.java @@ -26,6 +26,7 @@ import com.garbagemule.MobArena.things.InvalidThingInputString; import com.garbagemule.MobArena.things.Thing; import com.garbagemule.MobArena.things.ThingPicker; import com.garbagemule.MobArena.util.ClassChests; +import com.garbagemule.MobArena.util.Slugs; import com.garbagemule.MobArena.util.inventory.InventoryManager; import com.garbagemule.MobArena.util.timer.AutoStartTimer; import com.garbagemule.MobArena.util.timer.StartDelayTimer; @@ -77,6 +78,7 @@ public class ArenaImpl implements Arena // General stuff private MobArena plugin; private String name; + private String slug; private World world; private Messenger messenger; private Announcer announcer; @@ -155,6 +157,7 @@ public class ArenaImpl implements Arena throw new NullPointerException("[MobArena] ERROR! World for arena '" + name + "' does not exist!"); this.name = name; + this.slug = Slugs.create(name); this.world = world; this.plugin = plugin; this.settings = makeSection(section, "settings"); @@ -1448,6 +1451,11 @@ public class ArenaImpl implements Arena return MAUtils.nameConfigToArena(name); } + @Override + public String getSlug() { + return slug; + } + @Override public MobArena getPlugin() { diff --git a/src/main/java/com/garbagemule/MobArena/framework/Arena.java b/src/main/java/com/garbagemule/MobArena/framework/Arena.java index afaf7c9..cd13f9f 100644 --- a/src/main/java/com/garbagemule/MobArena/framework/Arena.java +++ b/src/main/java/com/garbagemule/MobArena/framework/Arena.java @@ -223,6 +223,8 @@ public interface Arena String arenaName(); + String getSlug(); + MobArena getPlugin(); Map getClasses(); diff --git a/src/main/java/com/garbagemule/MobArena/util/Slugs.java b/src/main/java/com/garbagemule/MobArena/util/Slugs.java new file mode 100644 index 0000000..3e4b455 --- /dev/null +++ b/src/main/java/com/garbagemule/MobArena/util/Slugs.java @@ -0,0 +1,18 @@ +package com.garbagemule.MobArena.util; + +public final class Slugs { + + /** + * Create a slug version + * @param input + * @return + */ + public static String create(String input) { + return input + .toLowerCase() + .replaceAll("[.,:;'\"]", "") + .replaceAll("[<>(){}\\[\\]]", "") + .replaceAll("[ _']", "-"); + } + +} diff --git a/src/test/java/com/garbagemule/MobArena/util/SlugsTest.java b/src/test/java/com/garbagemule/MobArena/util/SlugsTest.java new file mode 100644 index 0000000..bf9da5e --- /dev/null +++ b/src/test/java/com/garbagemule/MobArena/util/SlugsTest.java @@ -0,0 +1,45 @@ +package com.garbagemule.MobArena.util; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) +public class SlugsTest { + + @Parameters + public static Collection data() { + return Arrays.asList(new Object[][] { + {"castle", "castle"}, + {"Castle", "castle"}, + {"CaStLe", "castle"}, + {"Castle of Kebab", "castle-of-kebab"}, + {"Area 52", "area-52"}, + {"Project: Nuclear", "project-nuclear"}, + {"Mr. Kebal Bab's Mansion", "mr-kebal-babs-mansion"}, + {"Unnamed Arena (3)", "unnamed-arena-3"}, + {"The Wolf Master", "the-wolf-master"}, + {"already-a-slug", "already-a-slug"}, + }); + } + + @Parameter + public String input; + + @Parameter(1) + public String expected; + + @Test + public void test() { + String actual = Slugs.create(input); + + assertEquals("Wrong slug for '" + input + "'", expected, actual); + } +}