384 lines
15 KiB
C#
384 lines
15 KiB
C#
using NUnit.Framework;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.TestTools;
|
|
public class HangmanPlaymodeTests
|
|
{
|
|
private HangmanController hangmanController;
|
|
|
|
private int multiplayerConfirmInput = 4;
|
|
|
|
/// <summary>
|
|
/// SetupFunction to reach the hangman-game
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[UnitySetUp]
|
|
public IEnumerator SetupFunction()
|
|
{
|
|
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
|
|
string oneUser = $"{{\"version\":1027,\"users\":[{{\"entries\":[],\"username\":\"TEST\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0}}";
|
|
|
|
File.WriteAllText(path, oneUser);
|
|
PersistentDataController.PATH = path;
|
|
PersistentDataController.GetInstance().Load();
|
|
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
|
|
|
|
// Go to the minigame-selection scene to make sure that the minigameIndex is set correctly
|
|
SystemController.GetInstance().LoadNextScene("Common/Scenes/ListMinigamesScreen");
|
|
yield return new WaitForSeconds(0.2f);
|
|
var minigameScreen = GameObject.FindObjectOfType<ListMinigamesScreen>();
|
|
minigameScreen.minigameList.SetCurrentMinigame(MinigameIndex.HANGMAN);
|
|
|
|
// Go to the Hangman-game
|
|
SystemController.GetInstance().LoadNextScene("Hangman/Scenes/HangmanGame");
|
|
yield return new WaitForSeconds(0.2f);
|
|
|
|
// Fetch the hangmanController
|
|
hangmanController = GameObject.FindObjectOfType<HangmanController>();
|
|
yield return new WaitForSeconds(0.2f);
|
|
|
|
// Fetch the SignPredictor and deactivate it, this stops the basic game-loop from happening
|
|
var signPredictor = GameObject.FindObjectOfType<SignPredictor>();
|
|
GameObject signPredictorController = signPredictor.gameObject;
|
|
signPredictorController.SetActive(false);
|
|
yield return new WaitForSeconds(0.2f);
|
|
|
|
// Put some old scores in the scoreboard to test its functionality
|
|
// One from one day ago
|
|
Score score1 = new Score();
|
|
score1.scoreValue = 50;
|
|
score1.time = DateTime.Now.AddDays(-1).ToString();
|
|
|
|
// One from one hour ago
|
|
Score score2 = new Score();
|
|
score2.scoreValue = 70;
|
|
score2.time = DateTime.Now.AddHours(-1).ToString();
|
|
|
|
// One from 5 minutes ago
|
|
Score score3 = new Score();
|
|
score3.scoreValue = 90;
|
|
score3.time = DateTime.Now.AddMinutes(-5).ToString();
|
|
|
|
// Save the new score
|
|
var progress = UserList.GetCurrentUser().GetMinigameProgress(MinigameIndex.HANGMAN);
|
|
|
|
// Get the current list of scores
|
|
List<Score> latestScores = progress.latestScores;
|
|
List<Score> highestScores = progress.highestScores;
|
|
|
|
// Add the new score
|
|
latestScores.Add(score1);
|
|
highestScores.Add(score1);
|
|
latestScores.Add(score2);
|
|
highestScores.Add(score2);
|
|
latestScores.Add(score3);
|
|
highestScores.Add(score3);
|
|
|
|
// Sort the scores
|
|
highestScores.Sort((a, b) => b.scoreValue.CompareTo(a.scoreValue));
|
|
|
|
// Only save the top 10 scores, so this list doesn't keep growing endlessly
|
|
progress.latestScores = latestScores.Take(10).ToList();
|
|
progress.highestScores = highestScores.Take(10).ToList();
|
|
|
|
PersistentDataController.GetInstance().Save();
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests the singleplayer functionality, only the winning side as losing is easier when the word is chosen beforehand.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[UnityTest]
|
|
public IEnumerator SinglePlayerTests()
|
|
{
|
|
// Start singlePlayer
|
|
hangmanController.SinglePlayer();
|
|
|
|
// Assert that a random word was generated and that the game has started
|
|
string currentWord = hangmanController.getCurrentWord();
|
|
Assert.IsTrue(currentWord.Length > 0);
|
|
Assert.IsTrue(hangmanController.getCurrentMode() == 2);
|
|
|
|
Assert.IsFalse(hangmanController.inputPanel.activeSelf);
|
|
Assert.IsFalse(hangmanController.playerPanel.activeSelf);
|
|
Assert.IsTrue(hangmanController.gamePanel.activeSelf);
|
|
Assert.IsFalse(hangmanController.gameEndedPanel.activeSelf);
|
|
|
|
// Fetch the panel with the info for the fields and check if the controller has implemented them
|
|
var script = GameObject.FindObjectOfType<PanelHangmanGame>();
|
|
|
|
Assert.IsTrue(hangmanController.inputTextField == script.guessesTextField);
|
|
Assert.IsTrue(hangmanController.feedbackText == script.feedbackText);
|
|
Assert.IsTrue(hangmanController.feedbackProgress == script.feedbackProgressBar);
|
|
Assert.IsTrue(hangmanController.feedbackProgressImage == script.feedbackProgressImage);
|
|
Assert.IsTrue(hangmanController.webcamScreen == script.webcamScreen);
|
|
Assert.IsTrue(hangmanController.timerCircle == script.timerCircle);
|
|
Assert.IsTrue(hangmanController.confirmPanel == script.confirmPanel);
|
|
Assert.IsTrue(hangmanController.confirmText == script.confirmText);
|
|
|
|
Assert.IsTrue(hangmanController.getCorrects() == 0);
|
|
Assert.IsTrue(hangmanController.getWrongs() == 0);
|
|
Assert.IsTrue(hangmanController.getUsedLetters().Length == 0);
|
|
|
|
// Start guessing the word, start by trying a wrong letter to check if the image changes
|
|
string letter = "";
|
|
int localWrongs = 0;
|
|
|
|
// Wait to run over the update-functionality
|
|
yield return new WaitForSeconds(0.2f);
|
|
|
|
// Fetch a letter that isn't in the word
|
|
foreach (char let in new List<char>() { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' })
|
|
{
|
|
if (!currentWord.Contains(let.ToString().ToUpper()))
|
|
{
|
|
letter = let.ToString().ToUpper();
|
|
break;
|
|
}
|
|
}
|
|
// Input this knowingly-wrong letter
|
|
yield return ChooseLetter(letter);
|
|
localWrongs++;
|
|
// We know the letter is wrong, so check that the wrongs have increased
|
|
Assert.IsTrue(hangmanController.getWrongs() == localWrongs);
|
|
|
|
// Check all the correct letters
|
|
Dictionary<string, int> correctLetters = new Dictionary<string, int>();
|
|
foreach (char let in currentWord.ToUpper())
|
|
{
|
|
letter = let.ToString();
|
|
if (correctLetters.ContainsKey(letter))
|
|
{
|
|
correctLetters[letter] += 1;
|
|
}
|
|
else
|
|
{
|
|
correctLetters.Add(letter, 1);
|
|
}
|
|
}
|
|
int localCorrects = 0;
|
|
// Now add each of the letters and check if the correct are correctly updated
|
|
foreach (string s in correctLetters.Keys)
|
|
{
|
|
yield return ChooseLetter(s);
|
|
|
|
localCorrects += correctLetters[s];
|
|
Assert.IsTrue(hangmanController.getCorrects() == localCorrects);
|
|
}
|
|
|
|
// The game should be over now, check if the gameEndedPanel is active
|
|
Assert.IsTrue(hangmanController.gameEndedPanel.activeSelf);
|
|
|
|
// Fetch the gameEndedPanel to check it's values
|
|
var gameEndedScript = GameObject.FindObjectOfType<HangmanGameEndedPanel>();
|
|
Assert.IsTrue(gameEndedScript.endText.text == "GEWONNEN");
|
|
Assert.IsTrue(gameEndedScript.lettersRightText.text == hangmanController.getCorrects().ToString());
|
|
Assert.IsTrue(gameEndedScript.lettersWrongText.text == hangmanController.getWrongs().ToString());
|
|
Assert.IsTrue(gameEndedScript.lettersTotalText.text == (hangmanController.getCorrects() + hangmanController.getWrongs()).ToString());
|
|
|
|
yield return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests the multiplayer-code
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[UnityTest]
|
|
public IEnumerator MultiPlayerTests()
|
|
{
|
|
// Go to the input-screen
|
|
hangmanController.GoToInput();
|
|
|
|
// We will enter the word "testing" but will type a wrong letter after the 'i' that will be backspaced away
|
|
// Afterwards, we can go to the game and assert that the currectWord is indeed "testing"
|
|
|
|
// Correct letters
|
|
yield return InputLetter("T");
|
|
yield return InputLetter("E");
|
|
yield return InputLetter("S");
|
|
yield return InputLetter("T");
|
|
yield return InputLetter("I");
|
|
|
|
// Wrong letter, will be backspaced away
|
|
yield return InputLetter("V");
|
|
|
|
yield return new WaitForSeconds(0.2f);
|
|
// We can't simulate a key-press so we will need to settle for just calling its logic
|
|
hangmanController.BackSpacePressed();
|
|
|
|
// Wrong letter, but this one will be rejected
|
|
while (hangmanController.getCurrentMode() != multiplayerConfirmInput)
|
|
{
|
|
hangmanController.ProcessMostProbableSign(0.0001f, "Q");
|
|
yield return new WaitForSeconds(0.2f);
|
|
}
|
|
|
|
hangmanController.ConfirmDeny();
|
|
|
|
// Final correct letters
|
|
yield return InputLetter("N");
|
|
yield return InputLetter("G");
|
|
|
|
// We are satisfied with the word, pass it along
|
|
hangmanController.TwoPlayer();
|
|
|
|
Assert.IsTrue(hangmanController.getCurrentWord() == "TESTING");
|
|
|
|
// Input 9 wrong letters to lose the game
|
|
int localWrongs = 0;
|
|
Assert.IsTrue(hangmanController.getWrongs() == localWrongs);
|
|
foreach (string s in new List<string>() { "A", "B", "C", "D", "F", "H", "J", "K", "L", "M", "N", "O", "P" })
|
|
{
|
|
if (HangmanController.NUMBER_OF_FAILS_BEFORE_GAMEOVER >= localWrongs)
|
|
{
|
|
yield return ChooseLetter(s);
|
|
localWrongs++;
|
|
Assert.IsTrue(hangmanController.getWrongs() == localWrongs);
|
|
}
|
|
}
|
|
|
|
// The game should be over now, resulting in a loss
|
|
Assert.IsTrue(hangmanController.gameEndedPanel.activeSelf);
|
|
|
|
// Fetch the gameEndedPanel to check it's values
|
|
var gameEndedScript = GameObject.FindObjectOfType<HangmanGameEndedPanel>();
|
|
Assert.IsTrue(gameEndedScript.endText.text == "VERLOREN");
|
|
Assert.IsTrue(gameEndedScript.lettersRightText.text == hangmanController.getCorrects().ToString());
|
|
Assert.IsTrue(gameEndedScript.lettersWrongText.text == hangmanController.getWrongs().ToString());
|
|
Assert.IsTrue(gameEndedScript.lettersTotalText.text == (hangmanController.getCorrects() + hangmanController.getWrongs()).ToString());
|
|
|
|
yield return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests some remaning functionality regarding the feedback that isn't contained in the previous tests
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[UnityTest]
|
|
public IEnumerator SignChangingTest()
|
|
{
|
|
hangmanController.SinglePlayer();
|
|
|
|
hangmanController.ProcessMostProbableSign(0.001f, "A");
|
|
yield return new WaitForSeconds(0.2f);
|
|
// The sign for A has been held for 0.2f seconds...
|
|
Assert.IsTrue(hangmanController.getCurrentTime() >= 0.2f && hangmanController.getCurrentTime() <= 0.3f);
|
|
|
|
hangmanController.ProcessMostProbableSign(0.001f, "B");
|
|
yield return new WaitForSeconds(0.2f);
|
|
// The sign changed so the time needs to be at 0.2f again
|
|
Assert.IsTrue(hangmanController.getCurrentTime() >= 0.2f && hangmanController.getCurrentTime() <= 0.3f);
|
|
|
|
hangmanController.ProcessMostProbableSign(1000, "B");
|
|
yield return new WaitForSeconds(0.2f);
|
|
// The sign changed is way above the threshold, time is no longer tracked and is reset
|
|
Assert.IsTrue(hangmanController.getCurrentTime() == 0.0);
|
|
|
|
// Check that the time stays zero so long as the distance stays above the threshold
|
|
Learnable C = hangmanController.fingerSpelling.learnables.Find((l) => l.name == "C");
|
|
float threshold = C.thresholdDistance;
|
|
for (float i = 2 * threshold; i > threshold; i -= threshold / 6)
|
|
{
|
|
hangmanController.ProcessMostProbableSign(i, "C");
|
|
yield return new WaitForSeconds(0.01f);
|
|
Assert.IsTrue(hangmanController.getCurrentTime() == 0.0);
|
|
}
|
|
|
|
// Check that the time rises above zero when you dip just below the threshold
|
|
hangmanController.ProcessMostProbableSign(threshold - 0.01f, "C");
|
|
yield return new WaitForSeconds(0.01f);
|
|
Assert.IsTrue(hangmanController.getCurrentTime() > 0.0);
|
|
|
|
yield return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Test the functionality of the scoreboard to display multiple games
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[UnityTest]
|
|
public IEnumerator ScoreBoardTest()
|
|
{
|
|
// Quickly play 2 games to test if scoreboard is correctly reset and if entries are correctly added
|
|
// Game 1
|
|
hangmanController.GoToInput();
|
|
yield return InputLetter("A");
|
|
yield return InputLetter("A");
|
|
yield return InputLetter("A");
|
|
hangmanController.TwoPlayer();
|
|
Assert.IsTrue(hangmanController.getCurrentWord() == "AAA");
|
|
yield return ChooseLetter("A");
|
|
yield return new WaitForSeconds(1f);
|
|
|
|
Assert.IsTrue(hangmanController.gameEndedPanel.activeSelf);
|
|
var gameEndedScript = GameObject.FindObjectOfType<HangmanGameEndedPanel>();
|
|
int firstEntries = gameEndedScript.scoreboardEntriesContainer.childCount;
|
|
|
|
hangmanController.StartController();
|
|
|
|
// Game 2
|
|
hangmanController.GoToInput();
|
|
yield return InputLetter("A");
|
|
yield return InputLetter("A");
|
|
yield return InputLetter("A");
|
|
hangmanController.TwoPlayer();
|
|
Assert.IsTrue(hangmanController.getCurrentWord() == "AAA");
|
|
yield return ChooseLetter("A");
|
|
yield return new WaitForSeconds(1f);
|
|
Assert.IsTrue(hangmanController.gameEndedPanel.activeSelf);
|
|
|
|
int secondEntries = gameEndedScript.scoreboardEntriesContainer.childCount;
|
|
|
|
// Check that one entry has been added between the two games or that the scoreboard was already full
|
|
Assert.IsTrue(secondEntries == firstEntries + 1 || firstEntries == 10);
|
|
|
|
yield return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cleanup after testing
|
|
/// </summary>
|
|
[TearDown]
|
|
public void TearDown_HangmanTests()
|
|
{
|
|
PersistentDataController.PATH = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Private function to input a letter in multiplayer input-mode
|
|
/// </summary>
|
|
/// <param name="letter"></param>
|
|
/// <returns></returns>
|
|
private IEnumerator InputLetter(string letter)
|
|
{
|
|
while (hangmanController.getCurrentMode() != multiplayerConfirmInput)
|
|
{
|
|
// Choose the letter by giving it a very small distance
|
|
hangmanController.ProcessMostProbableSign(0.001f, letter);
|
|
yield return new WaitForSeconds(0.2f);
|
|
}
|
|
|
|
hangmanController.ConfirmAccept();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Private function to input a letter in game-mode
|
|
/// </summary>
|
|
/// <param name="letter"></param>
|
|
/// <returns></returns>
|
|
private IEnumerator ChooseLetter(string letter)
|
|
{
|
|
while (!hangmanController.getUsedLetters().Contains(letter))
|
|
{
|
|
// Choose the letter by giving it a very small distance
|
|
hangmanController.ProcessMostProbableSign(0.001f, letter);
|
|
yield return new WaitForSeconds(0.2f);
|
|
}
|
|
}
|
|
} |