diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..ad15fa9 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,34 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle + +name: Java CI with Gradle + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Build with Gradle + uses: gradle/gradle-build-action@0d13054264b0bb894ded474f08ebb30921341cee + with: + arguments: build diff --git a/build.gradle b/build.gradle index cbbabc8..8eb558b 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { } group 'edu.regent' -version '1.1' +version '1.2' sourceCompatibility = 1.17 diff --git a/src/main/java/edu/regent/shiritoribot/ShiritoriBot.java b/src/main/java/edu/regent/shiritoribot/ShiritoriBot.java index c322fd6..2aa60a5 100644 --- a/src/main/java/edu/regent/shiritoribot/ShiritoriBot.java +++ b/src/main/java/edu/regent/shiritoribot/ShiritoriBot.java @@ -20,9 +20,6 @@ public class ShiritoriBot { public static JDA jda; public static void main(String[] args) { - - - System.out.println(System.getenv("Discord_Secret_Token")); JDABuilder builder = JDABuilder.createDefault(System.getenv("Discord_Secret_Token")); //JDABuilder builder = JDABuilder.create(DISCORD_SECRET_TOKEN, GatewayIntent.) todo: setup correct intents builder.addEventListeners(buildCommandManager()); @@ -41,7 +38,8 @@ public static boolean isAuthorOf(Message message) { public static WordDictionary getWordDictionary() { try { - return WordDictionary.fromFile(new File(ShiritoriBot.class.getClassLoader().getResource("CollinsScrabbleWords(2019).txt").getFile())); + + return WordDictionary.fromStream(ShiritoriBot.class.getClassLoader().getResourceAsStream("CollinsScrabbleWords(2019).txt")); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/main/java/edu/regent/shiritoribot/discord/ChannelListener.java b/src/main/java/edu/regent/shiritoribot/discord/ChannelListener.java index 5d5e05c..e336fd2 100644 --- a/src/main/java/edu/regent/shiritoribot/discord/ChannelListener.java +++ b/src/main/java/edu/regent/shiritoribot/discord/ChannelListener.java @@ -39,11 +39,4 @@ public void sendGameJoinMessage(TextChannel channel) { } - - @Override - public void onGuildMessageReactionAdd(@Nonnull GuildMessageReactionAddEvent event) { - System.out.println("guild message reacted"); - } - - } diff --git a/src/main/java/edu/regent/shiritoribot/discord/textChannel/ActiveGameController.java b/src/main/java/edu/regent/shiritoribot/discord/textChannel/ActiveGameController.java index 7c8ad9a..021b939 100644 --- a/src/main/java/edu/regent/shiritoribot/discord/textChannel/ActiveGameController.java +++ b/src/main/java/edu/regent/shiritoribot/discord/textChannel/ActiveGameController.java @@ -5,14 +5,12 @@ import edu.regent.shiritoribot.discord.ShiritoriPlayer; import edu.regent.shiritoribot.game.EliminationException; import edu.regent.shiritoribot.game.ShiritoriWordValidator; -import net.dv8tion.jda.api.MessageBuilder; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.TextChannel; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import javax.annotation.Nonnull; -import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -20,10 +18,10 @@ public class ActiveGameController extends ChannelController { - private static long TURN_TIMEOUT_MILLIS = 30_000; + private static final long TURN_TIMEOUT_MILLIS = 30_000; - private List alivePlayers; - private List deadPlayers; + private final List alivePlayers; + private final List deadPlayers; private ShiritoriPlayer activePlayer; private ShiritoriWordValidator wordValidator; @@ -35,16 +33,22 @@ public ActiveGameController(TextChannel channel, Collection ini this.alivePlayers = new ArrayList<>(initialPlayers); this.deadPlayers = new ArrayList<>(); Collections.shuffle(alivePlayers); - activePlayer = alivePlayers.get(0); //will be skipped, get(1) will actually be first player to act) + } @Override protected void init() { clearChannelHistory(); + if(alivePlayers.isEmpty()) { + channel.sendMessage("Unable to start a game with no players").queue(); + close(); + return; + } for(ShiritoriPlayer player : alivePlayers) { player.setStatus(PlayerStatus.ALIVE); } wordValidator = new ShiritoriWordValidator(ShiritoriBot.getWordDictionary()); + activePlayer = alivePlayers.get(0); //will be skipped, get(1) will actually be first player to act nextPlayer(); } @@ -72,7 +76,7 @@ public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) { private void declareWinner(ShiritoriPlayer player) { player.setStatus(PlayerStatus.NO_VISIBLE_STATUS); - channel.sendMessage(player.getMember().getEffectiveName() + " WINS!").queue(); + channel.sendMessage(player.getMember().getAsMention() + " WINS!").queue(); close(); } @@ -114,11 +118,10 @@ private void nextPlayer() { activePlayer = alivePlayers.get(indexOfNextPlayer); } - System.out.println("Next Player: " + activePlayer.getName()); if(nextPlayerDisplayMessage != null) { nextPlayerDisplayMessage.delete().complete(); } - nextPlayerDisplayMessage = channel.sendMessage("Next Player: " + activePlayer.getName()).complete(); + nextPlayerDisplayMessage = channel.sendMessage("Next Player: " + activePlayer.getMember().getAsMention()).complete(); resetTimeout(); } diff --git a/src/main/java/edu/regent/shiritoribot/discord/textChannel/LobbyController.java b/src/main/java/edu/regent/shiritoribot/discord/textChannel/LobbyController.java index 2a8bd2b..bea24fd 100644 --- a/src/main/java/edu/regent/shiritoribot/discord/textChannel/LobbyController.java +++ b/src/main/java/edu/regent/shiritoribot/discord/textChannel/LobbyController.java @@ -16,8 +16,11 @@ public class LobbyController extends ChannelController { private static final String INITIAL_JOIN_TAG = "{shirijoin}"; - private static final String ACTUAL_JOIN_MESSAGE = "Creating game of Shiritori\n React to this message to join"; private static final String START_COMMAND = "!start"; + private static final String CANCEL_COMMAND = "!cancel"; + private static final String ACTUAL_JOIN_MESSAGE = "Creating game of Shiritori\n React to this message to join\n " + + "type " + START_COMMAND + " once all players have joined or " + CANCEL_COMMAND + " to cancel the game" ; + @@ -51,11 +54,10 @@ public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) { msg.editMessage(ACTUAL_JOIN_MESSAGE).queue(); msg.addReaction("U+2705").queue(); joinMsgID = msg.getId(); - return; - } - - if(isStartCommand(event)) { + } else if(isStartCommand(event)) { passControlTo(new ActiveGameController(channel, players.values())); + } else if(isCancelCommand(event)) { + passControlTo(new IdleController(channel)); } } @@ -90,4 +92,8 @@ private boolean isInitialJoinTag(GuildMessageReceivedEvent event) { private boolean isStartCommand(GuildMessageReceivedEvent event) { return event.getMessage().getContentDisplay().equalsIgnoreCase(START_COMMAND); } + + private boolean isCancelCommand(GuildMessageReceivedEvent event) { + return event.getMessage().getContentDisplay().equalsIgnoreCase(CANCEL_COMMAND); + } } diff --git a/src/main/java/edu/regent/shiritoribot/game/WordDictionary.java b/src/main/java/edu/regent/shiritoribot/game/WordDictionary.java index c69ea7f..c1dc0e5 100644 --- a/src/main/java/edu/regent/shiritoribot/game/WordDictionary.java +++ b/src/main/java/edu/regent/shiritoribot/game/WordDictionary.java @@ -2,7 +2,9 @@ import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Scanner; @@ -16,11 +18,14 @@ public static WordDictionary of(String... wordList) { } public static WordDictionary fromFile(File file) throws IOException { - Scanner scanner = new Scanner(file); + return fromStream(new FileInputStream(file)); + } + + public static WordDictionary fromStream(InputStream inputStream) throws IOException { + Scanner scanner = new Scanner(inputStream); scanner.useDelimiter(Pattern.compile("[,\n]+")); List wordList = new ArrayList<>(); while(scanner.hasNext()) { - //System.out.println(scanner.next()); wordList.add(scanner.next().trim()); } return new SimpleWordDictionaryImpl(wordList); diff --git a/src/test/java/edu/regent/shirtoribot/game/WordDictionaryTests.java b/src/test/java/edu/regent/shirtoribot/game/WordDictionaryTests.java index 0ce8bc8..f0ad3f1 100644 --- a/src/test/java/edu/regent/shirtoribot/game/WordDictionaryTests.java +++ b/src/test/java/edu/regent/shirtoribot/game/WordDictionaryTests.java @@ -39,4 +39,16 @@ public void fromFile_loadsAllWords() throws Exception { assert(dict.contains("salt lake city")); //ensures multi-word names work } + @Test + public void fromStream_loadsAllWords() throws Exception { + var inputSteam = getClass().getClassLoader().getResourceAsStream("simpleDictionary.txt"); + dict = WordDictionary.fromStream(inputSteam); + + assert(dict.contains("europe")); + assert(dict.contains("neptune")); + assert(dict.contains("mars")); + assert(dict.contains("jupiter")); + assert(dict.contains("salt lake city")); //ensures multi-word names work + } + }