Resolve WES-187 "Unit tests account and system"

This commit is contained in:
Dries Van Schuylenbergh
2023-04-30 15:51:41 +00:00
committed by Jerome Coudron
parent c4b6c60288
commit b9bbef8dcf
143 changed files with 2008 additions and 542 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 17374f544297b194aa5517c196ca2f07
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,14 @@
{
"name": "ArchitectureScripts",
"rootNamespace": "",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e83ddf9a537a96b4a804a16bb7872ec1
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
/// <summary>
/// Enum for easy indexing and checking if a course is of a certain kind
/// </summary>
public enum CourseIndex
{
FINGERSPELLING,
BASIC_SIGNS,
CLOTHING,
ANIMALS,
FOOD,
HOBBIES,
HOUSE,
FAMILY
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a5bf21dee022ed0489face1c734359de
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
/// <summary>
/// Enum for easy indexing and checking if a minigame is of a certain kind
/// </summary>
public enum MinigameIndex
{
SPELLING_BEE,
HANGMAN,
JUST_SIGN
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 97282ff3b465e3c4682d218b3819b2e8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,542 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;
/// <summary>
/// PersistentDataController singleton
/// </summary>
public class PersistentDataController
{
/// <summary>
/// The instance controlling the singleton
/// </summary>
private static PersistentDataController instance = null;
/// <summary>
/// Current implementation version of the PersistentDataController
/// </summary>
/// <remarks>MSB represent sprint version, LSB represent subversion</remarks>
public const int VERSION = 0x04_03;
/// <summary>
/// Path of the <c>.json</c>-file to store all serialized data
/// </summary>
public static string PATH = null;
/// <summary>
/// Class to hold a list of data records
/// </summary>
[Serializable]
public class PersistentDataContainer
{
/// <summary>
/// A helper class for handling the stored progress
/// </summary>
[Serializable]
public class PersistentDataEntry
{
/// <summary>
/// The key, used to reference the data object
/// </summary>
public string key;
/// <summary>
/// The object, representated as a list of byte (which can be serialized)
/// </summary>
public List<byte> data = new List<byte>();
public PersistentDataEntry(string key, byte[] data) : this(key, data.ToList())
{ }
public PersistentDataEntry(string key, List<byte> data)
{
this.key = key;
this.data = data;
}
}
/// <summary>
/// List of data records
/// </summary>
public List<PersistentDataEntry> entries = new List<PersistentDataEntry>();
/// <summary>
/// Update the value of a certain key,
/// or add a new value if the key was not present.
/// </summary>
/// <typeparam name="T">The type of the data to be added/updated</typeparam>
/// <param name="key">The key, used for referencing the data</param>
/// <param name="data">The object of type <typeparamref name="T"/></param>
/// <returns><c>true</c> if successful, <c>false</c> otherwise</returns>
public bool Set<T>(string key, T data)
{
if (data == null)
return false;
PersistentDataEntry entry = entries.Find(x => x.key == key);
// Hacky serialization stuff
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, data);
if (entry != null)
{
entry.data.Clear();
entry.data.AddRange(ms.ToArray());
}
else
{
entries.Add(new PersistentDataEntry(key, ms.ToArray()));
}
return true;
}
}
/// <summary>
/// Get the data object of a certain key
/// </summary>
/// <typeparam name="T">The type of the data object</typeparam>
/// <param name="key">The key referencing the data object</param>
/// <returns>The data, cast to a type <typeparamref name="T"/></returns>
/// <exception cref="KeyNotFoundException"></exception>
/// <exception cref="InvalidCastException"></exception>
public T Get<T>(string key)
{
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
// Find the correct key
foreach (PersistentDataEntry entry in entries)
{
if (entry.key == key)
{
// Hacky serialization stuff
byte[] data = entry.data.ToArray();
ms.Write(data, 0, data.Length);
ms.Seek(0, SeekOrigin.Begin);
return (T)bf.Deserialize(ms);
}
}
}
// Raise an exception when key is not found
throw new KeyNotFoundException();
}
/// <summary>
/// Remove a key-value from the data.
/// </summary>
/// <param name="key">The key referencing the data object</param>
/// <exception cref="KeyNotFoundException"></exception>
public void Remove(string key)
{
if (!Has(key))
throw new KeyNotFoundException();
entries.Remove(entries.Find(x => x.key == key));
}
/// <summary>
/// Remove and return value from the data.
/// </summary>
/// <typeparam name="T">The type of the data object</typeparam>
/// <param name="key">The key referencing the data object</param>
/// <param name="save">Whether the removal of the data should also be saved to disk</param>
/// <returns></returns>
public T Pop<T>(string key)
{
T data = Get<T>(key);
Remove(key);
return data;
}
/// <summary>
/// Check whether a key is present
/// </summary>
/// <param name="key">The key to check</param>
/// <returns>true if a item can be found with the specified key</returns>
public bool Has(string key)
{
return entries.Find(x => x.key == key) != null;
}
}
/// <summary>
/// Stored user data record
/// </summary>
[Serializable]
public class SavedUserData : PersistentDataContainer
{
public string username = null;
public int avatarIndex = -1;
public double playtime = 0.0;
public List<SavedMinigameProgress> minigames = new List<SavedMinigameProgress>();
public List<SavedCourseProgress> courses = new List<SavedCourseProgress>();
}
/// <summary>
/// Stored course progress data record
/// </summary>
[Serializable]
public class SavedCourseProgress : PersistentDataContainer
{
/// <summary>
/// Update the progress value of the SavedLearnableProgress with the given learnableName.
/// </summary>
/// <param name="learnableName"></param>
/// <param name="addValue"></param>
public void UpdateLearnable(string learnableName, float addValue)
{
SavedLearnableProgress learnable = learnables.Find(l => l.name == learnableName);
if (learnable == null)
throw new KeyNotFoundException();
// Update the progress value of the SavedLearnableProgress
learnable.progress += addValue;
// crop the learnable progress around -5 and 5
if (learnable.progress > 5.0f)
learnable.progress = 5.0f;
else if (learnable.progress < -5.0f)
learnable.progress = -5.0f;
// if learnable progress is big enough it is "completed"
if (learnable.progress > 3)
completedLearnables++;
}
/// <summary>
///
/// </summary>
/// <returns> bool which indicates if there are enough inUseLearnables </returns>
private bool EnoughLearnables()
{
// There need to be more then 5 non completed learnables
return inUseLearnables - completedLearnables > 5 || totalLearnables == inUseLearnables;
}
/// <summary>
/// Find a SavedLearnableProgress with the given name
/// </summary>
/// <param name="name"></param>
/// <returns> SavedLearnableProgress with the given name </returns>
public SavedLearnableProgress FindLearnable(string name)
{
return learnables.Find(l => l.name == name);
}
/// <summary>
/// Find learnable in learnables which is not yet in use, and set it active
/// </summary>
/// <returns> SavedLearnableProgress learnable </returns>
private SavedLearnableProgress UseUnusedLearnable()
{
SavedLearnableProgress learnable = learnables.Find(l => !l.inUse);
if (learnable == null)
return null;
learnable.inUse = true;
inUseLearnables++;
return learnable;
}
/// <summary>
/// Gets a random inUse learnable
/// </summary>
/// <returns> a randomly selected inUse SavedLearnable which is not yet completed</returns>
public SavedLearnableProgress GetRandomLearnable()
{
if (!EnoughLearnables())
return UseUnusedLearnable();
// only select inUse learnables which are not yet completed (progress < 3.5f)
List<SavedLearnableProgress> inUseLearnables = learnables.FindAll(l => l.inUse && l.progress <= 3.5f);
if (inUseLearnables.Count == 0)
return null;
// Select a random index from the in-use learnables list
int randomIndex = UnityEngine.Random.Range(0, inUseLearnables.Count);
return inUseLearnables[randomIndex];
}
/// <summary>
/// Create new SavedLearnableProgress object and assigns the index and name values
/// </summary>
/// <param name="name"></param>
/// <param name="index"></param>
/// <returns> bool which indicates the success of the function</returns>
public bool AddLearnable(string name, int index)
{
if (learnables.Any(learnable => learnable.name == name || learnable.index == index))
return false;
SavedLearnableProgress savedLearnableProgress = new SavedLearnableProgress();
savedLearnableProgress.index = index;
savedLearnableProgress.name = name;
learnables.Add(savedLearnableProgress);
totalLearnables++;
return true;
}
public CourseIndex courseIndex;
public float progress = -1.0f;
public int completedLearnables = 0;
public int inUseLearnables = 0;
public int totalLearnables = 0;
public List<SavedLearnableProgress> learnables = new List<SavedLearnableProgress>();
}
/// <summary>
/// Stored individual learnable progress
/// </summary>
[Serializable]
public class SavedLearnableProgress : PersistentDataContainer
{
public int index;
public bool inUse = false;
public string name;
public float progress = 0.0f;
}
/// <summary>
/// Stored minigame progress data record
/// </summary>
[Serializable]
public class SavedMinigameProgress : PersistentDataContainer
{
public MinigameIndex minigameIndex;
public List<Score> latestScores = new List<Score>();
public List<Score> highestScores = new List<Score>();
}
/// <summary>
/// Stored WeSign data record
/// </summary>
[Serializable]
private class SavedDataStructure
{
public int version = VERSION;
public List<SavedUserData> users = new List<SavedUserData>();
public int currentUser = -1;
public MinigameIndex currentMinigame;
public CourseIndex currentCourse;
public ThemeIndex currentTheme;
}
/// <summary>
/// The object holding the data references
/// </summary>
private SavedDataStructure json = new SavedDataStructure();
/// <summary>
/// Get the instance loaded by the singleton
/// </summary>
/// <returns><c>PersistentDataController</c> instance</returns>
public static PersistentDataController GetInstance()
{
// Create a new instance if non exists
if (instance == null || PATH == null)
{
if (PATH == null)
PersistentDataController.PATH = $"{Application.persistentDataPath}/wesign_saved_data.json";
instance = new PersistentDataController();
}
return instance;
}
/// <summary>
/// PersistentDataController contructor
/// </summary>
private PersistentDataController()
{
Load();
}
/// <summary>
/// Clear everything stored in the PersistentDataController, won't save to disk
/// </summary>
public void Clear()
{
json.users.Clear();
json.currentUser = -1;
}
/// <summary>
/// Save all data to disk
/// </summary>
public void Save()
{
string text = JsonUtility.ToJson(json);
File.CreateText(PATH).Close();
File.WriteAllText(PATH, text);
}
/// <summary>
/// Override current data with the data from disk, will just clear if no data was found.
/// </summary>
/// <param name="overrideOnFail"><c>true</c> if you want to override the existing file if it exists and the loading failed.</param>
/// <remarks>If the data on disk is outdated (version number is lower than the current version), the loading will also fail</remarks>
/// <returns><c>true</c> if successful, <c>false</c> otherwise</returns>
public bool Load(bool overrideOnFail = true)
{
Clear();
if (!File.Exists(PATH))
goto failed;
try
{
string text = File.ReadAllText(PATH);
SavedDataStructure newJson = JsonUtility.FromJson<SavedDataStructure>(text);
if (newJson == null || newJson.version != VERSION)
goto failed;
json = newJson;
return true;
}
catch (Exception) { goto failed; }
failed:
if (overrideOnFail)
Save();
return false;
}
/// <summary>
/// Add a user to the WeSign data record
/// </summary>
/// <param name="user">User data record</param>
/// <param name="save">Whether to save the addition immediately to disk</param>
public void AddUser(SavedUserData user, bool save = true)
{
if (json.users.Count == 0)
json.currentUser = 0;
json.users.Add(user);
if (save)
Save();
}
/// <summary>
/// Get a list of all user data records
/// </summary>
/// <returns></returns>
public List<SavedUserData> GetUsers()
{
return json.users;
}
/// <summary>
/// Get the index of the current user
/// </summary>
/// <returns></returns>
public int GetCurrentUser()
{
return json.currentUser;
}
/// <summary>
/// Set the index of the current record
/// </summary>
/// <param name="index">New index</param>
/// <param name="save">Whether to save the change immediately to disk</param>
/// <exception cref="IndexOutOfRangeException"></exception>
public void SetCurrentUser(int index, bool save = true)
{
if (index < 0 || json.users.Count <= index)
throw new IndexOutOfRangeException();
json.currentUser = index;
if (save)
Save();
}
/// <summary>
/// Remove a user data record
/// </summary>
/// <param name="index">Index of the user</param>
/// <param name="save">Whether to save the deletion immediately to disk</param>
/// <exception cref="IndexOutOfRangeException"></exception>
public void DeleteUser(int index, bool save = true)
{
if (index < 0 || json.users.Count <= index)
throw new IndexOutOfRangeException();
if (0 < json.currentUser && index <= json.currentUser)
json.currentUser--;
json.users.RemoveAt(index);
if (save)
Save();
}
/// <summary>
/// Get the current course
/// </summary>
/// <returns></returns>
public CourseIndex GetCurrentCourse()
{
return json.currentCourse;
}
/// <summary>
/// Set the current course
/// </summary>
/// <param name="course">New course index</param>
/// <param name="save">Whether to save the change immediately to disk</param>
public void SetCurrentCourse(CourseIndex course, bool save = true)
{
json.currentCourse = course;
if (save)
Save();
}
/// <summary>
/// Get the current minigame
/// </summary>
/// <returns></returns>
public MinigameIndex GetCurrentMinigame()
{
return json.currentMinigame;
}
/// <summary>
/// Set the current minigame
/// </summary>
/// <param name="minigame">New minigame index</param>
/// <param name="save">Whether to save the change immediately to disk</param>
public void SetCurrentMinigame(MinigameIndex minigame, bool save = true)
{
json.currentMinigame = minigame;
if (save)
Save();
}
/// <summary>
/// Get the current theme
/// </summary>
/// <returns></returns>
public ThemeIndex GetCurrentTheme()
{
return json.currentTheme;
}
/// <summary>
/// Set the current theme
/// </summary>
/// <param name="theme">New theme index</param>
/// <param name="save">Whether to save the change immediately to disk</param>
public void SetCurrentTheme(ThemeIndex theme, bool save = true)
{
json.currentTheme = theme;
if (save)
Save();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 164b1accbeff688429a4311f1e40bd59
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using System;
/// <summary>
/// Score class
/// </summary>
[Serializable]
public class Score
{
public int scoreValue;
public string time;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 16056ca3e1523f78cbd727cea2bfe047
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,647 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWER
using UnityEngine.U2D;
#endif
using Sprites = UnityEngine.Sprites;
#if UNITY_EDITOR
using UnityEditor;
// Custom Editor to order the variables in the Inspector similar to Image component
[CustomEditor(typeof(SlicedSlider)), CanEditMultipleObjects]
public class SlicedSliderEditor : Editor
{
private SerializedProperty spriteProp, colorProp;
private GUIContent spriteLabel;
private void OnEnable()
{
spriteProp = serializedObject.FindProperty("m_Sprite");
colorProp = serializedObject.FindProperty("m_Color");
spriteLabel = new GUIContent("Source Image");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(spriteProp, spriteLabel);
EditorGUILayout.PropertyField(colorProp);
DrawPropertiesExcluding(serializedObject, "m_Script", "m_Sprite", "m_Color", "m_OnCullStateChanged");
serializedObject.ApplyModifiedProperties();
}
}
#endif
// Credit: https://bitbucket.org/Unity-Technologies/ui/src/2018.4/UnityEngine.UI/UI/Core/Image.cs
[RequireComponent(typeof(CanvasRenderer))]
[AddComponentMenu("UI/Sliced Slider", 11)]
public class SlicedSlider : MaskableGraphic, ISerializationCallbackReceiver, ILayoutElement, ICanvasRaycastFilter
{
private static class SetPropertyUtility
{
public static bool SetStruct<T>(ref T currentValue, T newValue) where T : struct
{
if (EqualityComparer<T>.Default.Equals(currentValue, newValue))
return false;
currentValue = newValue;
return true;
}
public static bool SetClass<T>(ref T currentValue, T newValue) where T : class
{
if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue)))
return false;
currentValue = newValue;
return true;
}
}
public enum FillDirection { Right = 0, Left = 1, Up = 2, Down = 3 }
private static readonly Vector3[] s_Vertices = new Vector3[4];
private static readonly Vector2[] s_UVs = new Vector2[4];
private static readonly Vector2[] s_SlicedVertices = new Vector2[4];
private static readonly Vector2[] s_SlicedUVs = new Vector2[4];
#pragma warning disable 1692
#pragma warning disable IDE1006 // Suppress 'Naming rule violation' warnings
#pragma warning disable 0649
[SerializeField]
private Sprite m_Sprite;
public Sprite sprite
{
get { return m_Sprite; }
set
{
if (SetPropertyUtility.SetClass(ref m_Sprite, value))
{
SetAllDirty();
TrackImage();
}
}
}
[SerializeField]
private FillDirection m_FillDirection;
public FillDirection fillDirection
{
get { return m_FillDirection; }
set
{
if (SetPropertyUtility.SetStruct(ref m_FillDirection, value))
SetVerticesDirty();
}
}
[Range(0, 1)]
[SerializeField]
private float m_FillAmount = 1f;
public float fillAmount
{
get { return m_FillAmount; }
set
{
if (SetPropertyUtility.SetStruct(ref m_FillAmount, Mathf.Clamp01(value)))
SetVerticesDirty();
}
}
[SerializeField]
private bool m_FillCenter = true;
public bool fillCenter
{
get { return m_FillCenter; }
set
{
if (SetPropertyUtility.SetStruct(ref m_FillCenter, value))
SetVerticesDirty();
}
}
[SerializeField]
private float m_PixelsPerUnitMultiplier = 1f;
public float pixelsPerUnitMultiplier
{
get { return m_PixelsPerUnitMultiplier; }
set { m_PixelsPerUnitMultiplier = Mathf.Max(0.01f, value); }
}
public float pixelsPerUnit
{
get
{
float spritePixelsPerUnit = 100;
if (activeSprite)
spritePixelsPerUnit = activeSprite.pixelsPerUnit;
float referencePixelsPerUnit = 100;
if (canvas)
referencePixelsPerUnit = canvas.referencePixelsPerUnit;
return m_PixelsPerUnitMultiplier * spritePixelsPerUnit / referencePixelsPerUnit;
}
}
#pragma warning restore 0649
[NonSerialized]
private Sprite m_OverrideSprite;
public Sprite overrideSprite
{
get { return activeSprite; }
set
{
if (SetPropertyUtility.SetClass(ref m_OverrideSprite, value))
{
SetAllDirty();
TrackImage();
}
}
}
private Sprite activeSprite { get { return m_OverrideSprite != null ? m_OverrideSprite : m_Sprite; } }
public override Texture mainTexture
{
get
{
if (activeSprite != null)
return activeSprite.texture;
return material != null && material.mainTexture != null ? material.mainTexture : s_WhiteTexture;
}
}
public bool hasBorder
{
get
{
if (activeSprite != null)
{
Vector4 v = activeSprite.border;
return v.sqrMagnitude > 0f;
}
return false;
}
}
public override Material material
{
get
{
if (m_Material != null)
return m_Material;
if (activeSprite && activeSprite.associatedAlphaSplitTexture != null)
{
#if UNITY_EDITOR
if (Application.isPlaying)
#endif
return Image.defaultETC1GraphicMaterial;
}
return defaultMaterial;
}
set { base.material = value; }
}
public float alphaHitTestMinimumThreshold { get; set; }
#pragma warning restore IDE1006
#pragma warning restore 1692
protected SlicedSlider()
{
useLegacyMeshGeneration = false;
}
protected override void OnEnable()
{
base.OnEnable();
TrackImage();
}
protected override void OnDisable()
{
base.OnDisable();
if (m_Tracked)
UnTrackImage();
}
#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();
m_PixelsPerUnitMultiplier = Mathf.Max(0.01f, m_PixelsPerUnitMultiplier);
}
#endif
protected override void OnPopulateMesh(VertexHelper vh)
{
if (activeSprite == null)
{
base.OnPopulateMesh(vh);
return;
}
GenerateSlicedFilledSprite(vh);
}
/// <summary>
/// Update the renderer's material.
/// </summary>
protected override void UpdateMaterial()
{
base.UpdateMaterial();
// Check if this sprite has an associated alpha texture (generated when splitting RGBA = RGB + A as two textures without alpha)
if (activeSprite == null)
{
canvasRenderer.SetAlphaTexture(null);
return;
}
Texture2D alphaTex = activeSprite.associatedAlphaSplitTexture;
if (alphaTex != null)
canvasRenderer.SetAlphaTexture(alphaTex);
}
private void GenerateSlicedFilledSprite(VertexHelper vh)
{
vh.Clear();
if (m_FillAmount < 0.001f)
return;
Rect rect = GetPixelAdjustedRect();
Vector4 outer = Sprites.DataUtility.GetOuterUV(activeSprite);
Vector4 padding = Sprites.DataUtility.GetPadding(activeSprite);
if (!hasBorder)
{
Vector2 size = activeSprite.rect.size;
int spriteW = Mathf.RoundToInt(size.x);
int spriteH = Mathf.RoundToInt(size.y);
// Image's dimensions used for drawing. X = left, Y = bottom, Z = right, W = top.
Vector4 vertices = new Vector4(
rect.x + rect.width * (padding.x / spriteW),
rect.y + rect.height * (padding.y / spriteH),
rect.x + rect.width * ((spriteW - padding.z) / spriteW),
rect.y + rect.height * ((spriteH - padding.w) / spriteH));
GenerateFilledSprite(vh, vertices, outer, m_FillAmount);
return;
}
Vector4 inner = Sprites.DataUtility.GetInnerUV(activeSprite);
Vector4 border = GetAdjustedBorders(activeSprite.border / pixelsPerUnit, rect);
padding = padding / pixelsPerUnit;
s_SlicedVertices[0] = new Vector2(padding.x, padding.y);
s_SlicedVertices[3] = new Vector2(rect.width - padding.z, rect.height - padding.w);
s_SlicedVertices[1].x = border.x;
s_SlicedVertices[1].y = border.y;
s_SlicedVertices[2].x = rect.width - border.z;
s_SlicedVertices[2].y = rect.height - border.w;
for (int i = 0; i < 4; ++i)
{
s_SlicedVertices[i].x += rect.x;
s_SlicedVertices[i].y += rect.y;
}
s_SlicedUVs[0] = new Vector2(outer.x, outer.y);
s_SlicedUVs[1] = new Vector2(inner.x, inner.y);
s_SlicedUVs[2] = new Vector2(inner.z, inner.w);
s_SlicedUVs[3] = new Vector2(outer.z, outer.w);
float rectStartPos;
float _1OverTotalSize;
if (m_FillDirection == FillDirection.Left || m_FillDirection == FillDirection.Right)
{
rectStartPos = s_SlicedVertices[0].x;
float totalSize = (s_SlicedVertices[3].x - s_SlicedVertices[0].x);
_1OverTotalSize = totalSize > 0f ? 1f / totalSize : 1f;
}
else
{
rectStartPos = s_SlicedVertices[0].y;
float totalSize = (s_SlicedVertices[3].y - s_SlicedVertices[0].y);
_1OverTotalSize = totalSize > 0f ? 1f / totalSize : 1f;
}
for (int x = 0; x < 3; x++)
{
int x2 = x + 1;
for (int y = 0; y < 3; y++)
{
if (!m_FillCenter && x == 1 && y == 1)
continue;
int y2 = y + 1;
float sliceStart, sliceEnd;
switch (m_FillDirection)
{
case FillDirection.Right:
sliceStart = (s_SlicedVertices[x].x - rectStartPos) * _1OverTotalSize;
sliceEnd = (s_SlicedVertices[x2].x - rectStartPos) * _1OverTotalSize;
break;
case FillDirection.Up:
sliceStart = (s_SlicedVertices[y].y - rectStartPos) * _1OverTotalSize;
sliceEnd = (s_SlicedVertices[y2].y - rectStartPos) * _1OverTotalSize;
break;
case FillDirection.Left:
sliceStart = 1f - (s_SlicedVertices[x2].x - rectStartPos) * _1OverTotalSize;
sliceEnd = 1f - (s_SlicedVertices[x].x - rectStartPos) * _1OverTotalSize;
break;
case FillDirection.Down:
sliceStart = 1f - (s_SlicedVertices[y2].y - rectStartPos) * _1OverTotalSize;
sliceEnd = 1f - (s_SlicedVertices[y].y - rectStartPos) * _1OverTotalSize;
break;
default: // Just there to get rid of the "Use of unassigned local variable" compiler error
sliceStart = sliceEnd = 0f;
break;
}
if (sliceStart >= m_FillAmount)
continue;
Vector4 vertices = new Vector4(s_SlicedVertices[x].x, s_SlicedVertices[y].y, s_SlicedVertices[x2].x, s_SlicedVertices[y2].y);
Vector4 uvs = new Vector4(s_SlicedUVs[x].x, s_SlicedUVs[y].y, s_SlicedUVs[x2].x, s_SlicedUVs[y2].y);
float fillAmount = (m_FillAmount - sliceStart) / (sliceEnd - sliceStart);
GenerateFilledSprite(vh, vertices, uvs, fillAmount);
}
}
}
private Vector4 GetAdjustedBorders(Vector4 border, Rect adjustedRect)
{
Rect originalRect = rectTransform.rect;
for (int axis = 0; axis <= 1; axis++)
{
float borderScaleRatio;
// The adjusted rect (adjusted for pixel correctness) may be slightly larger than the original rect.
// Adjust the border to match the adjustedRect to avoid small gaps between borders (case 833201).
if (originalRect.size[axis] != 0)
{
borderScaleRatio = adjustedRect.size[axis] / originalRect.size[axis];
border[axis] *= borderScaleRatio;
border[axis + 2] *= borderScaleRatio;
}
// If the rect is smaller than the combined borders, then there's not room for the borders at their normal size.
// In order to avoid artefacts with overlapping borders, we scale the borders down to fit.
float combinedBorders = border[axis] + border[axis + 2];
if (adjustedRect.size[axis] < combinedBorders && combinedBorders != 0)
{
borderScaleRatio = adjustedRect.size[axis] / combinedBorders;
border[axis] *= borderScaleRatio;
border[axis + 2] *= borderScaleRatio;
}
}
return border;
}
private void GenerateFilledSprite(VertexHelper vh, Vector4 vertices, Vector4 uvs, float fillAmount)
{
if (m_FillAmount < 0.001f)
return;
float uvLeft = uvs.x;
float uvBottom = uvs.y;
float uvRight = uvs.z;
float uvTop = uvs.w;
if (fillAmount < 1f)
{
if (m_FillDirection == FillDirection.Left || m_FillDirection == FillDirection.Right)
{
if (m_FillDirection == FillDirection.Left)
{
vertices.x = vertices.z - (vertices.z - vertices.x) * fillAmount;
uvLeft = uvRight - (uvRight - uvLeft) * fillAmount;
}
else
{
vertices.z = vertices.x + (vertices.z - vertices.x) * fillAmount;
uvRight = uvLeft + (uvRight - uvLeft) * fillAmount;
}
}
else
{
if (m_FillDirection == FillDirection.Down)
{
vertices.y = vertices.w - (vertices.w - vertices.y) * fillAmount;
uvBottom = uvTop - (uvTop - uvBottom) * fillAmount;
}
else
{
vertices.w = vertices.y + (vertices.w - vertices.y) * fillAmount;
uvTop = uvBottom + (uvTop - uvBottom) * fillAmount;
}
}
}
s_Vertices[0] = new Vector3(vertices.x, vertices.y);
s_Vertices[1] = new Vector3(vertices.x, vertices.w);
s_Vertices[2] = new Vector3(vertices.z, vertices.w);
s_Vertices[3] = new Vector3(vertices.z, vertices.y);
s_UVs[0] = new Vector2(uvLeft, uvBottom);
s_UVs[1] = new Vector2(uvLeft, uvTop);
s_UVs[2] = new Vector2(uvRight, uvTop);
s_UVs[3] = new Vector2(uvRight, uvBottom);
int startIndex = vh.currentVertCount;
for (int i = 0; i < 4; i++)
vh.AddVert(s_Vertices[i], color, s_UVs[i]);
vh.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
vh.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
}
int ILayoutElement.layoutPriority { get { return 0; } }
float ILayoutElement.minWidth { get { return 0; } }
float ILayoutElement.minHeight { get { return 0; } }
float ILayoutElement.flexibleWidth { get { return -1; } }
float ILayoutElement.flexibleHeight { get { return -1; } }
float ILayoutElement.preferredWidth
{
get
{
if (activeSprite == null)
return 0;
return Sprites.DataUtility.GetMinSize(activeSprite).x / pixelsPerUnit;
}
}
float ILayoutElement.preferredHeight
{
get
{
if (activeSprite == null)
return 0;
return Sprites.DataUtility.GetMinSize(activeSprite).y / pixelsPerUnit;
}
}
void ILayoutElement.CalculateLayoutInputHorizontal() { }
void ILayoutElement.CalculateLayoutInputVertical() { }
bool ICanvasRaycastFilter.IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
{
if (alphaHitTestMinimumThreshold <= 0)
return true;
if (alphaHitTestMinimumThreshold > 1)
return false;
if (activeSprite == null)
return true;
Vector2 local;
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out local))
return false;
Rect rect = GetPixelAdjustedRect();
// Convert to have lower left corner as reference point.
local.x += rectTransform.pivot.x * rect.width;
local.y += rectTransform.pivot.y * rect.height;
Rect spriteRect = activeSprite.rect;
Vector4 border = activeSprite.border;
Vector4 adjustedBorder = GetAdjustedBorders(border / pixelsPerUnit, rect);
for (int i = 0; i < 2; i++)
{
if (local[i] <= adjustedBorder[i])
continue;
if (rect.size[i] - local[i] <= adjustedBorder[i + 2])
{
local[i] -= (rect.size[i] - spriteRect.size[i]);
continue;
}
float lerp = Mathf.InverseLerp(adjustedBorder[i], rect.size[i] - adjustedBorder[i + 2], local[i]);
local[i] = Mathf.Lerp(border[i], spriteRect.size[i] - border[i + 2], lerp);
}
// Normalize local coordinates.
Rect textureRect = activeSprite.textureRect;
Vector2 normalized = new Vector2(local.x / textureRect.width, local.y / textureRect.height);
// Convert to texture space.
float x = Mathf.Lerp(textureRect.x, textureRect.xMax, normalized.x) / activeSprite.texture.width;
float y = Mathf.Lerp(textureRect.y, textureRect.yMax, normalized.y) / activeSprite.texture.height;
switch (m_FillDirection)
{
case FillDirection.Right:
if (x > m_FillAmount)
return false;
break;
case FillDirection.Left:
if (1f - x > m_FillAmount)
return false;
break;
case FillDirection.Up:
if (y > m_FillAmount)
return false;
break;
case FillDirection.Down:
if (1f - y > m_FillAmount)
return false;
break;
}
try
{
return activeSprite.texture.GetPixelBilinear(x, y).a >= alphaHitTestMinimumThreshold;
}
catch (UnityException e)
{
Debug.LogError("Using alphaHitTestMinimumThreshold greater than 0 on Image whose sprite texture cannot be read. " + e.Message + " Also make sure to disable sprite packing for this sprite.", this);
return true;
}
}
void ISerializationCallbackReceiver.OnBeforeSerialize() { }
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
m_FillAmount = Mathf.Clamp01(m_FillAmount);
}
// Whether this is being tracked for Atlas Binding
private bool m_Tracked = false;
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWER
private static List<SlicedSlider> m_TrackedTexturelessImages = new List<SlicedSlider>();
private static bool s_Initialized;
#endif
private void TrackImage()
{
if (activeSprite != null && activeSprite.texture == null)
{
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWER
if (!s_Initialized)
{
SpriteAtlasManager.atlasRegistered += RebuildImage;
s_Initialized = true;
}
m_TrackedTexturelessImages.Add(this);
#endif
m_Tracked = true;
}
}
private void UnTrackImage()
{
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWER
m_TrackedTexturelessImages.Remove(this);
#endif
m_Tracked = false;
}
#if UNITY_2017_4 || UNITY_2018_2_OR_NEWER
private static void RebuildImage(SpriteAtlas spriteAtlas)
{
for (int i = m_TrackedTexturelessImages.Count - 1; i >= 0; i--)
{
SlicedSlider image = m_TrackedTexturelessImages[i];
if (spriteAtlas.CanBindTo(image.activeSprite))
{
image.SetAllDirty();
m_TrackedTexturelessImages.RemoveAt(i);
}
}
}
#endif
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b69b55aa2ac2e0e4592740cf1269d52c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,133 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
/// <summary>
/// SystemController singleton
/// </summary>
public class SystemController
{
/// <summary>
/// The instance controlling the singleton
/// </summary>
private static SystemController instance = null;
/// <summary>
/// Stack of the loaded scenes, used to easily go back to previous scenes
/// </summary>
private Stack<int> sceneStack = new Stack<int>();
/// <summary>
/// Index of the previous loaded scene
/// </summary>
public int previousScene = -1;
/// <summary>
/// Index of the current loaded scene
/// </summary>
public int currentScene = -1;
/// <summary>
/// Get the instance loaded by the singleton
/// </summary>
/// <returns>SystemController instance</returns>
public static SystemController GetInstance()
{
// Create a new instance if non exists
if (instance == null)
{
instance = new SystemController();
instance.currentScene = SceneManager.GetActiveScene().buildIndex;
instance.sceneStack.Push(instance.currentScene);
}
return instance;
}
/// <summary>
/// Get the number of passively 'active' scenes
/// </summary>
public int GetSceneStackSize() { return sceneStack.Count; }
/// <summary>
/// Load the scene and push on the stack
/// </summary>
/// <param name="scenePath">Path of the scene</param>
public void LoadNextScene(string scenePath)
{
LoadNextScene(SystemController.GetSceneIndex(scenePath));
}
/// <summary>
/// Get the index of a given scene
/// </summary>
/// <param name="scenePath">Path of the scene</param>
/// <returns></returns>
public static int GetSceneIndex(string scenePath)
{
return SceneUtility.GetBuildIndexByScenePath(scenePath);
}
/// <summary>
/// Load the scene and push on the stack
/// </summary>
/// <param name="sceneIndex">Buildindex of the scene</param>
public void LoadNextScene(int sceneIndex)
{
previousScene = currentScene;
currentScene = sceneIndex;
sceneStack.Push(currentScene);
SceneManager.LoadScene(currentScene);
}
/// <summary>
/// Swap the current scene with the new scene on the stack
/// </summary>
/// <param name="scenePath">Path of the scene</param>
public void SwapScene(string scenePath)
{
SwapScene(SystemController.GetSceneIndex(scenePath));
}
/// <summary>
/// Swap the current scene with the new scene on the stack
/// </summary>
/// <param name="sceneIndex">Buildindex of the scene</param>
public void SwapScene(int sceneIndex)
{
currentScene = sceneStack.Pop();
LoadNextScene(sceneIndex);
}
/// <summary>
/// Go back to the previous scene and unload the current scene
/// </summary>
public void BackToPreviousScene()
{
previousScene = sceneStack.Pop();
if (sceneStack.Count > 0) SceneManager.LoadScene(currentScene = sceneStack.Peek());
else Application.Quit();
}
/// <summary>
/// Go back to a specific scene, unloading all the scenes on the way
/// </summary>
/// <param name="scenePath">Path of the scene</param>
public void BackToScene(string scenePath)
{
BackToScene(SystemController.GetSceneIndex(scenePath));
}
/// <summary>
/// Go back to a specific scene, unloading all the scene on the way
/// </summary>
/// <param name="sceneIndex">Buildindex of the scene</param>
public void BackToScene(int sceneIndex)
{
previousScene = currentScene;
while (0 < sceneStack.Count && sceneStack.Peek() != sceneIndex) sceneStack.Pop();
if (sceneStack.Count > 0) SceneManager.LoadScene(currentScene = sceneStack.Peek());
else Application.Quit();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bf5ea73aa43049e45a0ad926db15f315
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
/// <summary>
/// Enum for easy indexing and checking if a course is of a certain kind
/// </summary>
public enum ThemeIndex
{
SIGN_ALPHABET,
SIGN_BASICS,
SIGN_CLOTHING,
SIGN_ANIMALS,
SIGN_FOOD,
SIGN_HOBBIES,
SIGN_HOUSE,
SIGN_FAMILY,
SPELLING_GEOGRAPY,
SPELLING_BUILDINGS,
SPELLING_SPORTS,
SPELLING_BASICS,
SPELLING_HOBBIES,
SPELLING_PEOPLE,
SPELLING_FRUIT,
SPELLING_VEGGIES,
SPELLING_WILD,
SPELLING_FARM
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 58e9afcf842bdfa48939e754bb39182a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8559f509b8f924f44bc10e2d20ac3eed
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 05ae9a4f64d7f5049b18346b8277e525
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,24 @@
{
"name": "ArchitectureEditMode",
"rootNamespace": "",
"references": [
"UnityEditor.TestRunner",
"UnityEngine.TestRunner",
"ArchitectureScripts"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b1a4ef95cbacdca459433eb2ddc05755
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,777 @@
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
/// <summary>
/// Test the PersistentDataController class
/// </summary>
[TestFixture]
public class PersistentDataControllerTests
{
/// <summary>
/// Create a new path so the existing .json file will not be overwritten
/// </summary>
private static string PATH = $"{Application.persistentDataPath}/wesign_unit_test.json";
/// <summary>
/// Reference to the pdc to perform tests on
/// </summary>
private PersistentDataController pdc = null;
/// <summary>
/// A dummy serializable struct to perform test operations on
/// </summary>
[Serializable]
private struct Struct
{
public int r, g, b;
public float x, y, z;
}
/// <summary>
/// A dummy serializable enum to perform test operations on
/// </summary>
private enum Enum
{
SQUARE,
TRIANBLE,
CIRCLE
}
[SetUp]
public void Setup_PersistentDataController()
{
Assert.IsNull(PersistentDataController.PATH);
PersistentDataController.PATH = PersistentDataControllerTests.PATH;
pdc = PersistentDataController.GetInstance();
}
[TearDown]
public void TearDown_PersistentDataController()
{
PersistentDataController.PATH = null;
}
[Test]
public void Test_PersistentDataController_GetInstance()
{
PersistentDataController.PATH = null;
Assert.IsNotNull(PersistentDataController.GetInstance());
Assert.AreEqual(0x04_03, PersistentDataController.VERSION);
Assert.AreEqual($"{Application.persistentDataPath}/wesign_saved_data.json", PersistentDataController.PATH);
}
[Test]
public void Test_PersistentDataController_Clear()
{
pdc.Load();
pdc.Clear();
Assert.Zero(pdc.GetUsers().Count);
Assert.AreEqual(-1, pdc.GetCurrentUser());
}
[Test]
public void Test_PersistentDataController_Save_Empty()
{
pdc.Load();
pdc.Clear();
pdc.Save();
FileAssert.Exists(PATH);
string content = File.ReadAllText(PATH);
string expected = "{\"version\":1027,\"users\":[],\"currentUser\":-1,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0}";
Assert.AreEqual(expected, content);
}
[Test]
public void Test_PersistentDataController_Save_New()
{
pdc.Load();
pdc.Clear();
if (File.Exists(PATH))
File.Delete(PATH);
pdc.Save();
FileAssert.Exists(PATH);
string content = File.ReadAllText(PATH);
string expected = "{\"version\":1027,\"users\":[],\"currentUser\":-1,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0}";
Assert.AreEqual(expected, content);
}
[Test]
public void Test_PersistentDataController_Load_Existing()
{
string content = "{\"version\":1027,\"users\":[],\"currentUser\":-1,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0}";
File.WriteAllText(PATH, content);
Assert.IsTrue(pdc.Load(false));
}
[Test]
public void Test_PersistentDataController_Load_OlderVersion()
{
string content = "{\"version\":1026,\"users\":[],\"currentUser\":-1,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0}";
File.WriteAllText(PATH, content);
Assert.IsFalse(pdc.Load(false));
}
[Test]
public void Test_PersistentDataController_Load_NewerVersion()
{
string content = "{\"version\":1028,\"users\":[],\"currentUser\":-1,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0}";
File.WriteAllText(PATH, content);
Assert.IsFalse(pdc.Load(false));
}
[Test]
public void Test_PersistentDataController_Load_New()
{
if (File.Exists(PATH))
File.Delete(PATH);
Assert.IsFalse(pdc.Load(false));
FileAssert.DoesNotExist(PATH);
}
[Test]
public void Test_PersistentDataController_Load_Exception()
{
File.WriteAllText(PATH, "https://www.youtube.com/watch?v=dQw4w9WgXcQ");
Assert.IsFalse(pdc.Load(false));
Assert.AreEqual("https://www.youtube.com/watch?v=dQw4w9WgXcQ", File.ReadAllText(PATH));
}
[Test]
public void Test_PersistentDataController_Load_Override()
{
File.WriteAllText(PATH, "https://www.youtube.com/watch?v=dQw4w9WgXcQ");
Assert.IsFalse(pdc.Load(true));
string content = File.ReadAllText(PATH);
string expected = "{\"version\":1027,\"users\":[],\"currentUser\":-1,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0}";
Assert.AreEqual(expected, content);
}
[Test]
public void Test_PersistentDataController_Version()
{
const int VERSION = 0x04_03;
Assert.AreEqual(VERSION, PersistentDataController.VERSION);
}
[Test]
public void Test_PersistentDataController_AddUser()
{
pdc.Load();
pdc.Clear();
var d = new PersistentDataController.SavedUserData()
{
username = "username",
avatarIndex = 0
};
pdc.AddUser(d);
string content = File.ReadAllText(PATH);
string expected = "{\"version\":1027,\"users\":[{\"entries\":[],\"username\":\"username\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0}";
Assert.AreEqual(expected, content);
}
[Test]
public void Test_PersistentDataController_GetUsers()
{
pdc.Load();
pdc.Clear();
var d = new PersistentDataController.SavedUserData()
{
username = "username",
avatarIndex = 0
};
pdc.AddUser(d);
var users = pdc.GetUsers();
Assert.AreEqual(1, users.Count);
Assert.AreEqual("username", users[0].username);
Assert.AreEqual(0, users[0].avatarIndex);
}
[Test]
public void Test_PersistentDataController_GetCurrentUser()
{
pdc.Load();
pdc.Clear();
Assert.AreEqual(-1, pdc.GetCurrentUser());
pdc.AddUser(new PersistentDataController.SavedUserData()
{
username = "username",
avatarIndex = 0
});
Assert.AreEqual(0, pdc.GetCurrentUser());
}
[Test]
public void Test_PersistentDataController_SetCurrentUser()
{
pdc.Load();
pdc.Clear();
for (int i = 0; i < 5; i++)
pdc.AddUser(new PersistentDataController.SavedUserData()
{
username = $"username_{i}",
avatarIndex = i
});
pdc.SetCurrentUser(3);
Assert.AreEqual(3, pdc.GetCurrentUser());
}
[Test]
public void Test_PersistentDataController_SetCurrentUser_Invalid()
{
pdc.Load();
pdc.Clear();
pdc.AddUser(new PersistentDataController.SavedUserData()
{
username = $"username",
avatarIndex = 0
});
Assert.Throws<IndexOutOfRangeException>(delegate { pdc.SetCurrentUser(3); });
}
[Test]
public void Test_PersistentDataController_SetCurrentUser_Empty()
{
pdc.Load();
pdc.Clear();
Assert.Throws<IndexOutOfRangeException>(delegate { pdc.SetCurrentUser(0); });
}
[Test]
public void Test_PersistentDataController_DeleteUser_BeforeCurrent()
{
pdc.Load();
pdc.Clear();
var users = new List<PersistentDataController.SavedUserData>();
for (int i = 0; i < 5; i++)
{
var d = new PersistentDataController.SavedUserData()
{
username = $"username_{i}",
avatarIndex = i
};
pdc.AddUser(d);
users.Add(d);
}
pdc.SetCurrentUser(0);
users.RemoveAt(2);
pdc.DeleteUser(2);
var vsers = pdc.GetUsers();
Assert.AreEqual(0, pdc.GetCurrentUser());
Assert.AreEqual(users.Count, vsers.Count);
for (int i = 0; i < 4; i++)
{
Assert.AreEqual(users[i].username, vsers[i].username);
Assert.AreEqual(users[i].avatarIndex, vsers[i].avatarIndex);
}
}
[Test]
public void Test_PersistentDataController_DeleteUser_Current()
{
pdc.Load();
pdc.Clear();
var users = new List<PersistentDataController.SavedUserData>();
for (int i = 0; i < 5; i++)
{
var d = new PersistentDataController.SavedUserData()
{
username = $"username_{i}",
avatarIndex = i
};
pdc.AddUser(d);
users.Add(d);
}
pdc.SetCurrentUser(2);
users.RemoveAt(2);
pdc.DeleteUser(2);
var vsers = pdc.GetUsers();
Assert.AreEqual(1, pdc.GetCurrentUser());
Assert.AreEqual(users.Count, vsers.Count);
for (int i = 0; i < 4; i++)
{
Assert.AreEqual(users[i].username, vsers[i].username);
Assert.AreEqual(users[i].avatarIndex, vsers[i].avatarIndex);
}
}
[Test]
public void Test_PersistentDataController_DeleteUser_AfterCurrent()
{
pdc.Load();
pdc.Clear();
var users = new List<PersistentDataController.SavedUserData>();
for (int i = 0; i < 5; i++)
{
var d = new PersistentDataController.SavedUserData()
{
username = $"username_{i}",
avatarIndex = i
};
pdc.AddUser(d);
users.Add(d);
}
pdc.SetCurrentUser(4);
users.RemoveAt(2);
pdc.DeleteUser(2);
var vsers = pdc.GetUsers();
Assert.AreEqual(3, pdc.GetCurrentUser());
Assert.AreEqual(users.Count, vsers.Count);
for (int i = 0; i < 4; i++)
{
Assert.AreEqual(users[i].username, vsers[i].username);
Assert.AreEqual(users[i].avatarIndex, vsers[i].avatarIndex);
}
}
[Test]
public void Test_PersistentDataController_DeleteUser_Invalid()
{
pdc.Load();
pdc.Clear();
pdc.AddUser(new PersistentDataController.SavedUserData()
{
username = $"username",
avatarIndex = 0
});
Assert.Throws<IndexOutOfRangeException>(delegate { pdc.SetCurrentUser(3); });
}
[Test]
public void Test_PersistentDataController_DeleteUser_Empty()
{
pdc.Load();
pdc.Clear();
Assert.Throws<IndexOutOfRangeException>(delegate { pdc.DeleteUser(0); });
}
[Test]
public void Test_PersistentDataController_CurrentCourse()
{
pdc.Load();
pdc.Clear();
pdc.SetCurrentCourse(CourseIndex.FINGERSPELLING);
Assert.AreEqual(CourseIndex.FINGERSPELLING, pdc.GetCurrentCourse());
}
[Test]
public void Test_PersistentDataController_CurrentMinigame()
{
pdc.Load();
pdc.Clear();
pdc.SetCurrentMinigame(MinigameIndex.SPELLING_BEE);
Assert.AreEqual(MinigameIndex.SPELLING_BEE, pdc.GetCurrentMinigame());
}
[Test]
public void Test_PersistentDataController_CurrentTheme()
{
pdc.Load();
pdc.Clear();
pdc.SetCurrentTheme(ThemeIndex.SIGN_ALPHABET);
Assert.AreEqual(ThemeIndex.SIGN_ALPHABET, pdc.GetCurrentTheme());
}
[Test]
public void Test_New_PersistentDataContainer()
{
var c = new PersistentDataController.PersistentDataContainer();
Assert.IsNotNull(c);
Assert.Zero(c.entries.Count);
}
[Test]
public void Test_PersistentDataContainer_Set_Invalid()
{
var c = new PersistentDataController.PersistentDataContainer();
Assert.IsFalse(c.Set<object>("key", null));
}
[Test]
public void Test_PersistentDataContainer_Set_DuplicateKey()
{
var c = new PersistentDataController.PersistentDataContainer();
Assert.IsTrue(c.Set<int>("key", 123));
Assert.IsTrue(c.Set<int>("key", 321));
}
[Test]
public void Test_PersistentDataContainer_Set_Int()
{
var c = new PersistentDataController.PersistentDataContainer();
Assert.IsTrue(c.Set<int>("key", 123));
}
[Test]
public void Test_PersistentDataContainer_Set_String()
{
var c = new PersistentDataController.PersistentDataContainer();
Assert.IsTrue(c.Set<string>("key", "abc"));
}
[Test]
public void Test_PersistentDataContainer_Set_Struct()
{
var c = new PersistentDataController.PersistentDataContainer();
Assert.IsTrue(c.Set<Struct>("key", new Struct()));
}
[Test]
public void Test_PersistentDataContainer_Set_Enum()
{
var c = new PersistentDataController.PersistentDataContainer();
Assert.IsTrue(c.Set<Enum>("key", new Enum()));
}
[Test]
public void Test_PersistentDataContainer_Get_InvalidType()
{
var c = new PersistentDataController.PersistentDataContainer();
c.Set<Struct>("key", new Struct() { r = 255, g = 127, b = 63, x = 31, y = 15, z = 7 });
Assert.Throws<InvalidCastException>(delegate { c.Get<int>("key"); });
c.Set<int>("key", 123);
Assert.Throws<InvalidCastException>(delegate { c.Get<Struct>("key"); });
}
[Test]
public void Test_PersistentDataContainer_Get_KeyNotFound()
{
var c = new PersistentDataController.PersistentDataContainer();
c.Set<int>("key", 123);
Assert.Throws<KeyNotFoundException>(delegate { c.Get<int>("KEY"); });
}
[Test]
public void Test_PersistentDataContainer_Get_Empty()
{
var c = new PersistentDataController.PersistentDataContainer();
Assert.Throws<KeyNotFoundException>(delegate { c.Get<int>("key"); });
}
[Test]
public void Test_PersistentDataContainer_Get_Int()
{
var c = new PersistentDataController.PersistentDataContainer();
c.Set<int>("key", 123);
Assert.AreEqual(123, c.Get<int>("key"));
}
[Test]
public void Test_PersistentDataContainer_Get_String()
{
var c = new PersistentDataController.PersistentDataContainer();
c.Set<string>("key", "value");
Assert.AreEqual("value", c.Get<string>("key"));
}
[Test]
public void Test_PersistentDataContainer_Get_Struct()
{
var c = new PersistentDataController.PersistentDataContainer();
var s = new Struct() { r = 255, g = 127, b = 63, x = 31, y = 15, z = 7 };
c.Set<Struct>("key", s);
Assert.AreEqual(s, c.Get<Struct>("key"));
}
[Test]
public void Test_PersistentDataContainer_Get_Enum()
{
var c = new PersistentDataController.PersistentDataContainer();
var e = Enum.CIRCLE;
c.Set<Enum>("key", e);
Assert.AreEqual(e, c.Get<Enum>("key"));
}
[Test]
public void Test_PersistentDataContainer_Remove_Invalid()
{
var c = new PersistentDataController.PersistentDataContainer();
c.Set<int>("key", 123);
Assert.Throws<KeyNotFoundException>(delegate { c.Remove("KEY"); });
}
[Test]
public void Test_PersistentDataContainer_Remove_Empty()
{
var c = new PersistentDataController.PersistentDataContainer();
Assert.Throws<KeyNotFoundException>(delegate { c.Remove("key"); });
}
[Test]
public void Test_PersistentDataContainer_Remove_Int()
{
var c = new PersistentDataController.PersistentDataContainer();
c.Set<int>("key", 123);
c.Remove("key");
Assert.Throws<KeyNotFoundException>(delegate { c.Get<int>("key"); });
}
[Test]
public void Test_PersistentDataContainer_Remove_String()
{
var c = new PersistentDataController.PersistentDataContainer();
c.Set<string>("key", "value");
c.Remove("key");
Assert.Throws<KeyNotFoundException>(delegate { c.Get<string>("key"); });
}
[Test]
public void Test_PersistentDataContainer_Remove_Struct()
{
var c = new PersistentDataController.PersistentDataContainer();
var s = new Struct() { r = 255, g = 127, b = 63, x = 31, y = 15, z = 7 };
c.Set<Struct>("key", s);
c.Remove("key");
Assert.Throws<KeyNotFoundException>(delegate { c.Get<Struct>("key"); });
}
[Test]
public void Test_PersistentDataContainer_Remove_Enum()
{
var c = new PersistentDataController.PersistentDataContainer();
c.Set<Enum>("key", Enum.CIRCLE);
c.Remove("key");
Assert.Throws<KeyNotFoundException>(delegate { c.Get<Enum>("key"); });
}
[Test]
public void Test_PersistentDataContainer_Pop_Invalid()
{
var c = new PersistentDataController.PersistentDataContainer();
c.Set<int>("key", 123);
Assert.Throws<KeyNotFoundException>(delegate { c.Remove("KEY"); });
}
[Test]
public void Test_PersistentDataContainer_Pop_Empty()
{
var c = new PersistentDataController.PersistentDataContainer();
Assert.Throws<KeyNotFoundException>(delegate { c.Remove("KEY"); });
}
[Test]
public void Test_PersistentDataContainer_Pop_Int()
{
var c = new PersistentDataController.PersistentDataContainer();
c.Set<int>("key", 123);
Assert.AreEqual(123, c.Pop<int>("key"));
Assert.Throws<KeyNotFoundException>(delegate { c.Get<int>("key"); });
}
[Test]
public void Test_PersistentDataContainer_Pop_String()
{
var c = new PersistentDataController.PersistentDataContainer();
c.Set<string>("key", "value");
Assert.AreEqual("value", c.Pop<string>("key"));
Assert.Throws<KeyNotFoundException>(delegate { c.Get<string>("key"); });
}
[Test]
public void Test_PersistentDataContainer_Pop_Struct()
{
var c = new PersistentDataController.PersistentDataContainer();
var s = new Struct() { r = 255, g = 127, b = 63, x = 31, y = 15, z = 7 };
c.Set<Struct>("key", s);
Assert.AreEqual(s, c.Pop<Struct>("key"));
Assert.Throws<KeyNotFoundException>(delegate { c.Get<Struct>("key"); });
}
[Test]
public void Test_PersistentDataContainer_Pop_Enum()
{
var c = new PersistentDataController.PersistentDataContainer();
c.Set<Enum>("key", Enum.CIRCLE);
Assert.AreEqual(Enum.CIRCLE, c.Pop<Enum>("key"));
Assert.Throws<KeyNotFoundException>(delegate { c.Get<Enum>("key"); });
}
[Test]
public void Test_PersistentDataContainer_Has_ValidKey()
{
var c = new PersistentDataController.PersistentDataContainer();
Assert.IsFalse(c.Has("key"));
c.Set<int>("key", 123);
Assert.IsTrue(c.Has("key"));
}
[Test]
public void Test_PersistentDataContainer_Has_InvalidKey()
{
var c = new PersistentDataController.PersistentDataContainer();
Assert.IsFalse(c.Has("KEY"));
c.Set<int>("key", 123);
Assert.IsFalse(c.Has("KEY"));
}
[Test]
public void Test_SavedCourseProgress_AddLearnable_Valid()
{
PersistentDataController.SavedCourseProgress progress = new PersistentDataController.SavedCourseProgress();
Assert.Zero(progress.learnables.Count);
bool added = progress.AddLearnable("learnable", 0);
Assert.IsTrue(added);
Assert.AreEqual(1, progress.learnables.Count);
Assert.AreEqual("learnable", progress.learnables[0].name);
Assert.AreEqual(0, progress.FindLearnable("learnable").index);
}
[Test]
public void Test_SavedCourseProgress_AddLearnable_DuplicateName()
{
PersistentDataController.SavedCourseProgress progress = new PersistentDataController.SavedCourseProgress();
progress.AddLearnable("learnable", 0);
Assert.AreEqual(1, progress.learnables.Count);
Assert.IsFalse(progress.AddLearnable("learnable", 1));
Assert.AreEqual(1, progress.learnables.Count);
}
[Test]
public void Test_SavedCourseProgress_AddLearnable_DuplicateIndex()
{
PersistentDataController.SavedCourseProgress progress = new PersistentDataController.SavedCourseProgress();
progress.AddLearnable("learnable", 0);
Assert.AreEqual(1, progress.learnables.Count);
Assert.IsFalse(progress.AddLearnable("LEARNABLE", 0));
Assert.AreEqual(1, progress.learnables.Count);
}
[Test]
public void Test_SavedCourseProgress_UpdateLearnable_InvalidName()
{
PersistentDataController.SavedCourseProgress progress = new PersistentDataController.SavedCourseProgress();
progress.AddLearnable("learnable", 0);
Assert.AreEqual(0.0f, progress.FindLearnable("learnable").progress);
Assert.Throws<KeyNotFoundException>(delegate { progress.UpdateLearnable("LEARNABLE", 3.0f); });
Assert.AreEqual(0.0f, progress.FindLearnable("learnable").progress);
}
[Test]
public void Test_SavedCourseProgress_UpdateLearnable_UpdatesProgress()
{
PersistentDataController.SavedCourseProgress progress = new PersistentDataController.SavedCourseProgress();
progress.AddLearnable("learnable", 0);
Assert.AreEqual(0.0f, progress.FindLearnable("learnable").progress);
progress.UpdateLearnable("learnable", 3.0f);
Assert.AreEqual(3.0f, progress.FindLearnable("learnable").progress);
}
[Test]
public void Test_SavedCourseProgress_UpdateLearnable_CropsProgressAtFive()
{
PersistentDataController.SavedCourseProgress progress = new PersistentDataController.SavedCourseProgress();
progress.AddLearnable("learnable", 0);
Assert.AreEqual(0, progress.completedLearnables);
progress.UpdateLearnable("learnable", 10.0f);
Assert.AreEqual(5.0f, progress.FindLearnable("learnable").progress);
Assert.AreEqual(1, progress.completedLearnables);
}
[Test]
public void Test_SavedCourseProgress_UpdateLearnable_CropsProgressAtNegativeFive()
{
PersistentDataController.SavedCourseProgress progress = new PersistentDataController.SavedCourseProgress();
progress.AddLearnable("learnable", 0);
Assert.AreEqual(0, progress.completedLearnables);
progress.UpdateLearnable("learnable", -10.0f);
Assert.AreEqual(-5.0f, progress.FindLearnable("learnable").progress);
Assert.AreEqual(0, progress.completedLearnables);
}
[Test]
public void Test_SavedCourseProgress_FindLearnable()
{
PersistentDataController.SavedCourseProgress progress = new PersistentDataController.SavedCourseProgress();
progress.AddLearnable("learnable 1", 0);
Assert.IsNull(progress.FindLearnable("learnable 2"));
progress.AddLearnable("learnable 2", 1);
Assert.IsNotNull(progress.FindLearnable("learnable 2"));
}
[Test]
public void Test_SavedCourseProgress_GetRandomLearnable_NoLearnables()
{
PersistentDataController.SavedCourseProgress progress = new PersistentDataController.SavedCourseProgress();
Assert.IsNull(progress.GetRandomLearnable());
}
[Test]
public void Test_SavedCourseProgress_GetRandomLearnable_NoUnusedLearnables()
{
PersistentDataController.SavedCourseProgress progress = new PersistentDataController.SavedCourseProgress();
progress.AddLearnable("learnable", 0);
progress.FindLearnable("learnable").inUse = true;
progress.completedLearnables = 1;
progress.inUseLearnables = 0;
Assert.IsNull(progress.GetRandomLearnable());
}
[Test]
public void Test_SavedCourseProgress_GetRandomLearnable_OnlyCompletedLearnables()
{
PersistentDataController.SavedCourseProgress progress = new PersistentDataController.SavedCourseProgress();
for (int i = 0; i < 2; i++)
{
progress.AddLearnable($"learnable {i}", i);
var learnable = progress.FindLearnable($"learnable {i}");
learnable.progress = 4.0f;
learnable.inUse = true;
}
progress.completedLearnables = 2;
progress.inUseLearnables = 0;
Assert.IsNull(progress.GetRandomLearnable());
}
[Test]
public void Test_SavedCourseProgress_GetRandomLearnable_Valid()
{
PersistentDataController.SavedCourseProgress progress = new PersistentDataController.SavedCourseProgress();
for (int i = 0; i < 10; i++)
{
progress.AddLearnable($"learnable {i}", i);
progress.FindLearnable($"learnable {i}").inUse = true;
}
progress.completedLearnables = 0;
progress.inUseLearnables = 10;
Assert.AreEqual(10, progress.inUseLearnables);
Assert.AreEqual(0, progress.completedLearnables);
Assert.IsNotNull(progress.GetRandomLearnable());
Assert.AreEqual(10, progress.inUseLearnables);
Assert.AreEqual(0, progress.completedLearnables);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 56873c5649b881846a54e2a2aa5ce499
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
using NUnit.Framework;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
/// <summary>
/// Test the SystemController class
/// </summary>
[TestFixture]
public class SystemControllerTests
{
[Test]
public void Test_SystemController_GetInstance()
{
Assert.IsNotNull(SystemController.GetInstance());
}
[Test]
public void Test_GetSceneIndex_InvalidScene()
{
Assert.AreEqual(-1, SystemController.GetSceneIndex("a/non/existing/scene"));
}
[Test]
public void Test_GetSceneIndex_ValidScene()
{
List<string> scenes = new List<string>()
{
"Common/Scenes/Boot",
"Common/Scenes/MainMenuScreen",
"Common/Scenes/CoursesMenuScreen",
"Common/Scenes/ListCoursesScreen",
"Common/Scenes/ListMinigamesScreen",
"Common/Scenes/CourseActivityScreen",
"Common/Scenes/MinigameActivityScreen",
"Common/Scenes/ThemeSelectionScreen",
"Common/Scenes/SettingsScreen",
"Accounts/Scenes/UserCreationScreen",
"Accounts/Scenes/ChangeUserScreen",
"Accounts/Scenes/UserProgressScreen",
"Courses/Scenes/CourseScreen",
"SpellingBee/Scenes/SpellingBeeGame",
"Hangman/Scenes/HangmanGame",
"JustSign/Scenes/JustSignGame",
};
Assert.AreEqual(SceneManager.sceneCountInBuildSettings, scenes.Count);
// Testing wether the names and indices are correct needs to be done in PlayMode
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17b5c320c11ddd6439fc5823fc1aaca6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 865ee232b6fa1184084ab1d58aaba61e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
{
"name": "ArchitecturePlayMode",
"rootNamespace": "",
"references": [
"UnityEditor.TestRunner",
"UnityEngine.TestRunner",
"ArchitectureScripts",
"AccountsScripts"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f8ed003d51e12ca44a9b41f98a4f9f3d
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,304 @@
using NUnit.Framework;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
/// <summary>
/// Test the SystemController class
/// </summary>
[TestFixture]
public class SystemControllerTests
{
/// <summary>
/// Wait time between scene transitions
/// </summary>
private const float WAIT_TIME = 0.2f;
/// <summary>
/// Reference to the SystemController instance
/// </summary>
private SystemController controller;
/// <summary>
/// Setting up the tests
/// </summary>
[UnitySetUp]
public IEnumerator Setup_SystemController()
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string oneUser = "{\"version\":1027,\"users\":[{\"entries\":[],\"username\":\"Tester0\",\"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();
controller = SystemController.GetInstance();
controller.LoadNextScene("Common/Scenes/MainMenuScreen");
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Cleaning up the tests
/// </summary>
[TearDown]
public void TearDown_SystemController()
{
controller.BackToScene(SceneManager.sceneCountInBuildSettings);
}
/// <summary>
/// Test whether all scenes are correctly inserted to the build path
/// </summary>
[Test]
public void Test_GetSceneIndex_ValidScene()
{
List<string> scenes = new List<string>()
{
"Common/Scenes/Boot",
"Common/Scenes/MainMenuScreen",
"Common/Scenes/CoursesMenuScreen",
"Common/Scenes/ListCoursesScreen",
"Common/Scenes/ListMinigamesScreen",
"Common/Scenes/CourseActivityScreen",
"Common/Scenes/MinigameActivityScreen",
"Common/Scenes/ThemeSelectionScreen",
"Common/Scenes/SettingsScreen",
"Accounts/Scenes/UserCreationScreen",
"Accounts/Scenes/ChangeUserScreen",
"Accounts/Scenes/UserProgressScreen",
"Courses/Scenes/CourseScreen",
"SpellingBee/Scenes/SpellingBeeGame",
"Hangman/Scenes/HangmanGame",
"JustSign/Scenes/JustSignGame",
};
for (var i = 0; i < scenes.Count; i++)
Assert.AreEqual(i, SystemController.GetSceneIndex(scenes[i]));
}
/// <summary>
/// Test whether a next scene can be loaded
/// </summary>
[UnityTest]
public IEnumerator Test_LoadNextScene_String()
{
int stackSize = controller.GetSceneStackSize();
string previous = "Common/Scenes/MainMenuScreen";
string next = "Common/Scenes/CoursesMenuScreen";
Assert.AreEqual(SystemController.GetSceneIndex(previous), controller.currentScene);
Assert.AreEqual(stackSize, controller.GetSceneStackSize());
controller.LoadNextScene(next);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(SystemController.GetSceneIndex(previous), controller.previousScene);
Assert.AreEqual(SystemController.GetSceneIndex(next), controller.currentScene);
Assert.AreEqual(stackSize + 1, controller.GetSceneStackSize());
}
/// <summary>
/// Test whether a next scene can be loaded
/// </summary>
[UnityTest]
public IEnumerator Test_LoadNextScene_Int()
{
int stackSize = controller.GetSceneStackSize();
int previous = 1;
int next = 2;
Assert.AreEqual(previous, controller.currentScene);
Assert.AreEqual(stackSize, controller.GetSceneStackSize());
controller.LoadNextScene(next);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(previous, controller.previousScene);
Assert.AreEqual(next, controller.currentScene);
Assert.AreEqual(stackSize + 1, controller.GetSceneStackSize());
}
/// <summary>
/// Test whether a scene can be swapped with the current one
/// </summary>
[UnityTest]
public IEnumerator Test_SwapScene_String()
{
int stackSize = controller.GetSceneStackSize();
string previous = "Common/Scenes/MainMenuScreen";
string next = "Common/Scenes/CoursesMenuScreen";
Assert.AreEqual(SystemController.GetSceneIndex(previous), controller.currentScene);
Assert.AreEqual(stackSize, controller.GetSceneStackSize());
controller.SwapScene(next);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(SystemController.GetSceneIndex(previous), controller.previousScene);
Assert.AreEqual(SystemController.GetSceneIndex(next), controller.currentScene);
Assert.AreEqual(stackSize, controller.GetSceneStackSize());
}
/// <summary>
/// Test whether a scene can be swapped with the current one
/// </summary>
[UnityTest]
public IEnumerator Test_SwapScene_Int()
{
int stackSize = controller.GetSceneStackSize();
int previous = 1;
int next = 2;
Assert.AreEqual(previous, controller.currentScene);
Assert.AreEqual(stackSize, controller.GetSceneStackSize());
controller.SwapScene(next);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(previous, controller.previousScene);
Assert.AreEqual(next, controller.currentScene);
Assert.AreEqual(stackSize, controller.GetSceneStackSize());
}
/// <summary>
/// Test whether the previous scene can be loaded
/// </summary>
[UnityTest]
public IEnumerator Test_BackToPreviousScene_LoadScene()
{
int stackSize = controller.GetSceneStackSize();
string previous = "Common/Scenes/MainMenuScreen";
string current = "Common/Scenes/CoursesMenuScreen";
string next = "Common/Scenes/ListCoursesScreen";
controller.LoadNextScene(current);
yield return new WaitForSeconds(WAIT_TIME);
controller.LoadNextScene(next);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(SystemController.GetSceneIndex(current), controller.previousScene);
Assert.AreEqual(SystemController.GetSceneIndex(next), controller.currentScene);
Assert.AreEqual(stackSize + 2, controller.GetSceneStackSize());
controller.BackToPreviousScene();
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(stackSize + 1, controller.GetSceneStackSize());
controller.BackToPreviousScene();
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(SystemController.GetSceneIndex(current), controller.previousScene);
Assert.AreEqual(SystemController.GetSceneIndex(previous), controller.currentScene);
Assert.AreEqual(stackSize, controller.GetSceneStackSize());
}
/// <summary>
/// Test whether when requesting to go back on the ast scene, will close the application
/// </summary>
[UnityTest]
public IEnumerator Test_BackToPreviousScene_QuitApplication()
{
int stackSize = controller.GetSceneStackSize();
controller.BackToPreviousScene();
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(stackSize - 1, controller.GetSceneStackSize());
}
/// <summary>
/// Test whether a previous scene can be loaded
/// </summary>
[UnityTest]
public IEnumerator Test_BackToScene_String_LoadScene()
{
int stackSize = controller.GetSceneStackSize();
string previous = "Common/Scenes/MainMenuScreen";
string current = "Common/Scenes/CoursesMenuScreen";
string next = "Common/Scenes/ListCoursesScreen";
controller.LoadNextScene(current);
yield return new WaitForSeconds(WAIT_TIME);
controller.LoadNextScene(next);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(SystemController.GetSceneIndex(current), controller.previousScene);
Assert.AreEqual(SystemController.GetSceneIndex(next), controller.currentScene);
Assert.AreEqual(stackSize + 2, controller.GetSceneStackSize());
controller.BackToScene(previous);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(SystemController.GetSceneIndex(next), controller.previousScene);
Assert.AreEqual(SystemController.GetSceneIndex(previous), controller.currentScene);
Assert.AreEqual(stackSize, controller.GetSceneStackSize());
}
/// <summary>
/// Test whether when requesting to go back to scene that is no longer loaded, will close the application
/// </summary>
[UnityTest]
public IEnumerator Test_BackToScene_String_QuitApplication()
{
int stackSize = controller.GetSceneStackSize();
string previous = "Common/Scenes/MainMenuScreen";
string current = "Common/Scenes/CoursesMenuScreen";
string next = "Common/Scenes/ListCoursesScreen";
controller.SwapScene(current);
yield return new WaitForSeconds(WAIT_TIME);
controller.LoadNextScene(next);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(SystemController.GetSceneIndex(current), controller.previousScene);
Assert.AreEqual(SystemController.GetSceneIndex(next), controller.currentScene);
Assert.AreEqual(stackSize + 1, controller.GetSceneStackSize());
controller.BackToScene(previous);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(stackSize - 1, controller.GetSceneStackSize());
}
/// <summary>
/// Test whether a previous scene can be loaded
/// </summary>
[UnityTest]
public IEnumerator Test_BackToScene_Int_LoadScene()
{
int stackSize = controller.GetSceneStackSize();
int previous = 1;
int current = 2;
int next = 3;
controller.LoadNextScene(current);
yield return new WaitForSeconds(WAIT_TIME);
controller.LoadNextScene(next);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(current, controller.previousScene);
Assert.AreEqual(next, controller.currentScene);
Assert.AreEqual(stackSize + 2, controller.GetSceneStackSize());
controller.BackToScene(previous);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(next, controller.previousScene);
Assert.AreEqual(previous, controller.currentScene);
Assert.AreEqual(stackSize, controller.GetSceneStackSize());
}
/// <summary>
/// Test whether when requesting to go back to scene that is no longer loaded, will close the application
/// </summary>
[UnityTest]
public IEnumerator Test_BackToScene_Int_QuitApplication()
{
int stackSize = controller.GetSceneStackSize();
int previous = 1;
int current = 2;
int next = 3;
controller.SwapScene(current);
yield return new WaitForSeconds(WAIT_TIME);
controller.LoadNextScene(next);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(current, controller.previousScene);
Assert.AreEqual(next, controller.currentScene);
Assert.AreEqual(stackSize + 1, controller.GetSceneStackSize());
controller.BackToScene(previous);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(stackSize - 1, controller.GetSceneStackSize());
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8ede8e90b1ef6144ca9b5e54493894fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: