package com.github.donkirkby.vograbulary.ultraghost; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import java.util.Arrays; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import com.github.donkirkby.vograbulary.SerializableTools; public class PuzzleTest { @Rule public ExpectedException thrown = ExpectedException.none(); private Puzzle puzzle; private String letters; private WordList wordList; private Student owner; private int changeCount; private int completionCount; private String changedSolution; @Before public void setUp() { letters = "PIE"; wordList = new WordList(); wordList.read(Arrays.asList("PRICE", "PIECE", "PIPE")); owner = new Student("Student"); changeCount = 0; completionCount = 0; changedSolution = null; puzzle = new Puzzle(letters, owner, wordList); puzzle.addListener(new Puzzle.Listener() { @Override public void changed() { changeCount++; changedSolution = puzzle.getSolution(); } @Override public void completed() { completionCount++; } }); } @Test public void startingResult() { WordResult result = puzzle.getResult(); assertThat("result", result, is(WordResult.UNKNOWN)); } @Test public void nullLetters() { letters = null; thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Puzzle letters were null."); new Puzzle(letters, owner, wordList); } @Test public void nullOwner() { owner = null; thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Puzzle owner was null."); new Puzzle(letters, owner, wordList); } @Test public void noWordListSolution() { puzzle = new Puzzle(letters, owner); puzzle.setSolution("PIXXE"); //Won't check that solution is a real word assertThat("result", puzzle.getResult(), is(WordResult.VALID)); } @Test public void noWordListResponse() { puzzle = new Puzzle(letters, owner); puzzle.setSolution("PIXXE"); //Won't check that solution is a real word puzzle.setResponse("PIXE"); //Won't check that solution is a real word assertThat("result", puzzle.getResult(), is(WordResult.SHORTER)); } @Test public void string() { String string = puzzle.toString(); assertThat("string", string, is("Puzzle(PIE, Student)")); } @Test public void getLettersDisplaySimple() { assertThat( "letters display", puzzle.getLettersDisplay(), is("PIE")); } @Test public void getLettersDisplayPrevious() { puzzle.setPreviousWord("PIPE"); assertThat( "letters display", puzzle.getLettersDisplay(), is("PIE after PIPE")); } @Test public void getNextBetterAfterPrevious() { puzzle.setPreviousWord("PRICE"); puzzle.setSolution(Puzzle.NO_SOLUTION); puzzle.setResponse(Puzzle.NO_SOLUTION); assertThat("hint", puzzle.findNextBetter(), nullValue()); } @Test public void solutionChangeEvent() { String expectedSolution = "XXXX"; puzzle.setSolution(expectedSolution); assertThat("change count", changeCount, is(1)); assertThat("solution", changedSolution, is(expectedSolution)); } @Test public void responseChangeEvent() { puzzle.setResponse("XXXX"); assertThat("change count", changeCount, is(1)); } @Test public void hintChangeEvent() { puzzle.setHint("XXXX"); assertThat("change count", changeCount, is(1)); } @Test public void completionEvent() { puzzle.setSolution("PRICE"); puzzle.setResponse("PIECE"); assertThat("completion count", completionCount, is(1)); } @Test public void completionEventHappensOnlyOnce() { puzzle.setSolution("PRICE"); puzzle.setResponse("PIECE"); puzzle.setHint("ZZZZ"); assertThat("completion count", completionCount, is(1)); } @Test public void adjustScoreAtStart() { float seconds = 0; puzzle.adjustScore(seconds); int score = puzzle.getScore(WordResult.NOT_IMPROVED); assertThat("score", score, is(100)); } @Test public void adjustScoreAfterDelay() { // Lose 2% every second. float seconds = 10; puzzle.adjustScore(seconds); int score = puzzle.getScore(WordResult.NOT_IMPROVED); assertThat("score", score, is(98)); } @Test public void adjustScoreAfterSecondDelay() { float seconds = 10; puzzle.adjustScore(seconds); puzzle.adjustScore(seconds); int score = puzzle.getScore(WordResult.NOT_IMPROVED); assertThat("score", score, is(95)); } @Test public void adjustScoreAfterTimeout() { float seconds = 51; puzzle.adjustScore(seconds); int score = puzzle.getScore(WordResult.NOT_IMPROVED); assertThat("score", score, is(0)); } @Test public void adjustScoreWhenPaused() { float seconds = 10; puzzle.setPaused(true); puzzle.adjustScore(seconds); int score = puzzle.getScore(WordResult.NOT_IMPROVED); assertThat("score", score, is(100)); } @Test public void togglePause() { boolean isPaused1 = puzzle.isPaused(); puzzle.togglePause(); boolean isPaused2 = puzzle.isPaused(); int startCount = changeCount; puzzle.togglePause(); boolean isPaused3 = puzzle.isPaused(); assertThat("paused at start", isPaused1, is(false)); assertThat("paused after toggle", isPaused2, is(true)); assertThat("paused after toggle back", isPaused3, is(false)); assertThat("changeCount", changeCount, is(startCount+1)); } @Test public void getDisplayAtStart() { float seconds = 0; puzzle.adjustScore(seconds); String display = puzzle.getResultDisplay(); assertThat("display", display, is("100")); } @Test public void getDisplayAfterSolution() { float seconds = 0; puzzle.adjustScore(seconds); puzzle.setSolution("PRICE"); String display = puzzle.getResultDisplay(); assertThat("display", display, is("valid 33 of 100")); } @Test public void getDisplayAfterSkip() { // Drops slowly at first, to 60 after 40.2s. float seconds = 40.2f; puzzle.adjustScore(seconds); puzzle.setSolution(""); String display = puzzle.getResultDisplay(); assertThat("display", display, is("skipping -20 of 20")); } @Test public void getDisplayAfterResponse() { float seconds = 40.2f; puzzle.adjustScore(seconds); puzzle.setSolution("PRICE"); puzzle.setResponse("PIECE"); String display = puzzle.getResultDisplay(); assertThat("display", display, is("earlier (40 of 60)")); } @Test public void getDisplayAfterInvalidResponse() { float seconds = 40.2f; puzzle.adjustScore(seconds); puzzle.setSolution(""); puzzle.setResponse("X"); String display = puzzle.getResultDisplay(); assertThat("display", display, is("not a word -12 of 20")); } @Test public void getScoreNotComplete() { int score = puzzle.getScore(); assertThat("display", score, is(0)); } @Test public void getScoreAfterSolution() { puzzle.setSolution("PRICE"); puzzle.setResponse(""); int score = puzzle.getScore(); assertThat("display", score, is(100)); } @Test public void getScoreAfterDelayedSolution() { float seconds = 10; puzzle.adjustScore(seconds); puzzle.setSolution("PRICE"); puzzle.setResponse(""); int score = puzzle.getScore(); assertThat("display", score, is(98)); } @Test public void getScoreAfterShorterResponse() { puzzle.setSolution("PRICE"); puzzle.setResponse("PIPE"); int score = puzzle.getScore(); assertThat("display", score, is(33)); } @Test public void getPotentialScore() { // Drops slowly at first, to 95 after 20s. float solutionSeconds = 20; puzzle.adjustScore(solutionSeconds); int notImprovedScore = puzzle.getScore(WordResult.NOT_IMPROVED); int earlierScore = puzzle.getScore(WordResult.EARLIER); int shorterScore = puzzle.getScore(WordResult.SHORTER); assertThat("display", notImprovedScore, is(95)); assertThat("display", earlierScore, is(63)); // 2/3 assertThat("display", shorterScore, is(32)); // 1/3 } @Test public void getScoreAfterInvalidSolution() { // Lose 5 seconds for invalid response float solutionSeconds = 12; float moreSolutionSeconds = 3; puzzle.adjustScore(solutionSeconds); puzzle.setSolution("PRIXE"); puzzle.adjustScore(moreSolutionSeconds); int notImprovedScore = puzzle.getScore(WordResult.NOT_IMPROVED); assertThat("display", notImprovedScore, is(95)); } @Test public void getScoreAfterDelayedResponse() { // Drops slowly at first, to 60 after 40.2s. float solutionSeconds = 40.2f; // Gain 4% of difference every second until response float responseSeconds = 5; // time between solution and response puzzle.adjustScore(solutionSeconds); puzzle.setSolution("PRICE"); puzzle.adjustScore(responseSeconds); int notImprovedScore = puzzle.getScore(WordResult.NOT_IMPROVED); int earlierScore = puzzle.getScore(WordResult.EARLIER); int shorterScore = puzzle.getScore(WordResult.SHORTER); assertThat("display", notImprovedScore, is(60)); assertThat("display", earlierScore, is(40 + 4)); assertThat("display", shorterScore, is(20 + 8)); } @Test public void getScoreAfterInvalidResponse() { // Drops slowly at first, to 60 after 40.2s. float solutionSeconds = 40.2f; // Gain 4% of difference every second until response, // also lose 5 seconds for invalid response float responseSeconds = 5; // time between solution and response puzzle.adjustScore(solutionSeconds); puzzle.setSolution("PRICE"); puzzle.adjustScore(responseSeconds); puzzle.setResponse("PCICE"); int notImprovedScore = puzzle.getScore(WordResult.NOT_IMPROVED); int earlierScore = puzzle.getScore(WordResult.EARLIER); int shorterScore = puzzle.getScore(WordResult.SHORTER); assertThat("not improved score", notImprovedScore, is(60)); assertThat("earlier score", earlierScore, is(40 + 8)); assertThat("shorter score", shorterScore, is(20 + 16)); assertThat("completionCount", completionCount, is(0)); } @Test public void getScoreAfterSkip() { // Drops slowly at first, to 60 after 40.2s. float solutionSeconds = 40.2f; // Gain 4% of difference every second until response float responseSeconds = 5; // time between solution and response puzzle.adjustScore(solutionSeconds); puzzle.setSolution(""); puzzle.adjustScore(responseSeconds); int skippedScore = puzzle.getScore(WordResult.SKIP_NOT_IMPROVED); int wordFoundScore = puzzle.getScore(WordResult.WORD_FOUND); assertThat("skipped score", skippedScore, is(20)); // 1/3 for skip assertThat("word found score", wordFoundScore, is(-20 + 8)); } @Test public void solutionTimeout() { // Out of time after 50s. float solutionSeconds = 50; puzzle.adjustScore(solutionSeconds); assertThat("score", puzzle.getScore(), is(0)); assertThat("result", puzzle.getResultDisplay(), is("out of time (0)")); assertThat("completion count", completionCount, is(1)); } @Test public void invalidSolutionTimeout() { // Lose 2% every second until solution float solutionSeconds = 45; puzzle.adjustScore(solutionSeconds); puzzle.setSolution("X"); assertThat("score", puzzle.getScore(), is(0)); assertThat( "result", puzzle.getResultDisplay(), is("not a word and out of time (0)")); } @Test public void responseTimeout() { // Gain 4% of difference every second until response float responseSeconds = 25; // time between solution and response puzzle.setSolution(""); puzzle.adjustScore(responseSeconds); assertThat("score", puzzle.getScore(), is(33)); assertThat( "result", puzzle.getResultDisplay(), is("skipping and out of time (33)")); assertThat("completion count", completionCount, is(1)); } @Test public void invalidResponseTimeout() { // Gain 4% of difference every second until response float responseSeconds = 20; // time between solution and response puzzle.setSolution(""); puzzle.adjustScore(responseSeconds); puzzle.setResponse("X"); assertThat("score", puzzle.getScore(), is(33)); assertThat( "result", puzzle.getResultDisplay(), is("not a word and out of time (33)")); assertThat("completion count", completionCount, is(1)); } @Test public void serialize() throws Exception { puzzle.setSolution("BAD"); puzzle.getResult(); byte[] bytes = SerializableTools.serialize(puzzle); Puzzle puzzle2 = SerializableTools.deserialize(bytes, Puzzle.class); assertThat("letters", puzzle2.getLetters(), is(puzzle.getLetters())); } }