i18n: per-player EN/PT via Adventure GlobalTranslator #1
@@ -25,7 +25,7 @@ All player-facing text is Portuguese (pt-BR).
|
||||
| `ranking` | `/ranking mineracao` and friends. Covers **offline players too**. |
|
||||
| `marcos` | Announces round milestones — 100 km walked, 24 hours played — the first time someone crosses one. |
|
||||
| `mortes` | Replaces each death message with a comic pt-BR line (cause-based flavor + a death counter) and sends the death coordinates **privately** to the dead player on respawn (the death screen swallows chat sent during the event), so they can run back to their dropped items. Respects `keepInventory`. No storage, no command. |
|
||||
| `zoacao` | A bare `f`/`F` in chat (trimmed, nothing else) is swapped for a random line from `zoacao.mensagens` — a chat gag. The player's name still prefixes it. Pure chat swap; the `luto` tribute is unaffected (paying respects still needs the `[F]` button or `/f`). Affects Bedrock chat too (it's a chat event, not a click). |
|
||||
| `zoacao` | A chat message matching the trigger (a pattern + a match mode) is swapped for a random line from `zoacao.mensagens` — a chat gag. The player's name still prefixes it. Default: a bare `f`/`F` (trimmed) → a random gag line. Match modes: `igual` (equals), `contem` (contains), `comeca` (starts with), `termina` (ends with), `regex`. The mode, the pattern, and the message list are all editable in-game with `/canalhandia zoacao ...`. Pure chat swap; the `luto` tribute is unaffected (paying respects still needs the `[F]` button or `/f`). Affects Bedrock chat too (it's a chat event, not a click). |
|
||||
| `ia` | `/ia <pergunta>` asks an OpenAI-compatible model in chat. Optional wiki grounding, per-player memory, operator corrections. |
|
||||
|
||||
Toggle any of them: `/canalhandia modulo <nome> <on|off>`
|
||||
@@ -164,6 +164,12 @@ Admin (`canalhandia.admin`):
|
||||
/canalhandia modulo <nome> <on|off> liga/desliga um módulo
|
||||
/canalhandia marcos força uma verificação de marcos
|
||||
/canalhandia limpar [cooldown|historico|tudo]
|
||||
/canalhandia zoacao listar mostra a regra e as frases da zoação
|
||||
/canalhandia zoacao modo <m> igual | contem | comeca | termina | regex
|
||||
/canalhandia zoacao padrao <texto> texto/regex que dispara a zoação
|
||||
/canalhandia zoacao adicionar <frase> adiciona uma frase de zoação
|
||||
/canalhandia zoacao remover <n|texto> remove uma frase de zoação
|
||||
/canalhandia zoacao limpar volta para as frases padrão
|
||||
/canalhandia reload
|
||||
/curiosidade modo <entrada|intervalo|ambos|manual>
|
||||
/curiosidade intervalo <min> intervalo do modo temporizado
|
||||
|
||||
@@ -480,17 +480,20 @@ public final class Canalhandia extends JavaPlugin implements Listener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Chat gag: a bare "f" (or "F", trimmed, nothing else) gets replaced with a
|
||||
* random line from {@code zoacao.mensagens}. Pure chat swap — the player's
|
||||
* name still prefixes it as normal. Independent of {@code luto}: paying
|
||||
* respects still needs the {@code [F]} button (Java) or {@code /f} command.
|
||||
* Chat gag: a message matching the {@code zoacao} trigger (pattern + match
|
||||
* mode, default a bare "f") gets replaced with a random line from
|
||||
* {@code zoacao.mensagens}. Pure chat swap — the player's name still
|
||||
* prefixes it as normal. Independent of {@code luto}: paying respects still
|
||||
* needs the {@code [F]} button (Java) or {@code /f} command. Editable
|
||||
* in-game via {@code /canalhandia zoacao ...}.
|
||||
*/
|
||||
@EventHandler
|
||||
public void onChatF(AsyncPlayerChatEvent event) {
|
||||
if (!settings.moduleEnabled(Module.ZOACAO)) {
|
||||
return;
|
||||
}
|
||||
String gag = Zoacao.replace(event.getMessage(), settings.zoacaoMessages(), random);
|
||||
String gag = Zoacao.replace(event.getMessage(), settings.zoacaoMode(),
|
||||
settings.zoacaoPattern(), settings.zoacaoMessages(), random);
|
||||
if (gag != null) {
|
||||
event.setMessage(gag);
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter {
|
||||
}
|
||||
}
|
||||
case "limpar" -> clear(sender, rest);
|
||||
case "zoacao" -> zoacaoEdit(sender, rest);
|
||||
case "reload" -> {
|
||||
if (admin(sender)) {
|
||||
plugin.reloadConfig();
|
||||
@@ -619,6 +620,97 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In-game editing of the {@code zoacao} chat gag: the match mode, the
|
||||
* trigger pattern, and the replacement message list. Admin-only; every
|
||||
* change writes through to config.yml immediately.
|
||||
*/
|
||||
private void zoacaoEdit(CommandSender sender, String[] args) {
|
||||
if (!admin(sender)) {
|
||||
return;
|
||||
}
|
||||
Settings settings = plugin.settings();
|
||||
String sub = args.length > 0 ? args[0].toLowerCase(Locale.ROOT) : "listar";
|
||||
switch (sub) {
|
||||
case "listar", "status" -> {
|
||||
Msg.header(sender, "Zoação (gag de chat)");
|
||||
Msg.line(sender, "correspondência", settings.zoacaoMode().key()
|
||||
+ " (igual | contem | comeca | termina | regex)");
|
||||
Msg.line(sender, "padrão", settings.zoacaoPattern());
|
||||
List<String> messages = settings.zoacaoMessages();
|
||||
Msg.line(sender, "mensagens", "(" + messages.size() + ")");
|
||||
for (int i = 0; i < messages.size(); i++) {
|
||||
sender.sendMessage(Component.text(" " + (i + 1) + ". ", NamedTextColor.DARK_AQUA)
|
||||
.append(Component.text(messages.get(i), NamedTextColor.WHITE)));
|
||||
}
|
||||
}
|
||||
case "modo" -> {
|
||||
if (args.length < 2) {
|
||||
Msg.error(sender, "Uso: /canalhandia zoacao modo <igual|contem|comeca|termina|regex>");
|
||||
return;
|
||||
}
|
||||
Zoacao.Mode mode = Zoacao.Mode.byKey(args[1]);
|
||||
if (mode == null) {
|
||||
Msg.error(sender, "Modo inválido. Use: igual, contem, comeca, termina, regex.");
|
||||
return;
|
||||
}
|
||||
settings.zoacaoMode(mode);
|
||||
Msg.ok(sender, "Correspondência da zoação: " + mode.key() + ".");
|
||||
}
|
||||
case "padrao" -> {
|
||||
if (args.length < 2) {
|
||||
Msg.error(sender, "Uso: /canalhandia zoacao padrao <texto> (atual: " + settings.zoacaoPattern() + ")");
|
||||
return;
|
||||
}
|
||||
String pattern = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
|
||||
settings.zoacaoPattern(pattern);
|
||||
Msg.ok(sender, "Padrão da zoação: " + pattern + ".");
|
||||
}
|
||||
case "adicionar", "add" -> {
|
||||
if (args.length < 2) {
|
||||
Msg.error(sender, "Uso: /canalhandia zoacao adicionar <frase>");
|
||||
return;
|
||||
}
|
||||
String line = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
|
||||
List<String> messages = new ArrayList<>(settings.zoacaoMessages());
|
||||
messages.add(line);
|
||||
settings.zoacaoMessages(messages);
|
||||
Msg.ok(sender, "Adicionado: " + line + " (agora " + messages.size() + " mensagens).");
|
||||
}
|
||||
case "remover", "remove" -> {
|
||||
List<String> messages = new ArrayList<>(settings.zoacaoMessages());
|
||||
if (args.length < 2) {
|
||||
Msg.error(sender, "Uso: /canalhandia zoacao remover <número|texto>");
|
||||
return;
|
||||
}
|
||||
String target = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
|
||||
int index = parse(target, Integer.MIN_VALUE);
|
||||
boolean removed;
|
||||
if (index != Integer.MIN_VALUE) {
|
||||
int idx = index - 1;
|
||||
removed = idx >= 0 && idx < messages.size();
|
||||
if (removed) {
|
||||
messages.remove(idx);
|
||||
}
|
||||
} else {
|
||||
removed = messages.removeIf(m -> m.equalsIgnoreCase(target));
|
||||
}
|
||||
if (!removed) {
|
||||
Msg.error(sender, "Não encontrei '" + target + "' na lista.");
|
||||
return;
|
||||
}
|
||||
settings.zoacaoMessages(messages);
|
||||
Msg.ok(sender, "Removido. Restam " + messages.size() + " mensagens.");
|
||||
}
|
||||
case "limpar" -> {
|
||||
// Clear the configured list so the built-in defaults come back.
|
||||
settings.zoacaoMessages(List.of());
|
||||
Msg.ok(sender, "Lista limpa — voltou para as mensagens padrão.");
|
||||
}
|
||||
default -> Msg.error(sender, "Uso: /canalhandia zoacao <listar|modo|padrao|adicionar|remover|limpar>");
|
||||
}
|
||||
}
|
||||
|
||||
private void clear(CommandSender sender, String[] args) {
|
||||
if (!admin(sender)) {
|
||||
return;
|
||||
@@ -666,6 +758,8 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter {
|
||||
}
|
||||
}
|
||||
Msg.line(sender, "categorias ativas", enabled.isEmpty() ? "nenhuma" : String.join(", ", enabled));
|
||||
Msg.line(sender, "zoação", settings.zoacaoMode().key() + " '" + settings.zoacaoPattern()
|
||||
+ "' (" + settings.zoacaoMessages().size() + " mensagens)");
|
||||
Msg.line(sender, "ia", plugin.ai().configured()
|
||||
? settings.aiModel() + " · perfil " + settings.aiProfile().name().toLowerCase(Locale.ROOT)
|
||||
+ " · " + plugin.ai().askedToday() + "/" + settings.aiDailyLimit() + " hoje"
|
||||
@@ -724,6 +818,12 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter {
|
||||
commands.put("/curiosidade reacao add <chave> <rótulo>", "cria ou muda uma reação");
|
||||
commands.put("/curiosidade reacao remover <chave>", "remove uma reação");
|
||||
commands.put("/curiosidade categoria <nome> <on|off>", "liga/desliga uma categoria");
|
||||
commands.put("/canalhandia zoacao listar", "mostra a regra e as frases da zoação");
|
||||
commands.put("/canalhandia zoacao modo <m>", "igual | contem | comeca | termina | regex");
|
||||
commands.put("/canalhandia zoacao padrao <texto>", "texto/regex que dispara a zoação");
|
||||
commands.put("/canalhandia zoacao adicionar <frase>", "adiciona uma frase de zoação");
|
||||
commands.put("/canalhandia zoacao remover <n|texto>", "remove uma frase de zoação");
|
||||
commands.put("/canalhandia zoacao limpar", "volta para as frases padrão");
|
||||
}
|
||||
commands.forEach((cmd, description) -> sender.sendMessage(
|
||||
Component.text(" " + cmd, NamedTextColor.AQUA)
|
||||
@@ -893,7 +993,7 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter {
|
||||
if (args.length == 1) {
|
||||
List<String> options = new ArrayList<>(List.of("status", "modulos", "plataformas"));
|
||||
if (sender.hasPermission(ADMIN)) {
|
||||
options.addAll(List.of("modulo", "marcos", "limpar", "reload"));
|
||||
options.addAll(List.of("modulo", "marcos", "limpar", "zoacao", "reload"));
|
||||
}
|
||||
return filter(options, args[0]);
|
||||
}
|
||||
@@ -907,6 +1007,12 @@ final class CanalhandiaCommand implements CommandExecutor, TabCompleter {
|
||||
if (args.length == 2 && args[0].equalsIgnoreCase("limpar")) {
|
||||
return filter(List.of("cooldown", "historico", "tudo"), args[1]);
|
||||
}
|
||||
if (args.length == 2 && args[0].equalsIgnoreCase("zoacao")) {
|
||||
return filter(List.of("listar", "modo", "padrao", "adicionar", "remover", "limpar"), args[1]);
|
||||
}
|
||||
if (args.length == 3 && args[0].equalsIgnoreCase("zoacao") && args[1].equalsIgnoreCase("modo")) {
|
||||
return filter(List.of("igual", "contem", "comeca", "termina", "regex"), args[2]);
|
||||
}
|
||||
if (args.length == 3 && args[0].equalsIgnoreCase("modulo")) {
|
||||
return filter(List.of("on", "off"), args[2]);
|
||||
}
|
||||
|
||||
@@ -347,9 +347,9 @@ final class Settings {
|
||||
// --- zoacao (f-gag) -----------------------------------------------------
|
||||
|
||||
/**
|
||||
* Lines a bare "f" in chat gets replaced with, picked at random. Defaults
|
||||
* to a small built-in list if unset/empty so the feature works out of the
|
||||
* box; operators edit {@code zoacao.mensagens} in config.yml to customise.
|
||||
* Lines a matching chat message gets replaced with, picked at random.
|
||||
* Defaults to a small built-in list if unset/empty so the feature works out
|
||||
* of the box; operators edit {@code zoacao.mensagens} in-game to customise.
|
||||
*/
|
||||
List<String> zoacaoMessages() {
|
||||
List<String> messages = plugin.getConfig().getStringList("zoacao.mensagens");
|
||||
@@ -365,6 +365,31 @@ final class Settings {
|
||||
return messages;
|
||||
}
|
||||
|
||||
/** Writes the full message list through to config immediately. */
|
||||
void zoacaoMessages(List<String> messages) {
|
||||
plugin.getConfig().set("zoacao.mensagens", messages);
|
||||
plugin.saveConfig();
|
||||
}
|
||||
|
||||
/** How a chat message is tested against the trigger pattern. */
|
||||
Zoacao.Mode zoacaoMode() {
|
||||
return Zoacao.Mode.byKeyOrDefault(plugin.getConfig().getString("zoacao.correspondencia", "igual"),
|
||||
Zoacao.Mode.IGUAL);
|
||||
}
|
||||
|
||||
void zoacaoMode(Zoacao.Mode mode) {
|
||||
set("zoacao.correspondencia", mode.key());
|
||||
}
|
||||
|
||||
/** The trigger text (or regex for the {@code regex} mode). */
|
||||
String zoacaoPattern() {
|
||||
return plugin.getConfig().getString("zoacao.padrao", "f");
|
||||
}
|
||||
|
||||
void zoacaoPattern(String pattern) {
|
||||
set("zoacao.padrao", pattern);
|
||||
}
|
||||
|
||||
// --- content ------------------------------------------------------------
|
||||
|
||||
boolean categoryEnabled(Category category) {
|
||||
|
||||
@@ -1,37 +1,110 @@
|
||||
package dev.marcospaulo.canalhandia;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Pure logic for the {@code zoacao} chat gag: when a player sends a bare
|
||||
* {@code "f"} (or {@code "F"}, trimmed, nothing else) their message is swapped
|
||||
* for a random line from a configurable list. Extracted so the trigger rule is
|
||||
* Pure logic for the {@code zoacao} chat gag: when a player's chat message
|
||||
* matches a configurable trigger (a pattern + a match mode), it is swapped
|
||||
* for a random line from a configurable list. Extracted so the match rule is
|
||||
* unit-testable without a server.
|
||||
*
|
||||
* <p>Match modes:
|
||||
* <ul>
|
||||
* <li>{@link Mode#IGUAL} — message equals the pattern (ignoring case, trimmed)</li>
|
||||
* <li>{@link Mode#CONTEM} — message contains the pattern (case-insensitive)</li>
|
||||
* <li>{@link Mode#COMECA} — message starts with the pattern</li>
|
||||
* <li>{@link Mode#TERMINA} — message ends with the pattern</li>
|
||||
* <li>{@link Mode#REGEX} — pattern is a case-insensitive regex, matched anywhere</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>This is a standalone chat gag. It does not interact with the {@code luto}
|
||||
* tribute — paying respects still happens via the {@code [F]} button (Java) or
|
||||
* the {@code /f} command (Bedrock), neither of which is a chat message.
|
||||
*/
|
||||
final class Zoacao {
|
||||
|
||||
/** How a chat message is tested against the trigger pattern. */
|
||||
enum Mode {
|
||||
IGUAL("igual"),
|
||||
CONTEM("contem"),
|
||||
COMECA("comeca"),
|
||||
TERMINA("termina"),
|
||||
REGEX("regex");
|
||||
|
||||
private final String key;
|
||||
|
||||
Mode(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
String key() {
|
||||
return key;
|
||||
}
|
||||
|
||||
static Mode byKey(String key) {
|
||||
for (Mode mode : values()) {
|
||||
if (mode.key.equalsIgnoreCase(key)) {
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Mode byKeyOrDefault(String key, Mode fallback) {
|
||||
Mode mode = byKey(key);
|
||||
return mode == null ? fallback : mode;
|
||||
}
|
||||
}
|
||||
|
||||
private Zoacao() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message the chat message as sent by the player
|
||||
* @param mode how to test the message against the pattern
|
||||
* @param pattern the trigger text (or regex for {@link Mode#REGEX})
|
||||
* @param gags the configured replacement lines; if null/empty, no gag
|
||||
* @param random shared random used to pick a line
|
||||
* @return the replacement line if the message is a bare "f", otherwise null
|
||||
* @return the replacement line if the message matches, otherwise null
|
||||
* (meaning "leave the message alone")
|
||||
*/
|
||||
static String replace(String message, List<String> gags, Random random) {
|
||||
if (message == null || gags == null || gags.isEmpty()) {
|
||||
static String replace(String message, Mode mode, String pattern, List<String> gags, Random random) {
|
||||
if (message == null || gags == null || gags.isEmpty() || pattern == null || pattern.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
if (!message.trim().equalsIgnoreCase("f")) {
|
||||
if (!matches(message, mode, pattern)) {
|
||||
return null;
|
||||
}
|
||||
return gags.get(random.nextInt(gags.size()));
|
||||
}
|
||||
|
||||
/** Pure test of one message against one pattern under one mode. */
|
||||
static boolean matches(String message, Mode mode, String pattern) {
|
||||
if (message == null || mode == null || pattern == null) {
|
||||
return false;
|
||||
}
|
||||
String trimmed = message.trim();
|
||||
String needle = pattern.toLowerCase(Locale.ROOT);
|
||||
switch (mode) {
|
||||
case IGUAL:
|
||||
return trimmed.equalsIgnoreCase(pattern);
|
||||
case CONTEM:
|
||||
return trimmed.toLowerCase(Locale.ROOT).contains(needle);
|
||||
case COMECA:
|
||||
return trimmed.toLowerCase(Locale.ROOT).startsWith(needle);
|
||||
case TERMINA:
|
||||
return trimmed.toLowerCase(Locale.ROOT).endsWith(needle);
|
||||
case REGEX:
|
||||
try {
|
||||
return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(trimmed).find();
|
||||
} catch (java.util.regex.PatternSyntaxException e) {
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,9 +71,20 @@ janela-reacao-segundos: 90
|
||||
luto:
|
||||
cabeca: true
|
||||
|
||||
# Frases que substituem um "f" sozinho no chat (módulo zoacao). Uma é sorteada
|
||||
# por mensagem. Edite à vontade — a graça é ser inesperado.
|
||||
# Zoa de quem manda uma mensagem que bate com o padrão, trocando por uma frase
|
||||
# engraçada. Tudo editável em jogo com /canalhandia zoacao ...
|
||||
zoacao:
|
||||
# Como comparar a mensagem do chat com o padrão:
|
||||
# igual - mensagem inteira igual ao padrão (ignora maiúsculas e espaços)
|
||||
# contem - mensagem contém o padrão em qualquer lugar
|
||||
# comeca - mensagem começa com o padrão
|
||||
# termina - mensagem termina com o padrão
|
||||
# regex - padrão é uma expressão regular (maiúsculas ignoradas)
|
||||
correspondencia: igual
|
||||
# Texto (ou regex) que dispara a zoação. Padrão: só um "f" sozinho.
|
||||
padrao: "f"
|
||||
# Frases que substituem a mensagem. Uma é sorteada por vez. Edite à vontade —
|
||||
# a graça é ser inesperado.
|
||||
mensagens:
|
||||
- "Sou gay"
|
||||
- "Gosto de anime"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.marcospaulo.canalhandia;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@@ -13,48 +14,129 @@ class ZoacaoTest {
|
||||
private static final List<String> GAGS = List.of(
|
||||
"Sou gay", "Gosto de anime", "Jogo no celular");
|
||||
|
||||
// --- Mode.byKey ---------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void bareLowercaseFIsReplacedWithAGagFromTheList() {
|
||||
String gag = Zoacao.replace("f", GAGS, new Random(0L));
|
||||
void modeByKeyParsesEachMode() {
|
||||
assertEquals(Zoacao.Mode.IGUAL, Zoacao.Mode.byKey("igual"));
|
||||
assertEquals(Zoacao.Mode.CONTEM, Zoacao.Mode.byKey("contem"));
|
||||
assertEquals(Zoacao.Mode.COMECA, Zoacao.Mode.byKey("comeca"));
|
||||
assertEquals(Zoacao.Mode.TERMINA, Zoacao.Mode.byKey("termina"));
|
||||
assertEquals(Zoacao.Mode.REGEX, Zoacao.Mode.byKey("regex"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void modeByKeyIsCaseInsensitive() {
|
||||
assertEquals(Zoacao.Mode.CONTEM, Zoacao.Mode.byKey("CONTEM"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void modeByKeyReturnsNullForUnknown() {
|
||||
assertNull(Zoacao.Mode.byKey("exato"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void modeByKeyOrDefaultFallsBack() {
|
||||
assertEquals(Zoacao.Mode.IGUAL, Zoacao.Mode.byKeyOrDefault("xx", Zoacao.Mode.IGUAL));
|
||||
assertEquals(Zoacao.Mode.CONTEM, Zoacao.Mode.byKeyOrDefault("contem", Zoacao.Mode.IGUAL));
|
||||
}
|
||||
|
||||
// --- matches / replace: IGUAL ------------------------------------------
|
||||
|
||||
@Test
|
||||
void igualBareLowercaseFMatches() {
|
||||
assertTrue(Zoacao.matches("f", Zoacao.Mode.IGUAL, "f"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void igualBareUppercaseFMatches() {
|
||||
assertTrue(Zoacao.matches("F", Zoacao.Mode.IGUAL, "f"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void igualSurroundingWhitespaceStillMatches() {
|
||||
assertTrue(Zoacao.matches(" f ", Zoacao.Mode.IGUAL, "f"));
|
||||
assertTrue(Zoacao.matches("\tF\n", Zoacao.Mode.IGUAL, "f"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void igualFWithAnythingElseDoesNotMatch() {
|
||||
assertFalse(Zoacao.matches("f lol", Zoacao.Mode.IGUAL, "f"));
|
||||
assertFalse(Zoacao.matches("ff", Zoacao.Mode.IGUAL, "f"));
|
||||
assertFalse(Zoacao.matches("pra você f", Zoacao.Mode.IGUAL, "f"));
|
||||
}
|
||||
|
||||
// --- matches: CONTEM / COMECA / TERMINA ---------------------------------
|
||||
|
||||
@Test
|
||||
void contemMatchesAnywhere() {
|
||||
assertTrue(Zoacao.matches("aaaffffaaa", Zoacao.Mode.CONTEM, "fff"));
|
||||
assertTrue(Zoacao.matches("morte do f cara", Zoacao.Mode.CONTEM, "f"));
|
||||
assertFalse(Zoacao.matches("oi", Zoacao.Mode.CONTEM, "f"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void comecaMatchesAtStart() {
|
||||
assertTrue(Zoacao.matches("f para o morto", Zoacao.Mode.COMECA, "f"));
|
||||
assertTrue(Zoacao.matches("FFFreak", Zoacao.Mode.COMECA, "f"));
|
||||
assertFalse(Zoacao.matches("oi f", Zoacao.Mode.COMECA, "f"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void terminaMatchesAtEnd() {
|
||||
assertTrue(Zoacao.matches("press f", Zoacao.Mode.TERMINA, "f"));
|
||||
assertTrue(Zoacao.matches("mais F", Zoacao.Mode.TERMINA, "f"));
|
||||
assertFalse(Zoacao.matches("f oi", Zoacao.Mode.TERMINA, "f"));
|
||||
}
|
||||
|
||||
// --- matches: REGEX -----------------------------------------------------
|
||||
|
||||
@Test
|
||||
void regexMatchesAnywhereCaseInsensitive() {
|
||||
assertTrue(Zoacao.matches("drop f na fogueira", Zoacao.Mode.REGEX, "\\bf\\b"));
|
||||
assertTrue(Zoacao.matches("FFFFFFFF", Zoacao.Mode.REGEX, "f+"));
|
||||
assertFalse(Zoacao.matches("floresta", Zoacao.Mode.REGEX, "^f$"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void regexInvalidPatternDoesNotMatch() {
|
||||
assertFalse(Zoacao.matches("f", Zoacao.Mode.REGEX, "(["));
|
||||
}
|
||||
|
||||
// --- replace -----------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void replaceReturnsAGagWhenMatch() {
|
||||
String gag = Zoacao.replace("f", Zoacao.Mode.IGUAL, "f", GAGS, new Random(0L));
|
||||
assertTrue(GAGS.contains(gag), "expected a gag from the list, got " + gag);
|
||||
}
|
||||
|
||||
@Test
|
||||
void bareUppercaseFIsReplaced() {
|
||||
// A single-element list makes the random pick deterministic.
|
||||
String gag = Zoacao.replace("F", List.of("alvo"), new Random(0L));
|
||||
assertEquals("alvo", gag);
|
||||
void replaceSingleElementListIsDeterministic() {
|
||||
assertEquals("alvo",
|
||||
Zoacao.replace("f", Zoacao.Mode.IGUAL, "f", List.of("alvo"), new Random(0L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void surroundingWhitespaceStillCountsAsBareF() {
|
||||
assertEquals("alvo", Zoacao.replace(" f ", List.of("alvo"), new Random(0L)));
|
||||
assertEquals("alvo", Zoacao.replace("\tF\n", List.of("alvo"), new Random(0L)));
|
||||
void replaceReturnsNullWhenNoMatch() {
|
||||
assertNull(Zoacao.replace("oi", Zoacao.Mode.IGUAL, "f", GAGS, new Random(0L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void fWithAnythingElseIsLeftAlone() {
|
||||
assertNull(Zoacao.replace("f lol", GAGS, new Random(0L)));
|
||||
assertNull(Zoacao.replace("ff", GAGS, new Random(0L)));
|
||||
assertNull(Zoacao.replace("f.", GAGS, new Random(0L)));
|
||||
assertNull(Zoacao.replace("pra você f", GAGS, new Random(0L)));
|
||||
void replaceReturnsNullForEmptyOrNullGags() {
|
||||
assertNull(Zoacao.replace("f", Zoacao.Mode.IGUAL, "f", List.of(), new Random(0L)));
|
||||
assertNull(Zoacao.replace("f", Zoacao.Mode.IGUAL, "f", null, new Random(0L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonFMessagesAreLeftAlone() {
|
||||
assertNull(Zoacao.replace("oi", GAGS, new Random(0L)));
|
||||
assertNull(Zoacao.replace("", GAGS, new Random(0L)));
|
||||
assertNull(Zoacao.replace("F para o morto", GAGS, new Random(0L)));
|
||||
void replaceReturnsNullForBlankOrNullPattern() {
|
||||
assertNull(Zoacao.replace("f", Zoacao.Mode.IGUAL, "", GAGS, new Random(0L)));
|
||||
assertNull(Zoacao.replace("f", Zoacao.Mode.IGUAL, " ", GAGS, new Random(0L)));
|
||||
assertNull(Zoacao.replace("f", Zoacao.Mode.IGUAL, null, GAGS, new Random(0L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void emptyOrNullGagsLeaveMessageAlone() {
|
||||
assertNull(Zoacao.replace("f", List.of(), new Random(0L)));
|
||||
assertNull(Zoacao.replace("f", null, new Random(0L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void nullMessageLeftAlone() {
|
||||
assertNull(Zoacao.replace(null, GAGS, new Random(0L)));
|
||||
void replaceReturnsNullForNullMessage() {
|
||||
assertNull(Zoacao.replace(null, Zoacao.Mode.IGUAL, "f", GAGS, new Random(0L)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user