1 Commits

Author SHA1 Message Date
Supaaah1
14241c3e7b showcase
don't merge this shitty ass code pls
2023-03-24 17:28:17 +01:00
2924 changed files with 172769 additions and 120670 deletions

View File

@@ -27,7 +27,7 @@ steps:
pull: if-not-exists
image: sonarsource/sonar-scanner-cli
commands:
- sonar-scanner -Dsonar.host.url=$SONAR_HOST -Dsonar.login=$SONAR_TOKEN -Dsonar.projectKey=$SONAR_PROJECT_KEY -Dsonar.projectVersion=$DRONE_REPO_BRANCH-$DRONE_COMMIT_AUTHOR-$DRONE_COMMIT -Dsonar.coverageReportPaths="./code_coverage/Report/SonarQube.xml"
- sonar-scanner -Dsonar.host.url=$SONAR_HOST -Dsonar.login=$SONAR_TOKEN -Dsonar.projectKey=$SONAR_PROJECT_KEY -Dsonar.coverageReportPaths="./code_coverage/Report/SonarQube.xml"
environment:
SONAR_HOST:
from_secret: sonar_host
@@ -37,3 +37,47 @@ steps:
from_secret: sonar_project_key
---
kind: pipeline
name: builds
type: docker
trigger:
event:
- push
branch:
- master
- development
- Automatic-Builds
steps:
- name: unity-builds
image: docker.io/library/unity-runner:0.1
commands:
- mkdir -p ./wesign-builds/{tmp,WeSign-Windows,WeSign-Linux,WeSign-MacOS}
- /opt/unity/editors/2021.3.19f1/Editor/Unity -batchmode -nographics -projectPath . -buildWindowsPlayer ./wesign-builds/tmp/WeSign-Windows.exe -quit --headless || true
- chmod 777 -R .
- /opt/unity/editors/2021.3.19f1/Editor/Unity -batchmode -nographics -projectPath . -buildWindowsPlayer ./wesign-builds/WeSign-Windows/WeSign.exe -quit --headless
- /opt/unity/editors/2021.3.19f1/Editor/Unity -batchmode -nographics -projectPath . -buildLinux64Player ./wesign-builds/WeSign-Linux/WeSign -quit --headless
- /opt/unity/editors/2021.3.19f1/Editor/Unity -batchmode -nographics -projectPath . -buildOSXUniversalPlayer ./wesign-builds/WeSign-MacOS/WeSign.app -quit --headless
- name: commit-files
image: alpine/git
environment:
GIT_AUTHOR_NAME: DroneCI
GIT_AUTHOR_EMAIL: droneci@wesign.com
GIT_COMMITTER_NAME: DroneCI
GIT_COMMITTER_EMAIL: droneci@wesign.com
commands:
- git config --global user.name "DroneCI"
- git config --global user.email "droneci@wesign.com"
- zip -r ./wesign-builds/WeSign-Windows.zip ./wesign-builds/WeSign-Windows
- zip -r ./wesign-builds/WeSign-MacOS.zip ./wesign-builds/WeSign-MacOS
- zip -r ./wesign-builds/WeSign-Linux.zip ./wesign-builds/WeSign-Linux
- git add ./wesign-builds/WeSign-Windows.zip
- git add ./wesign-builds/WeSign-MacOS.zip
- git add ./wesign-builds/WeSign-Linux.zip
- git commit -m "Add build files [skip ci]"
- git push -f https://oauth2:ixKiNbp48zzmP5PF-epo@gitlab.ilabt.imec.be/wesign/unity-application/

5
.gitignore vendored
View File

@@ -9,7 +9,6 @@
/[Bb]uilds/
/[Ll]ogs/
/[Uu]ser[Ss]ettings/
/[Cc]ode[Cc]overage/
# MemoryCaptures can get excessive in size.
# They also could contain extremely sensitive data
@@ -73,6 +72,4 @@ crashlytics-build.properties
/[Aa]ssets/[Ss]treamingAssets/aa.meta
/[Aa]ssets/[Ss]treamingAssets/aa/*
.DS_Store
/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json
CodeCoverage/
.DS_Store

View File

@@ -1,137 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &7141392721760992647
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7141392721760992646}
- component: {fileID: 7141392721760992644}
- component: {fileID: 2518831828376613321}
m_Layer: 5
m_Name: Axes Tick Marker
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7141392721760992646
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7141392721760992647}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.5}
m_AnchorMax: {x: 0, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 50, y: 50}
m_Pivot: {x: 0, y: 0}
--- !u!222 &7141392721760992644
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7141392721760992647}
m_CullTransparentMesh: 1
--- !u!114 &2518831828376613321
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7141392721760992647}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: 0
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4279242768
m_fontColor: {r: 0.0627451, g: 0.0627451, b: 0.0627451, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 36
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 36
m_fontStyle: 0
m_HorizontalAlignment: 4
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 0
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 9d96609216a825843b33f6af9cdfa29b
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -343,12 +343,6 @@ MonoBehaviour:
button: {fileID: -2577348215772602702}
courseProgress:
entries: []
courseIndex: 0
progress: -1
completedLearnables: 0
inUseLearnables: 0
totalLearnables: 0
learnables: []
courseList: {fileID: 11400000, guid: a7ab583094b7897468bbca9243717608, type: 2}
thumbnail: {fileID: 5101881939775039227}
title: {fileID: 5101881939882359064}
@@ -497,15 +491,15 @@ MonoBehaviour:
m_Calls: []
m_text: <Minigame title>
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
m_sharedMaterial: {fileID: -2577534979213189211, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4284235525
m_fontColor: {r: 0.019607844, g: 0.24705882, b: 0.36078432, a: 1}
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
@@ -623,7 +617,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.9490196, g: 0.49803922, b: 0.047058824, a: 1}
m_Color: {r: 0, g: 0.7529412, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1

View File

@@ -33,8 +33,8 @@ RectTransform:
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0.5}
m_AnchorMax: {x: 1, y: 0.5}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 50, y: 50}
m_Pivot: {x: 0, y: 0}

View File

@@ -1,515 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &758255480231791509
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 758255480231791508}
- component: {fileID: 758255480231791506}
- component: {fileID: 758255480231791507}
- component: {fileID: 8445851122681183268}
m_Layer: 0
m_Name: LearnableProgressCard
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &758255480231791508
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255480231791509}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 758255481422566555}
- {fileID: 758255481061489079}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &758255480231791506
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255480231791509}
m_CullTransparentMesh: 1
--- !u!114 &758255480231791507
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255480231791509}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 1
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &8445851122681183268
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255480231791509}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7835fc450a6bbf24d95f0a19491fb8c1, type: 3}
m_Name:
m_EditorClassIdentifier:
progress:
entries: []
index: 0
inUse: 0
name:
progress: 0
course: {fileID: 0}
thumbnail: {fileID: 758255481422566554}
stars:
- {fileID: 758255481653936988}
- {fileID: 758255481997431046}
- {fileID: 758255482122419822}
--- !u!1 &758255481061489032
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 758255481061489079}
- component: {fileID: 758255481061489077}
- component: {fileID: 758255481061489078}
- component: {fileID: 758255481061489076}
m_Layer: 0
m_Name: Status
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &758255481061489079
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481061489032}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 758255481653936989}
- {fileID: 758255481997431047}
- {fileID: 758255482122419823}
m_Father: {fileID: 758255480231791508}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 0}
m_AnchoredPosition: {x: 0, y: -32}
m_SizeDelta: {x: -20, y: 45}
m_Pivot: {x: 0.5, y: 0}
--- !u!222 &758255481061489077
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481061489032}
m_CullTransparentMesh: 1
--- !u!114 &758255481061489078
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481061489032}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.5803922, g: 0.58431375, b: 0.6, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 1
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &758255481061489076
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481061489032}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Padding:
m_Left: 0
m_Right: 0
m_Top: 0
m_Bottom: 0
m_ChildAlignment: 4
m_Spacing: 0
m_ChildForceExpandWidth: 1
m_ChildForceExpandHeight: 1
m_ChildControlWidth: 1
m_ChildControlHeight: 0
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!1 &758255481422566556
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 758255481422566555}
- component: {fileID: 758255481422566553}
- component: {fileID: 758255481422566554}
m_Layer: 0
m_Name: Image
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &758255481422566555
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481422566556}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 758255480231791508}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &758255481422566553
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481422566556}
m_CullTransparentMesh: 1
--- !u!114 &758255481422566554
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481422566556}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 5e3c345e006acf74791d272061159b89, type: 3}
m_Type: 0
m_PreserveAspect: 1
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &758255481653936990
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 758255481653936989}
- component: {fileID: 758255481653936987}
- component: {fileID: 758255481653936988}
m_Layer: 0
m_Name: Image
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &758255481653936989
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481653936990}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 758255481061489079}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 60}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &758255481653936987
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481653936990}
m_CullTransparentMesh: 1
--- !u!114 &758255481653936988
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481653936990}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: -2086278073, guid: 4d6d852f751f20046ae733db5bdb1af1, type: 3}
m_Type: 0
m_PreserveAspect: 1
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &758255481997431064
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 758255481997431047}
- component: {fileID: 758255481997431045}
- component: {fileID: 758255481997431046}
m_Layer: 0
m_Name: Image (1)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &758255481997431047
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481997431064}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 758255481061489079}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 60}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &758255481997431045
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481997431064}
m_CullTransparentMesh: 1
--- !u!114 &758255481997431046
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255481997431064}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: -2086278073, guid: 4d6d852f751f20046ae733db5bdb1af1, type: 3}
m_Type: 0
m_PreserveAspect: 1
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &758255482122419808
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 758255482122419823}
- component: {fileID: 758255482122419821}
- component: {fileID: 758255482122419822}
m_Layer: 0
m_Name: Image (2)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &758255482122419823
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255482122419808}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 758255481061489079}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 60}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &758255482122419821
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255482122419808}
m_CullTransparentMesh: 1
--- !u!114 &758255482122419822
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 758255482122419808}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: -2086278073, guid: 4d6d852f751f20046ae733db5bdb1af1, type: 3}
m_Type: 0
m_PreserveAspect: 1
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1

View File

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

View File

@@ -68,15 +68,15 @@ MonoBehaviour:
m_Calls: []
m_text: 'Topscore: 123456789'
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
m_sharedMaterial: {fileID: -2577534979213189211, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4284235525
m_fontColor: {r: 0.019607844, g: 0.24705882, b: 0.36078432, a: 1}
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
@@ -275,9 +275,6 @@ MonoBehaviour:
button: {fileID: 5555894415693752970}
minigameProgress:
entries: []
minigameIndex: 0
latestScores: []
highestScores: []
minigameList: {fileID: 11400000, guid: 51453f9b41bc72f468ba3e67ab622f8f, type: 2}
thumbnail: {fileID: 5101881939775039227}
title: {fileID: 5101881939882359064}
@@ -426,15 +423,15 @@ MonoBehaviour:
m_Calls: []
m_text: <Minigame title>
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
m_sharedMaterial: {fileID: -2577534979213189211, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4284235525
m_fontColor: {r: 0.019607844, g: 0.24705882, b: 0.36078432, a: 1}
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:

View File

@@ -96,7 +96,7 @@ MonoBehaviour:
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 0
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
@@ -277,15 +277,15 @@ MonoBehaviour:
m_Calls: []
m_text: Gebruiker
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
m_sharedMaterial: {fileID: -2577534979213189211, guid: 1baf2eae62f542f4585aaf3c9c3e229a, type: 2}
m_fontAsset: {fileID: 11400000, guid: 3602bedf0ebe5b64596873f09eddf57b, type: 2}
m_sharedMaterial: {fileID: -1030930060397404263, guid: 3602bedf0ebe5b64596873f09eddf57b, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4284235525
m_fontColor: {r: 0.019607844, g: 0.24705882, b: 0.36078432, a: 1}
rgba: 4281479730
m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
@@ -481,6 +481,13 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 172fcacd3bd90f442a6b94f0ff43a76a, type: 3}
m_Name:
m_EditorClassIdentifier:
userList: {fileID: 11400000, guid: 072bec636a40f7e4e93b0ac624a3bda2, type: 2}
user:
username:
avatar: {fileID: 0}
playtime: 0
courses: []
minigames: []
button: {fileID: 7566391564300576381}
avatar: {fileID: 5164936991071620901}
username: {fileID: 7566391564272109414}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,42 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 81765ea55baf15d45b01b02187b02429, type: 3}
m_Name: UserAvatarList
m_EditorClassIdentifier:
avatars:
- {fileID: 21300000, guid: 6feaaea4b64633f49b4538bfd4b3755c, type: 3}
- {fileID: 21300000, guid: 399cc241fc79bd74db314f146e7fb6b9, type: 3}
- {fileID: 21300000, guid: 4654657a2ebea444898fa6eeaefcd18d, type: 3}
- {fileID: 21300000, guid: 0cc198f1cde659246a199b30459720b1, type: 3}
- {fileID: 21300000, guid: 7f105a09a3d164547925ee1bdfa595ca, type: 3}
- {fileID: 21300000, guid: 313c22e5834595645989d609fe9d8853, type: 3}
- {fileID: 21300000, guid: e5f3d99cdf5298d4f86d42dd019a6bad, type: 3}
- {fileID: 21300000, guid: b67b99d98d1ceb1489743bcd78b9ab70, type: 3}
- {fileID: 21300000, guid: e4af402f37099cd4195d7d2654519744, type: 3}
- {fileID: 21300000, guid: 73f4e028d9efb644aa23538a749667c5, type: 3}
- {fileID: 21300000, guid: 61e56570163833e448037bc353ada0ac, type: 3}
- {fileID: 21300000, guid: 8e69dfd19237abb4f98eb11e74153109, type: 3}
- {fileID: 21300000, guid: bc11ff9d6cc35de45ab58f39f13d7142, type: 3}
- {fileID: 21300000, guid: f989719a5c45c7a4183b2bc12c1c4905, type: 3}
- {fileID: 21300000, guid: 1392922567cd59d4fb0beceea3f5917a, type: 3}
- {fileID: 21300000, guid: 3c314ae9e10eafb49b57c98c9e779bd8, type: 3}
- {fileID: 21300000, guid: 33509e453b5093e43a148a668a961c56, type: 3}
- {fileID: 21300000, guid: 39ac3b86729423846be1fbd56b8d92d6, type: 3}
- {fileID: 21300000, guid: 1118d67f50622cc4ab02aa23c6dc1fd4, type: 3}
- {fileID: 21300000, guid: e519f0f7b00e6834187963a0131cae52, type: 3}
- {fileID: 21300000, guid: eefb367ff44256d43a14cde2c3924321, type: 3}
- {fileID: 21300000, guid: 83d6525e4efa4954091e08095349f45a, type: 3}
- {fileID: 21300000, guid: db31bca6363270441ab54421f55c1263, type: 3}
- {fileID: 21300000, guid: 9d5771baa6ea6e041b066135d6798e1c, type: 3}
- {fileID: 21300000, guid: 2b01165a5836ab14593d7a5862bd6793, type: 3}
- {fileID: 21300000, guid: 8c304fe460423214ea0bb6ebc235ed2d, type: 3}
- {fileID: 21300000, guid: b203b4e5f8568ff46b2277ce6d61017a, type: 3}

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 017ec1af3b6cc4d4ab2b506911a4edad
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3f3d6d68c3c3db64e91cf5ec9537ccda, type: 3}
m_Name: UserList
m_EditorClassIdentifier:
storedUserList:
currentUserIndex: 0
storedUsers: []

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 072bec636a40f7e4e93b0ac624a3bda2
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -3,7 +3,6 @@
"rootNamespace": "",
"references": [
"GUID:6055be8ebefd69e48b49212b09b47b2f",
"GUID:e83ddf9a537a96b4a804a16bb7872ec1",
"GUID:7f2d0ee6dd21e1d4eb25b71b7a749d25"
],
"includePlatforms": [],

View File

@@ -22,6 +22,11 @@ public class ChangeUserScreen : MonoBehaviour
/// </summary>
public GameObject error;
/// <summary>
/// Reference to the user list
/// </summary>
public UserList userList;
/// <summary>
/// Index of the current selected user in the UserList
/// </summary>
@@ -37,7 +42,6 @@ public class ChangeUserScreen : MonoBehaviour
/// </summary>
void Start()
{
PersistentDataController.GetInstance().Load();
error.SetActive(false);
DisplayUsers();
}
@@ -48,10 +52,12 @@ public class ChangeUserScreen : MonoBehaviour
private void DisplayUsers()
{
foreach (Transform child in usersContainer)
{
Destroy(child.gameObject);
}
List<User> users = UserList.GetUsers();
currentUserIndex = UserList.IndexOf(UserList.GetCurrentUser().GetUsername());
List<User> users = userList.GetUsers();
currentUserIndex = userList.GetCurrentUserIndex();
for (int i = 0; i < users.Count; i++)
{
User user = users[i];
@@ -72,7 +78,7 @@ public class ChangeUserScreen : MonoBehaviour
Image background = instance.GetComponent<Image>();
userBackgrounds.Add(background);
// Set background color
background.color = i == currentUserIndex ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
background.color = i == currentUserIndex ? Color.blue : Color.gray;
}
}
@@ -82,9 +88,9 @@ public class ChangeUserScreen : MonoBehaviour
/// <param name="index">Index to the user in the <c>this.userBackgrounds</c> list</param>
private void UpdateSelection(int index)
{
userBackgrounds[currentUserIndex].color = new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
userBackgrounds[currentUserIndex].color = Color.gray;
currentUserIndex = index;
userBackgrounds[currentUserIndex].color = new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f);
userBackgrounds[currentUserIndex].color = Color.blue;
}
/// <summary>
@@ -92,7 +98,8 @@ public class ChangeUserScreen : MonoBehaviour
/// </summary>
public void IChooseYou()
{
UserList.ChangeCurrentUser(currentUserIndex);
userList.ChangeCurrentUser(currentUserIndex);
userList.Save();
SystemController.GetInstance().BackToPreviousScene();
}

View File

@@ -21,10 +21,10 @@ public class CourseProgressCard : MonoBehaviour
/// <summary>
/// Reference to the progress so we can display a progress bar
/// </summary>
public PersistentDataController.SavedCourseProgress courseProgress;
public Progress courseProgress;
/// <summary>
/// Reference to the list of minigameCards so we can query the correct course
/// Reference to the list of courses so we can query the correct course
/// </summary>
public CourseList courseList;
@@ -48,11 +48,11 @@ public class CourseProgressCard : MonoBehaviour
/// </summary>
void Start()
{
Course course = courseList.GetCourseByIndex(courseProgress.courseIndex);
Course course = courseList.GetCourseByIndex(courseProgress.Get<CourseIndex>("courseIndex"));
thumbnail.sprite = course.thumbnail;
title.text = course.title;
progressBar.value = courseProgress.progress;
progressBar.value = courseProgress.Get<float>("courseProgress");
button.onClick.AddListener(selectActivity);
}
}

View File

@@ -1,40 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// Class to handle learnable progress card display
/// </summary>
public class LearnableProgressCard : MonoBehaviour
{
/// <summary>
/// Reference to the progress so we can display a progress bar
/// </summary>
public PersistentDataController.SavedLearnableProgress progress;
/// <summary>
/// Reference to the list of minigameCards so we can query the correct course
/// </summary>
public Learnable learnable;
/// <summary>
/// UI reference to the thumbnail of the course
/// </summary>
public Image thumbnail;
/// <summary>
/// UI refeerence to the title of the course
/// </summary>
public List<Image> stars;
/// <summary>
/// Start is called before the first frame update
/// </summary>
void Start()
{
thumbnail.sprite = learnable.image;
var starRewards = new float[] { 1.0f, 2.5f, 4.0f, };
for (int i = 0; i < 3; i++)
stars[i].color = starRewards[i] < progress.progress ? Color.white : Color.black;
}
}

View File

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

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
@@ -23,7 +22,7 @@ public class MinigameProgressCard : MonoBehaviour
/// <summary>
/// Reference to the minigame progress
/// </summary>
public PersistentDataController.SavedMinigameProgress minigameProgress;
public Progress minigameProgress;
/// <summary>
/// Reference to the minigame list
@@ -50,15 +49,13 @@ public class MinigameProgressCard : MonoBehaviour
/// </summary>
void Start()
{
Minigame minigame = minigameList.GetMinigameByIndex(minigameProgress.minigameIndex);
Minigame minigame = minigameList.GetMinigameByIndex(minigameProgress.Get<MinigameIndex>("minigameIndex"));
thumbnail.sprite = minigame.thumbnail;
title.text = minigame.title;
List<Score> highscores = minigameProgress.Get<List<Score>>("highestScores");
int score = highscores.Count > 0 ? highscores[0].scoreValue : 0;
highscore.text = $"Topscore: {score}";
button.onClick.AddListener(selectActivity);
List<Score> highscores = minigameProgress.highestScores;
if (0 < highscores.Count)
highscore.text = $"TOPSCORE: {highscores.Max((s) => s.scoreValue)}";
else
highscore.text = "(NOG) GEEN TOPSCORE";
}
}

View File

@@ -1,130 +0,0 @@
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// Class to handle course list progress display
/// </summary>
public class PanelCourseProgress : MonoBehaviour
{
/// <summary>
/// Reference to the current user
/// </summary>
private User user;
/// <summary>
/// Reference to the courses list
/// </summary>
public CourseList courseList;
/// <summary>
/// Prefab of a course card
/// </summary>
public GameObject courseCardPrefab;
/// <summary>
/// UI reference to the container holding all course cards
/// </summary>
public Transform coursesContainer;
/// <summary>
/// UI reference to the course info panel
/// </summary>
public GameObject courseInfo;
/// <summary>
/// UI reference to the message that displays when no course progress is present
/// </summary>
public GameObject emptyCourses;
/// <summary>
/// Reference to the title on the info panel
/// </summary>
public TMP_Text courseTitle;
/// <summary>
/// Reference to the learnable card prefab
/// </summary>
public GameObject learnableCardPrefab;
/// <summary>
/// Reference to the container for holding the learnable cards
/// </summary>
public Transform learnablesContainer;
/// <summary>
/// Reference to the course progress bar on the info panel
/// </summary>
public SlicedSlider progressBar;
/// <summary>
/// Current selected course
/// </summary>
private int selectedCourse = 0;
/// <summary>
/// List of course backgrounds and indices
/// </summary>
private List<Tuple<Image, CourseIndex>> courseCards = new List<Tuple<Image, CourseIndex>>();
/// <summary>
/// Start is called before the first frame update
/// </summary>
void Start()
{
PersistentDataController.GetInstance().Load();
user = UserList.GetCurrentUser();
var courses = user.GetCourses();
courseInfo.SetActive(0 < courses.Count);
emptyCourses.SetActive(courses.Count <= 0);
int i = 0;
foreach (var courseProgress in courses)
{
// Create instance of prefab
GameObject instance = GameObject.Instantiate(courseCardPrefab, coursesContainer);
int j = i++;
// Initialize card
CourseProgressCard cpc = instance.GetComponent<CourseProgressCard>();
cpc.courseProgress = courseProgress;
cpc.selectActivity = () => UpdateSelection(j);
// Store reference to background so we can apply fancy coloring
Image background = instance.GetComponent<Image>();
background.color = new Color(159 / 255f, 231 / 255f, 245 / 255f, 120/255f);
this.courseCards.Add(Tuple.Create(background, courseProgress.courseIndex));
}
if (0 < courses.Count)
UpdateSelection(0);
}
/// <summary>
/// Update the current selected course
/// </summary>
/// <param name="newCourse">Index to the new course</param>
private void UpdateSelection(int newCourse)
{
courseCards[selectedCourse].Item1.color = new Color(159 / 255f, 231 / 255f, 245 / 255f, 120 / 255f);
selectedCourse = newCourse;
courseCards[selectedCourse].Item1.color = new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f);
var progress = user.GetCourseProgress(courseCards[selectedCourse].Item2);
var course = courseList.GetCourseByIndex(progress.courseIndex);
courseTitle.text = course.title;
progressBar.fillAmount = progress.progress;
foreach (Transform child in learnablesContainer)
Destroy(child.gameObject);
for (int i = 0; i < course.theme.learnables.Count; i++)
{
GameObject instance = GameObject.Instantiate(learnableCardPrefab, learnablesContainer);
var script = instance.GetComponent<LearnableProgressCard>();
script.learnable = course.theme.learnables[i];
script.progress = progress.learnables[i];
}
}
}

View File

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

View File

@@ -1,127 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// Class to handle minigame list progress display
/// </summary>
public class PanelMinigameProgress : MonoBehaviour
{
/// <summary>
/// Reference to the current user
/// </summary>
private User user;
/// <summary>
/// Reference to the minigames list
/// </summary>
public MinigameList minigameList;
/// <summary>
/// Prefab of a minigame card
/// </summary>
public GameObject minigameCardPrefab;
/// <summary>
/// UI reference to the container holding all the minigame cards
/// </summary>
public Transform minigamesContainer;
/// <summary>
/// UI reference to the minigame info panel
/// </summary>
public GameObject minigameInfo;
/// <summary>
/// UI reference to the message that displays when no minigame progress is present
/// </summary>
public GameObject emptyMinigames;
/// <summary>
/// UI reference to the plot
/// </summary>
public ProgressGraph progressGraph;
/// <summary>
/// Reference to the title of the minigame of the info panel
/// </summary>
public TMP_Text minigameTitle;
/// <summary>
/// Reference to the text that will display when an empty minigame progress object is selected
/// </summary>
public GameObject emptyHighscore;
/// <summary>
/// Current selected course
/// </summary>
private int selectedMinigame = 0;
/// <summary>
/// List of course backgrounds and indices
/// </summary>
private List<Tuple<Image, MinigameIndex>> minigameCards = new List<Tuple<Image, MinigameIndex>>();
/// <summary>
/// Start is called before the first frame update
/// </summary>
void Start()
{
PersistentDataController.GetInstance().Load();
user = UserList.GetCurrentUser();
var minigames = user.GetMinigames();
minigameInfo.SetActive(minigames.Count > 0);
emptyMinigames.SetActive(minigames.Count <= 0);
int i = 0;
foreach (var minigameProgress in minigames)
{
// Create instance of prefab
GameObject instance = GameObject.Instantiate(minigameCardPrefab, minigamesContainer);
int j = i++;
// Initialize card
MinigameProgressCard mpc = instance.GetComponent<MinigameProgressCard>();
mpc.minigameProgress = minigameProgress;
mpc.selectActivity = () => UpdateSelection(j);
// Store reference to background so we can apply fancy coloring
Image background = instance.GetComponent<Image>();
background.color = new Color(159 / 255f, 231 / 255f, 245 / 255f, 120 / 255f);
minigameCards.Add(Tuple.Create(background, minigameProgress.minigameIndex));
}
if (0 < minigames.Count)
UpdateSelection(0);
}
/// <summary>
/// Update the current selected course
/// </summary>
/// <param name="newMinigame">Index to the new course</param>
private void UpdateSelection(int newMinigame)
{
minigameCards[selectedMinigame].Item1.color = new Color(159 / 255f, 231 / 255f, 245 / 255f, 120 / 255f);
selectedMinigame = newMinigame;
minigameCards[selectedMinigame].Item1.color = new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f);
var progress = user.GetMinigameProgress(minigameCards[selectedMinigame].Item2);
minigameTitle.text = minigameList.GetMinigameByIndex(progress.minigameIndex).title;
List<Score> latestScores = progress.latestScores;
List<Score> highestScores = progress.highestScores;
if (0 < highestScores.Count)
{
emptyHighscore.SetActive(false);
progressGraph.gameObject.SetActive(true);
progressGraph.Plot(latestScores.ConvertAll<double>((s) => (double)s.scoreValue), highestScores.Max((s) => s.scoreValue));
}
else
{
emptyHighscore.SetActive(true);
progressGraph.gameObject.SetActive(false);
}
}
}

View File

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

View File

@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;
/// <summary>
/// A class for holding all progress belonging to a user
/// </summary>
[Serializable]
public class Progress
{
/// <summary>
/// A helper class for handling the stored progress
/// </summary>
[Serializable]
protected class DataEntry
{
/// <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> bytes = new List<byte>();
public DataEntry(string key, byte[] data)
{
this.key = key;
this.bytes = new List<byte>(data);
}
}
/// <summary>
/// Entries in the <c>Progress</c> object
/// </summary>
[SerializeField]
private List<DataEntry> entries = new List<DataEntry>();
/// <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 AddOrUpdate<T>(string key, T data)
{
if (data == null)
return false;
DataEntry 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.bytes.Clear();
entry.bytes.AddRange(ms.ToArray());
}
else
{
entries.Add(new DataEntry(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>
public T Get<T>(string key)
{
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
// Find the correct key
foreach (DataEntry entry in entries)
{
if (entry.key == key)
{
// Hacky serialization stuff
byte[] data = entry.bytes.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();
}
}

View File

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

View File

@@ -1,263 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// Class to handle and draw a nice line graph to a Texture2D
/// </summary>
public class ProgressGraph : MonoBehaviour
{
/// <summary>
/// UI reference to the plot
/// </summary>
public RawImage progressGraph;
/// <summary>
/// Prefab of the highscore marker to display on the graph
/// </summary>
public GameObject highscoreMarker;
/// <summary>
/// Prefab of the axes tick marker to display on the graph
/// </summary>
public GameObject axesTickMarker;
/// <summary>
/// Color of the graph line
/// </summary>
public Color lineColor;
/// <summary>
/// Bckground color
/// </summary>
public Color backgroundColor;
/// <summary>
/// Color of the text and axes grid
/// </summary>
public Color textColor;
/// <summary>
/// Color of the highscore line
/// </summary>
public Color highscoreColor;
/// <summary>
/// Left and right padding of the graph
/// </summary>
private const int GRAPH_PADDING_X_PX = 50;
/// <summary>
/// Top and bottom padding of the graph
/// </summary>
private const int GRAPH_PADDING_Y_PX = 50;
/// <summary>
/// Radius of the point on the graph
/// </summary>
private const int GRAPH_POINT_RADIUS = 10;
/// <summary>
/// Size of the line on the graph
/// </summary>
private const int GRAPH_LINE_SIZE = 4;
/// <summary>
/// Plot points and a highscore on the graph
/// </summary>
/// <param name="scores">List of score values to plot</param>
/// <param name="highscore">Highscore value (this will be plotted in a fancy color)</param>
public void Plot(List<double> scores, double highscore)
{
// Remove previous marker(s)
foreach (Transform child in progressGraph.gameObject.transform)
Destroy(child.gameObject);
// Get texture reference
Texture2D tex = progressGraph.texture as Texture2D;
RectTransform rect = progressGraph.gameObject.transform as RectTransform;
if (tex == null)
{
tex = new Texture2D(
width: (int)rect.sizeDelta.x,
height: (int)rect.sizeDelta.y,
textureFormat: TextureFormat.ARGB32,
mipCount: 3,
linear: true
);
}
tex.filterMode = FilterMode.Point;
FillTexture(tex, backgroundColor);
// calculate positions and offsets
int x0 = GRAPH_PADDING_X_PX, x1 = tex.width - GRAPH_PADDING_X_PX;
int y0 = GRAPH_PADDING_Y_PX, y1 = tex.height - GRAPH_PADDING_Y_PX;
double min = scores.Min();
double max = scores.Max();
List<Tuple<int, int>> points = new List<Tuple<int, int>>();
for (int i = 0; i < scores.Count; i++)
{
int _x = x0 + (scores.Count > 1 ? i * ((x1 - x0) / (scores.Count - 1)) : (x1 - x0) / 2);
int _y = y0 + (int)((y1 - y0) * (min != max ? (scores[i] - min) / (max - min) : 0.5));
points.Add(Tuple.Create(_x, _y));
}
// Calculate scaling
const int NUMBER_OF_AXES = 5;
double spacing = 0.0;
if (min == max)
{
spacing = CalculateSpacing(highscore, NUMBER_OF_AXES);
max = highscore + 2 * spacing;
min = highscore - 2 * spacing;
}
spacing = CalculateSpacing(max - min, NUMBER_OF_AXES);
double begin = spacing * Math.Round(min / spacing);
// Draw axes
double pixels_per_unit = (y1 - y0) / (max - min);
double Y = begin;
int y = y0 + (int)(pixels_per_unit * (Y - min));
int total = 0;
do
{
if (y0 <= y)
{
DrawLine(tex, x0, y, x1, y, 2, textColor);
GameObject tick = GameObject.Instantiate(axesTickMarker, rect);
tick.GetComponent<RectTransform>().localPosition = new Vector3(-10 - rect.sizeDelta.y * rect.pivot.x, y - 25 - rect.sizeDelta.y * rect.pivot.y, 0);
TMP_Text txt = tick.GetComponent<TMP_Text>();
txt.text = $"{Y}";
txt.color = textColor;
}
total += 1;
Y += spacing;
y = y0 + (int)(pixels_per_unit * (Y - min));
// Fail save
if (2 * NUMBER_OF_AXES < total)
break;
} while (y <= y1);
// Draw highscore
if (min <= highscore && highscore <= max)
{
y = y0 + (int)(pixels_per_unit * (highscore - min));
DrawLine(tex, x0, y, x1, y, GRAPH_LINE_SIZE, highscoreColor);
GameObject marker = GameObject.Instantiate(highscoreMarker, rect);
marker.GetComponent<RectTransform>().localPosition = new Vector3(tex.width - 50 - rect.sizeDelta.x * rect.pivot.x, y - 25 - rect.sizeDelta.y * rect.pivot.y, 0);
}
// Draw points
for (int i = 0; i < points.Count; i++)
{
Tuple<int, int> p = points[i];
if (0 < i)
{
Tuple<int, int> q = points[i - 1];
DrawLine(tex, p.Item1, p.Item2, q.Item1, q.Item2, GRAPH_LINE_SIZE, lineColor);
}
DrawPoint(tex, p.Item1, p.Item2, GRAPH_POINT_RADIUS, lineColor);
}
// Apply to graph GameObject
tex.Apply();
progressGraph.texture = tex;
}
/// <summary>
/// Calculate nice spacing
/// </summary>
/// <param name="mu">Either `max - min` if max != min, otherwise `highscore`</param>
/// <param name="numberOfAxes">Number of horizontal axes grid lines shown on the graph</param>
/// <returns>Spacing between each axes grid line</returns>
private double CalculateSpacing(double mu, int numberOfAxes)
{
if (mu == 0)
return 1.0;
double[] otherSpacings = { 0.5, 1.0, 2.0, 5.0 };
int mag = (int)Math.Floor(Math.Log10(Math.Abs(mu)));
int MAG = (int)Math.Pow(10, mag);
double spacing = MAG;
foreach (double o in otherSpacings)
{
if (Math.Abs(mu - numberOfAxes * spacing) <= Math.Abs(mu - numberOfAxes * o * MAG))
continue;
spacing = o * MAG;
}
return spacing;
}
/// <summary>
/// Set all the pixels of a texture to a given color
/// </summary>
/// <param name="tex">Texture to fill</param>
/// <param name="color">Color to set the texture to</param>
private void FillTexture(Texture2D tex, Color color)
{
for (int y = 0; y < tex.height; y++)
for (int x = 0; x < tex.width; x++)
tex.SetPixel(x, y, color);
}
/// <summary>
/// Draw a point to a texture
/// </summary>
/// <param name="tex">Texture2D to plot point on</param>
/// <param name="xc">Center x-pos</param>
/// <param name="yc">Center y-pos</param>
/// <param name="r">Radius (aka width and height)</param>
/// <param name="color">Color of the point</param>
private void DrawPoint(Texture2D tex, int xc, int yc, int r, Color color)
{
for (int y = yc - r; y < yc + r; y++)
for (int x = xc - r; x < xc + r; x++)
tex.SetPixel(x, y, color);
}
/// <summary>
/// Draw a line to a texture
/// </summary>
/// <param name="tex">Texture2D to plot line on</param>
/// <param name="x0">Starting x-pos</param>
/// <param name="y0">Strating y-pos</param>
/// <param name="x1">Ending x-pos</param>
/// <param name="y1">Ending y-pos</param>
/// <param name="size">Size of the line (width)</param>
/// <param name="color">Color of the line</param>
private void DrawLine(Texture2D tex, int x0, int y0, int x1, int y1, int size, Color color)
{
int w = x1 - x0;
int h = y1 - y0;
int length = Mathf.Abs(x1 - x0);
if (Mathf.Abs(y1 - y0) > length)
length = Mathf.Abs(h);
double dx = w / (double)length;
double dy = h / (double)length;
double x = x0;
double y = y0;
double r = size / 2;
for (int i = 0; i <= length; i++)
{
for (int j = (int)(y - r); j < y + r; j++)
for (int k = (int)(x - r); k < x + r; k++)
tex.SetPixel(k, j, color);
x += dx;
y += dy;
}
}
}

View File

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

View File

@@ -0,0 +1,104 @@
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>
/// 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.sceneStack.Push(SceneManager.GetActiveScene().buildIndex);
}
return instance;
}
/// <summary>
/// Load the scene and push on the stack
/// </summary>
/// <param name="scenePath">Path of the scene</param>
public void LoadNextScene(string scenePath)
{
LoadNextScene(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)
{
sceneStack.Push(sceneIndex);
SceneManager.LoadScene(sceneIndex);
}
/// <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(SceneUtility.GetBuildIndexByScenePath(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)
{
sceneStack.Pop();
LoadNextScene(sceneIndex);
}
/// <summary>
/// Go back to the previous scene and unload the current scene
/// </summary>
public void BackToPreviousScene()
{
sceneStack.Pop();
if (sceneStack.Count > 0) SceneManager.LoadScene(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(SceneUtility.GetBuildIndexByScenePath(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)
{
while (0 < sceneStack.Count && sceneStack.Peek() != sceneIndex) sceneStack.Pop();
if (sceneStack.Count > 0) SceneManager.LoadScene(sceneStack.Peek());
else Application.Quit();
}
}

View File

@@ -2,129 +2,92 @@ using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using static PersistentDataController;
/// <summary>
/// A class holding all information of a user
/// </summary>
[Serializable]
public class User
{
/// <summary>
/// Reference to the user stored data record
/// User nickname
/// </summary>
private SavedUserData storedUserData;
public string username;
/// <summary>
/// Constructor
/// The avatar of the user
/// </summary>
/// <param name="data">Reference to the user stored data record</param>
public User(SavedUserData data)
{
this.storedUserData = data;
}
public Sprite avatar;
/// <summary>
/// Get the username
/// The total playtime of the user
/// </summary>
public string GetUsername() { return storedUserData.username; }
/// <remarks>TODO: needs to be implemented</remarks>
public double playtime;
/// <summary>
/// Get the total playtime
/// List of courses a user started/completed
/// </summary>
public double GetPlaytime() { return storedUserData.playtime; }
[SerializeField]
public List<Progress> courses = new List<Progress>();
/// <summary>
/// Get the avatar
/// List of minigames a user played
/// </summary>
public Sprite GetAvatar() { return UserList.AVATARS[storedUserData.avatarIndex]; }
[SerializeField]
public List<Progress> minigames = new List<Progress>();
/// <summary>
/// Get a list of all recently started minigameCards
/// Get a list of all recently started courses
/// </summary>
/// <returns>A <c>List</c> of <c>Tuples</c>, containing the <c>CourseIndex</c>
/// and a <c>float</c> holding the progress (value between 0 and 1) of the user in this course</returns>
public List<Tuple<CourseIndex, float>> GetRecentCourses()
{
// TODO: return better results (for now only return all minigameCards)
// TODO: return better results (for now only return all courses)
List<Tuple<CourseIndex, float>> recentCourses = new List<Tuple<CourseIndex, float>>();
foreach (var courseProgress in storedUserData.courses)
foreach (Progress courseProgress in courses)
{
CourseIndex idx = courseProgress.courseIndex;
float progress = courseProgress.progress;
CourseIndex idx = courseProgress.Get<CourseIndex>("courseIndex");
float progress = courseProgress.Get<float>("courseProgress");
recentCourses.Add(Tuple.Create<CourseIndex, float>(idx, progress));
}
return recentCourses.Take(3).ToList();
}
/// <summary>
/// Get a list of all recommended minigameCards
/// Get a list of all recommended courses
/// </summary>
/// <returns>A <c>List</c> of <c>Tuples</c>, containing the <c>CourseIndex</c>
/// and a <c>float</c> holding the progress (value between 0 and 1) of the user in this course</returns>
public List<Tuple<CourseIndex, float>> GetRecommendedCourses()
{
List<Tuple<CourseIndex, float>> recommenedCourses = new List<Tuple<CourseIndex, float>>();
if (storedUserData.courses.Count == 0)
if (courses.Count == 0)
{
recommenedCourses.Add(Tuple.Create<CourseIndex, float>(CourseIndex.FINGERSPELLING, 0.0f));
}
else
{
// TODO: return better results (for now only return all minigameCards)
foreach (var courseProgress in storedUserData.courses)
// TODO: return better results (for now only return all courses)
foreach (Progress courseProgress in courses)
{
CourseIndex idx = courseProgress.courseIndex;
float progress = courseProgress.progress;
CourseIndex idx = courseProgress.Get<CourseIndex>("courseIndex");
float progress = courseProgress.Get<float>("courseProgress");
recommenedCourses.Add(Tuple.Create<CourseIndex, float>(idx, progress));
}
}
return recommenedCourses.Take(3).ToList();
}
/// <summary>
/// Get the progress of all minigameCards the user did
/// </summary>
/// <returns></returns>
public List<SavedCourseProgress> GetCourses()
{
return storedUserData.courses;
}
/// <summary>
/// Get the progress of a certain course
/// </summary>
/// <param name="courseIndex">Index of course</param>
/// <returns><c>Progress</c> belonging to the <c>courseIndex</c>, <c>null</c> if course was not found</returns>
public SavedCourseProgress GetCourseProgress(CourseIndex courseIndex)
public Progress GetCourseProgress(CourseIndex courseIndex)
{
return storedUserData.courses.Find((p) => p.courseIndex == courseIndex);
}
/// <summary>
/// Add new progress of a course
/// </summary>
/// <param name="progress">SavedCourseProgress data record</param>
public void AddCourseProgress(SavedCourseProgress progress)
{
storedUserData.courses.Add(progress);
}
/// <summary>
/// Reset progress of a course
/// </summary>
/// <param name="courseIndex">Index of course</param>
public void ResetCourseProgress(CourseIndex courseIndex)
{
storedUserData.courses.RemoveAll((p) => p.courseIndex == courseIndex);
}
/// <summary>
/// Get the progress of all minigames the user did
/// </summary>
/// <returns></returns>
public List<SavedMinigameProgress> GetMinigames()
{
return storedUserData.minigames;
return courses.Find((p) => p.Get<CourseIndex>("courseIndex") == courseIndex);
}
/// <summary>
@@ -132,26 +95,8 @@ public class User
/// </summary>
/// <param name="minigameIndex">Index of the minigame</param>
/// <returns><c>Progress</c> belonging to the <c>minigameIndex</c>, <c>null</c> if minigame was not found</returns>
public SavedMinigameProgress GetMinigameProgress(MinigameIndex minigameIndex)
public Progress GetMinigameProgress(MinigameIndex minigameIndex)
{
return storedUserData.minigames.Find((p) => p.minigameIndex == minigameIndex);
}
/// <summary>
/// Add new progress of a minigame
/// </summary>
/// <param name="progress">SavedMinigameProgress data record</param>
public void AddMinigameProgress(SavedMinigameProgress progress)
{
storedUserData.minigames.Add(progress);
}
/// <summary>
/// Reset progress of a minigame
/// </summary>
/// <param name="minigameIndex">Index of the minigame</param>
public void ResetMinigameProgress(MinigameIndex minigameIndex)
{
storedUserData.minigames.RemoveAll((p) => p.minigameIndex == minigameIndex);
return minigames.Find((p) => p.Get<MinigameIndex>("minigameIndex") == minigameIndex);
}
}

View File

@@ -1,22 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Container to hold a reference to all possible user avatar sprites
/// </summary>
[CreateAssetMenu(menuName = "Create new Scriptable/User Avatar List")]
public class UserAvatarList : ScriptableObject
{
/// <summary>
/// List of avatar sprites
/// </summary>
public List<Sprite> avatars = new List<Sprite>();
/// <summary>
/// Awake is called when the object gets created
/// </summary>
public void Awake()
{
UserList.AVATARS = avatars;
}
}

View File

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

View File

@@ -8,6 +8,11 @@ using UnityEngine.UI;
/// </summary>
public class UserCard : MonoBehaviour
{
/// <summary>
/// Reference to the userlist
/// </summary>
public UserList userList;
/// <summary>
/// User to upload info into this card
/// </summary>
@@ -48,8 +53,8 @@ public class UserCard : MonoBehaviour
/// </summary>
void Start()
{
avatar.sprite = user.GetAvatar();
username.text = user.GetUsername();
avatar.sprite = user.avatar;
username.text = user.username;
button.onClick.AddListener(selectUser);
}
@@ -58,9 +63,10 @@ public class UserCard : MonoBehaviour
/// </summary>
public void DeleteUser()
{
if (UserList.DeleteUser(user.GetUsername()))
if (userList.DeleteUser(user))
{
// User is removed, update and save
userList.Save();
updateUserCardContainer();
}
else

View File

@@ -34,9 +34,20 @@ public class UserCreationScreen : MonoBehaviour
/// </summary>
public GameObject avatarPrefab;
/// <summary>
/// List of all sprites that are supported as avatars
/// </summary>
public List<Sprite> sprites = new List<Sprite>();
/// <summary>
/// Reference to the UserList ScriptableObject
/// </summary>
public UserList users;
/// <summary>
/// Current selected avatar
/// </summary>
[SerializeField]
private int selectedAvatar = 0;
/// <summary>
@@ -44,15 +55,6 @@ public class UserCreationScreen : MonoBehaviour
/// </summary>
private List<Image> avatars = new List<Image>();
/// <summary>
/// Reference to the back button, so we can deactivate it when the user cannot go back (when no user is found at startup)
/// </summary>
public GameObject backButton;
/// <summary>
/// Boolean used to check whether the user can go back to the previous scene
/// </summary>
public static bool canGoBack = true;
/// <summary>
/// Start is called before the first frame update
@@ -60,12 +62,8 @@ public class UserCreationScreen : MonoBehaviour
void Start()
{
errorMessage.SetActive(false);
backButton.SetActive(canGoBack);
// Reset to default value
UserCreationScreen.canGoBack = true;
for (int i = 0; i < UserList.AVATARS.Count; i++)
for (int i = 0; i < sprites.Count; i++)
{
// Create instance of prefab
GameObject instance = GameObject.Instantiate(avatarPrefab, avatarsContainer);
@@ -79,9 +77,9 @@ public class UserCreationScreen : MonoBehaviour
Image background = instance.GetComponent<Image>();
avatars.Add(background);
// Set background color
background.color = selectedAvatar == i ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : Color.gray;
background.color = selectedAvatar == i ? Color.blue : Color.gray;
// Find correct component for setting the sprite
instance.transform.Find("Image").GetComponent<Image>().sprite = UserList.AVATARS[i];
instance.transform.Find("Image").GetComponent<Image>().sprite = sprites[i];
}
}
@@ -93,7 +91,7 @@ public class UserCreationScreen : MonoBehaviour
{
avatars[selectedAvatar].color = Color.gray;
selectedAvatar = newAvatar;
avatars[selectedAvatar].color = new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f);
avatars[selectedAvatar].color = Color.blue;
}
/// <summary>
@@ -115,10 +113,10 @@ public class UserCreationScreen : MonoBehaviour
string username = inputName.text;
if (IsValidUsername(username))
{
if (UserList.GetUserByUsername(username) == null)
if (users.GetUserByUsername(username) == null)
{
// Create a new entry in the UserList ScriptableObject
UserList.AddUser(username, UserList.AVATARS[selectedAvatar]);
users.ChangeCurrentUser(users.CreateAndAddNewUser(username, sprites[selectedAvatar]));
SystemController.GetInstance().BackToPreviousScene();
}
// Warn user that username already exists

View File

@@ -1,33 +1,78 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
/// <summary>
/// Keep track of all users
/// </summary>
public static class UserList
[CreateAssetMenu(menuName = "Create new Scriptable/UserList")]
public class UserList : ScriptableObject
{
/// <summary>
/// List of possible avatar sprites
/// Helper class to enable serialization of the UserList class
/// (<c>ScriptableObject</c>s cannot be serialized)
/// </summary>
public static List<Sprite> AVATARS = new List<Sprite>();
[Serializable]
public class StoredUserList
{
/// <summary>
/// The index of the current/last logged in user in the <c>storedUsers</c> list
/// </summary>
public int currentUserIndex;
/// <summary>
/// A list containing all users (which can be serialized)
/// </summary>
public List<User> storedUsers = new List<User>();
}
/// <summary>
/// Reference to the serializable version of <c>UserList</c>
/// </summary>
[SerializeField]
private StoredUserList storedUserList = new StoredUserList();
/// <summary>
/// Path of the <c>.json</c>-file to store all serialized data
/// </summary>
public static string PATH = null;
/// <summary>
/// OnEnable will make sure the <c>PATH</c>-variable is correctly initialized
/// </summary>
void OnEnable()
{
PATH = $"{Application.persistentDataPath}/users.json";
Load();
}
/// <summary>
/// Create a new user
/// </summary>
/// <param name="name">The username of the new user</param>
/// <param name="avatar">Reference to the user avatar</param>
/// <returns>A newly created user</returns>
public User CreateNewUser(string name, Sprite avatar)
{
User user = new User();
user.username = name;
user.avatar = avatar;
return user;
}
/// <summary>
/// Create a new user and save (add to list)
/// </summary>
/// <param name="username">The username of the new user</param>
/// <param name="name">The username of the new user</param>
/// <param name="avatar">Reference to the user avatar</param>
/// <returns>A newly created user</returns>
public static User AddUser(string username, Sprite avatar)
public User CreateAndAddNewUser(string name, Sprite avatar)
{
PersistentDataController pdc = PersistentDataController.GetInstance();
PersistentDataController.SavedUserData data = new PersistentDataController.SavedUserData();
data.username = username;
data.playtime = 0.0;
data.avatarIndex = AVATARS.IndexOf(avatar);
pdc.AddUser(data);
return new User(data);
User user = CreateNewUser(name, avatar);
storedUserList.storedUsers.Add(user);
Save();
return user;
}
/// <summary>
@@ -35,127 +80,110 @@ public static class UserList
/// </summary>
/// <param name="username">The username of the user</param>
/// <returns><c>User</c>-object if a user with such username was found, <c>null</c> otherwise</returns>
public static User GetUserByUsername(string username)
public User GetUserByUsername(string username)
{
foreach (User user in GetUsers())
if (user.GetUsername() == username) return user;
foreach (User user in storedUserList.storedUsers)
if (user.username == username) return user;
return null;
}
/// <summary>
/// Get a user by index
/// </summary>
/// <param name="index">The index of the user</param>
/// <returns>User object</returns>
/// <exception cref="IndexOutOfRangeException"></exception>
public static User GetUserByIndex(int index)
{
List<User> users = GetUsers();
if (index < 0 || users.Count <= index)
throw new IndexOutOfRangeException();
return users[index];
}
/// <summary>
/// Get a list of all users currently stored
/// </summary>
/// <returns>A list of all users</returns>
public static List<User> GetUsers()
public List<User> GetUsers()
{
PersistentDataController pdc = PersistentDataController.GetInstance();
return pdc.GetUsers().ConvertAll((d) => new User(d));
return storedUserList.storedUsers;
}
/// <summary>
/// Get the current logged in user
/// </summary>
/// <returns>The current logged in user</returns>
public static User GetCurrentUser()
public User GetCurrentUser()
{
List<User> users = GetUsers();
if (users.Count == 0)
return null;
return users[PersistentDataController.GetInstance().GetCurrentUser()];
return storedUserList.storedUsers[storedUserList.currentUserIndex];
}
/// <summary>
/// Get the index in the userlist of a user
/// Get the index in the userlist of the current playing user
/// </summary>
/// <returns></returns>
public static int IndexOf(string username)
public int GetCurrentUserIndex()
{
int idx = GetUsers().FindIndex((e) => e.GetUsername() == username);
if (idx < 0)
throw new KeyNotFoundException();
return idx;
return storedUserList.currentUserIndex;
}
/// <summary>
/// Change the current user
/// </summary>
/// <param name="index">Index of the user in the userlist</param>
/// <exception cref="IndexOutOfRangeException"></exception>
public static void ChangeCurrentUser(int index)
public void ChangeCurrentUser(int index)
{
if (index < 0 || GetUsers().Count <= index)
throw new IndexOutOfRangeException();
PersistentDataController.GetInstance().SetCurrentUser(index, true);
storedUserList.currentUserIndex = index;
}
/// <summary>
/// Change the current user
/// </summary>
/// <param name="index">Username of the user</param>
/// <exception cref="KeyNotFoundException"></exception>
public static void ChangeCurrentUser(string username)
/// <param name="user">Reference to the user in the userlist</param>
public void ChangeCurrentUser(User user)
{
int index = GetUsers().FindIndex((e) => e.GetUsername() == username);
try { ChangeCurrentUser(index); }
catch (IndexOutOfRangeException) { throw new KeyNotFoundException(); }
storedUserList.currentUserIndex = storedUserList.storedUsers.IndexOf(user);
}
/// <summary>
/// Remove the user
/// </summary>
/// <param name="index">The index of the user in the userlist</param>
/// <returns>true if user was successful removed, false otherwise</returns>
public bool DeleteUser(int index)
{
return DeleteUser(storedUserList.storedUsers[index]);
}
/// <summary>
/// I am inevitable, *snap*
/// </summary>
/// <param name="index">The index of the user in the userlist</param>
/// <param name="user">Reference to the user to be removed</param>
/// <returns>true if the user was successful removed, false otherwise</returns>
/// <exception cref="IndexOutOfRangeException"></exception>
public static bool DeleteUser(int index)
public bool DeleteUser(User user)
{
List<User> users = GetUsers();
if (index < 0 || users.Count <= index)
throw new IndexOutOfRangeException();
if (1 < users.Count)
if (1 < storedUserList.storedUsers.Count)
{
PersistentDataController.GetInstance().DeleteUser(index);
return true;
if (storedUserList.currentUserIndex == storedUserList.storedUsers.Count - 1)
{
storedUserList.currentUserIndex--;
}
return storedUserList.storedUsers.Remove(user);
}
return false;
}
/// <summary>
/// Delete a user from the userliset
/// Save the users
/// </summary>
/// <param name="username">Username of the user</param>
/// <returns>true if the user was successful removed, false otherwise</returns>
/// <exception cref="KeyNotFoundException"></exception>
public static bool DeleteUser(string username)
public void Save()
{
int index = GetUsers().FindIndex((e) => e.GetUsername() == username);
try { return DeleteUser(index); }
catch (IndexOutOfRangeException) { throw new KeyNotFoundException(); }
string json = JsonUtility.ToJson(storedUserList);
File.CreateText(PATH).Close();
File.WriteAllText(PATH, json);
}
/// <summary>
/// Save the current UserList
/// Override the current content of the userlist by what is stored on disk
/// </summary>
public static void Save()
public void Load()
{
PersistentDataController.GetInstance().Save();
try
{
storedUserList.storedUsers.Clear();
string text = File.ReadAllText(PATH);
storedUserList = JsonUtility.FromJson<StoredUserList>(text);
}
catch (FileNotFoundException) { Debug.Log($"Path '{PATH}' not found"); }
}
}

View File

@@ -1,3 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
@@ -7,6 +10,11 @@ using UnityEngine.UI;
/// </summary>
public class UserProgressScreen : MonoBehaviour
{
/// <summary>
/// Reference to the userlist
/// </summary>
public UserList userList;
/// <summary>
/// Reference to the current user
/// </summary>
@@ -23,24 +31,80 @@ public class UserProgressScreen : MonoBehaviour
public Image avatar;
/// <summary>
/// Reference to the courses panel
/// UI reference to the user total playtime
/// </summary>
public GameObject coursesPanel;
public TMP_Text playtime;
/// <summary>
/// Reference to the minigame panel
/// Prefab of the highscore marker to display on the graph
/// </summary>
public GameObject minigamesPanel;
public GameObject highscoreMarker;
/// <summary>
/// Reference to the courses tab button (to set nice color)
/// Prefab of a course card
/// </summary>
public Image coursesTabButton;
public GameObject courseCardPrefab;
/// <summary>
/// Reference to the minigames tab button (to set nice color)
/// UI reference to the container holding all course cards
/// </summary>
public Image minigamesTabButton;
public GameObject coursesContainer;
/// <summary>
/// UI reference to the message that displays when no course progress is present
/// </summary>
public GameObject emptyCourses;
/// <summary>
/// Prefab of a minigame card
/// </summary>
public GameObject minigameCardPrefab;
/// <summary>
/// UI reference to the container holding all the minigame cards
/// </summary>
public GameObject minigamesContainer;
/// <summary>
/// UI reference to the message that displays when no minigame progress is present
/// </summary>
public GameObject emptyMinigames;
/// <summary>
/// UI reference to the plot
/// </summary>
public RawImage progressGraph;
/// <summary>
/// Left and right padding of the graph
/// </summary>
private const int GRAPH_PADDING_X_PX = 50;
/// <summary>
/// Top and bottom padding of the graph
/// </summary>
private const int GRAPH_PADDING_Y_PX = 50;
/// <summary>
/// Radius of the point on the graph
/// </summary>
private const int GRAPH_POINT_RADIUS = 10;
/// <summary>
/// Size of the line on the graph
/// </summary>
private const int GRAPH_LINE_SIZE = 4;
/// <summary>
/// Current selected activity draw to the graph
/// </summary>
private int selectedActivity = -1;
/// <summary>
/// List of activity backgrounds and indices
/// </summary>
private List<Tuple<Image, int>> activities = new List<Tuple<Image, int>>();
/// <summary>
/// Start is called before the first frame update
@@ -48,35 +112,266 @@ public class UserProgressScreen : MonoBehaviour
void Start()
{
// Assign the current user
PersistentDataController.GetInstance().Load();
user = UserList.GetCurrentUser();
user = userList.GetCurrentUser();
// Set correct displayed items
username.text = user.GetUsername();
avatar.sprite = user.GetAvatar();
username.text = user.username;
avatar.sprite = user.avatar;
// TODO: implement total playtime
//playtime.text = $"Totale speeltijd: {user.playtime.ToString("0.00")}";
DisplayCourses();
// Set graph inactive
progressGraph.gameObject.SetActive(false);
int i = 0;
// Display courses
coursesContainer.SetActive(user.courses.Count > 0);
emptyCourses.SetActive(user.courses.Count <= 0);
foreach (Progress courseProgress in user.courses)
{
// Create instance of prefab
GameObject instance = GameObject.Instantiate(courseCardPrefab, coursesContainer.transform.Find("Viewport").Find("Content").transform);
int j = i++;
// Initialize card
CourseProgressCard cpc = instance.GetComponent<CourseProgressCard>();
cpc.courseProgress = courseProgress;
cpc.selectActivity = () => UpdateSelection(j);
// Store reference to background so we can apply fancy coloring
Image background = instance.GetComponent<Image>();
background.color = Color.gray;
activities.Add(Tuple.Create(background, (int)courseProgress.Get<CourseIndex>("courseIndex")));
}
// Display minigames
minigamesContainer.SetActive(user.minigames.Count > 0);
emptyMinigames.SetActive(user.minigames.Count <= 0);
foreach (Progress minigameProgress in user.minigames)
{
// Create instance of prefab
GameObject instance = GameObject.Instantiate(minigameCardPrefab, minigamesContainer.transform.Find("Viewport").Find("Content").transform);
int j = i++;
// Initialize card
MinigameProgressCard mpc = instance.GetComponent<MinigameProgressCard>();
mpc.minigameProgress = minigameProgress;
mpc.selectActivity = () => UpdateSelection(j);
// Store reference to background so we can apply fancy coloring
Image background = instance.GetComponent<Image>();
background.color = Color.gray;
activities.Add(Tuple.Create(background, (int)minigameProgress.Get<MinigameIndex>("minigameIndex")));
}
}
/// <summary>
/// Switch to displaying the courses
/// Update the current selected activity
/// </summary>
public void DisplayCourses()
/// <param name="newActivity">Index to the new activity</param>
private void UpdateSelection(int newActivity)
{
coursesPanel.SetActive(true);
coursesTabButton.color = new Color(247 / 255f, 173 / 255f, 25 / 255f, 1f);
minigamesPanel.SetActive(false);
minigamesTabButton.color = new Color(247 / 255f, 173 / 255f, 25 / 255f, 120/255f);
if (selectedActivity < 0)
{
progressGraph.gameObject.SetActive(true);
}
else
{
activities[selectedActivity].Item1.color = Color.gray;
}
selectedActivity = newActivity;
activities[selectedActivity].Item1.color = Color.blue;
if (selectedActivity < user.courses.Count)
{
// TODO: create a better graph
//DisplayCourseGraph((CourseIndex)activities[selectedActivity].Item2);
// For now: just deactivate graph rendering
progressGraph.gameObject.SetActive(false);
}
else
{
DisplayMinigameGraph((MinigameIndex)activities[selectedActivity].Item2);
// TODO: remove line, this is only because courses deactivates the graph
progressGraph.gameObject.SetActive(true);
}
}
/// <summary>
/// Switch to displaying the minigames
/// Plot the graph of a course
/// </summary>
public void DisplayMinigames()
/// <param name="index">Index of the course</param>
/// <remarks>TODO: create a better plot</remarks>
private void DisplayCourseGraph(CourseIndex index) { }
/// <summary>
/// Plot the graph of a minigame
/// </summary>
/// <param name="minigameIndex">Index of the minigame</param>
private void DisplayMinigameGraph(MinigameIndex minigameIndex)
{
coursesPanel.SetActive(false);
coursesTabButton.color = new Color(247 / 255f, 173 / 255f, 25 / 255f, 120 / 255f);
minigamesPanel.SetActive(true);
minigamesTabButton.color = new Color(247 / 255f, 173 / 255f, 25 / 255f, 1f);
Progress progress = user.GetMinigameProgress(minigameIndex);
List<Score> latestScores = progress.Get<List<Score>>("latestScores");
List<Score> highestScores = progress.Get<List<Score>>("highestScores");
if (0 < highestScores.Count)
{
PlotGraph(latestScores.ConvertAll<double>((s) => (double)s.scoreValue), highestScores[0].scoreValue);
}
else
{
progressGraph.gameObject.SetActive(false);
}
}
/// <summary>
/// Plot points and a highscore on the graph
/// </summary>
/// <param name="scores">List of score values to plot</param>
/// <param name="highscore">Highscore value (this will be plotted in a fancy color)</param>
private void PlotGraph(List<double> scores, double highscore)
{
// Remove previous marker(s)
foreach (Transform child in progressGraph.gameObject.transform)
{
Destroy(child.gameObject);
}
// Get texture reference
Texture2D tex = progressGraph.texture as Texture2D;
if (tex == null)
{
RectTransform rt = progressGraph.gameObject.transform as RectTransform;
tex = new Texture2D(
width: (int)rt.sizeDelta.x,
height: (int)rt.sizeDelta.y,
textureFormat: TextureFormat.ARGB32,
mipCount: 3,
linear: true
);
}
tex.filterMode = FilterMode.Point;
// calculate positions and offsets
int x0 = GRAPH_PADDING_X_PX, x1 = tex.width - GRAPH_PADDING_X_PX;
int y0 = GRAPH_PADDING_Y_PX, y1 = tex.height - GRAPH_PADDING_Y_PX;
double min = scores.Min();
double max = scores.Max();
List<Tuple<int, int>> points = new List<Tuple<int, int>>();
for (int i = 0; i < scores.Count; i++)
{
int x = x0 + (scores.Count > 1 ? i * ((x1 - x0) / (scores.Count - 1)) : (x1 - x0) / 2);
int y = y0 + (int)((y1 - y0) * (min != max ? (scores[i] - min) / (max - min) : 0.5));
points.Add(Tuple.Create(x, y));
}
// Calculate scaling
int mag = (int)Math.Round(Math.Log10(max));
int MAG = (int)Math.Pow(10, mag);
double c = max / MAG;
// Draw axes
if (min != max)
{
for (double d = c / 5.0; d < c; d += 0.2 * c)
{
int y = y0 + (int)((y1 - y0) * (MAG * d - min) / (max - min));
DrawLine(tex, x0, y, x1, y, 2, Color.gray);
}
}
else
{
int y = y0 + (int)((y1 - y0) * 0.5);
DrawLine(tex, x0, y0, x1, y0, 2, Color.gray);
DrawLine(tex, x0, y, x1, y, 2, Color.gray);
DrawLine(tex, x0, y1, x1, y1, 2, Color.gray);
}
// Draw highscore
if (min <= highscore && highscore <= max)
{
int y = y0 + (int)((y1 - y0) * (min != max ? (highscore - min) / (max - min) : 0.5));
DrawLine(tex, x0, y, x1, y, 3, new Color(255, 192, 0));
GameObject marker = GameObject.Instantiate(highscoreMarker, progressGraph.gameObject.transform);
RectTransform rect = marker.GetComponent<RectTransform>();
rect.localPosition = new Vector3(0, y - 25, 0);
}
// Draw points
for (int i = 0; i < points.Count; i++)
{
Tuple<int, int> p = points[i];
if (0 < i)
{
Tuple<int, int> q = points[i - 1];
DrawLine(tex, p.Item1, p.Item2, q.Item1, q.Item2, GRAPH_LINE_SIZE, Color.blue);
}
DrawPoint(tex, p.Item1, p.Item2, GRAPH_POINT_RADIUS, Color.blue);
}
// Apply to graph GameObject
tex.Apply();
progressGraph.texture = tex;
}
/// <summary>
/// Draw a point to a texture
/// </summary>
/// <param name="tex">Texture2D to plot point on</param>
/// <param name="xc">Center x-pos</param>
/// <param name="yc">Center y-pos</param>
/// <param name="r">Radius (aka width and height)</param>
/// <param name="color">Color of the point</param>
private void DrawPoint(Texture2D tex, int xc, int yc, int r, Color color)
{
for (int y = yc - r; y < yc + r; y++)
{
for (int x = xc - r; x < xc + r; x++)
{
tex.SetPixel(x, y, color);
}
}
}
/// <summary>
/// Draw a line to a texture
/// </summary>
/// <param name="tex">Texture2D to plot line on</param>
/// <param name="x0">Starting x-pos</param>
/// <param name="y0">Strating y-pos</param>
/// <param name="x1">Ending x-pos</param>
/// <param name="y1">Ending y-pos</param>
/// <param name="size">Size of the line (width)</param>
/// <param name="color">Color of the line</param>
private void DrawLine(Texture2D tex, int x0, int y0, int x1, int y1, int size, Color color)
{
int w = x1 - x0;
int h = y1 - y0;
int length = Mathf.Abs(x1 - x0);
if (Mathf.Abs(y1 - y0) > length)
{
length = Mathf.Abs(h);
}
double dx = w / (double)length;
double dy = h / (double)length;
double x = x0;
double y = y0;
double r = size / 2;
for (int i = 0; i <= length; i++)
{
for (int j = (int)(y - r); j < y + r; j++)
{
for (int k = (int)(x - r); k < x + r; k++)
{
tex.SetPixel(k, j, color);
}
}
x += dx;
y += dy;
}
}
}

View File

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

View File

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

View File

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

View File

@@ -1,27 +0,0 @@
using NUnit.Framework;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
/// <summary>
/// Test the UserAvatarList class
/// </summary>
[TestFixture]
public class UserAvatarListTests
{
/// <summary>
/// Test the UserAvatarList class correctly initializes the UserList class
/// </summary>
[Test]
public void Test_Awake()
{
UserList.AVATARS = new List<Sprite>();
var scriptableObject = AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset");
scriptableObject.Awake();
for (int i = 0; i < scriptableObject.avatars.Count; i++)
Assert.AreEqual(scriptableObject.avatars[i], UserList.AVATARS[i]);
}
}

View File

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

View File

@@ -1,33 +0,0 @@
using NUnit.Framework;
/// <summary>
/// Test the UserCreationScreen class
/// </summary>
[TestFixture]
public class UserCreationScreenTests
{
/// <summary>
/// Tets IsValidUsername will return <c>true</c> for an valid username
/// </summary>
[Test]
public void Test_UserCreationScreen_IsValidUsername_True()
{
foreach (char c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
Assert.IsTrue(UserCreationScreen.IsValidUsername(c.ToString()));
Assert.IsTrue(UserCreationScreen.IsValidUsername("123456789AbC"));
}
/// <summary>
/// Tets IsValidUsername will return <c>false</c> for an invalid username
/// </summary>
[Test]
public void Test_UserCreationScreen_IsValidUsername_False()
{
Assert.IsFalse(UserCreationScreen.IsValidUsername(string.Empty));
foreach (char c in " \n\t+-*/%_.,;:!?(){}[]\\'\"|&~^$")
Assert.IsFalse(UserCreationScreen.IsValidUsername(c.ToString()));
Assert.IsFalse(UserCreationScreen.IsValidUsername("123456789_10_11_12_13"));
}
}

View File

@@ -1,444 +0,0 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
/// <summary>
/// Test the UserList class
/// </summary>
[TestFixture]
public class UserListTests
{
/// <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>
/// Helper variable for quick user creation
/// </summary>
private string username = "u5erNam3";
/// <summary>
/// Helper variable for quick user creation
/// </summary>
private Sprite avatar = null;
/// <summary>
/// Setup the tests
/// </summary>
[SetUp]
public void Setup_UserList()
{
PersistentDataController.PATH = UserListTests.PATH;
if (File.Exists(PATH))
File.Delete(PATH);
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
avatar = UserList.AVATARS[0];
}
/// <summary>
/// Cleanup after testing
/// </summary>
[TearDown]
public void TearDown_UserList()
{
PersistentDataController.PATH = null;
}
/// <summary>
/// Test for creation of a new UserList
/// </summary>
[Test]
public void Test_New_UserList()
{
Assert.Zero(UserList.GetUsers().Count);
}
/// <summary>
/// Test for creation of new user (without adding the user to the list)
/// </summary>
[Test]
public void Test_UserList_AddUser()
{
Assert.Zero(UserList.GetUsers().Count);
User user = UserList.AddUser(username, avatar);
Assert.IsNotNull(user);
Assert.AreEqual(1, UserList.GetUsers().Count);
Assert.AreEqual(username, user.GetUsername());
Assert.AreEqual(avatar, user.GetAvatar());
}
/// <summary>
/// Test whether an existing user can be found by its username
/// </summary>
[Test]
public void Test_UserList_GetUserByUsername_Valid()
{
User u = UserList.AddUser(username, avatar);
User v = UserList.GetUserByUsername(username);
Assert.AreEqual(u.GetUsername(), v.GetUsername());
}
/// <summary>
/// Test whether a non-existing user can not be found
/// </summary>
[Test]
public void Test_UserList_GetUserByUsername_Null()
{
User user = UserList.GetUserByUsername("not-a-user");
Assert.IsNull(user);
}
/// <summary>
/// Test whether an existing user can be found by its username
/// </summary>
[Test]
public void Test_UserList_GetUserByIndex_Valid()
{
User u = UserList.AddUser(username, avatar);
User v = UserList.GetUserByIndex(0);
Assert.AreEqual(u.GetUsername(), v.GetUsername());
}
/// <summary>
/// Test whether a non-existing user can not be found
/// </summary>
[Test]
public void Test_UserList_GetUserByIndex_Exception()
{
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.GetUserByIndex(0); });
}
/// <summary>
/// Test whether a userlist is correctly returned
/// </summary>
[Test]
public void Test_UserList_GetUsers()
{
List<User> u = new List<User>();
for (int i = 0; i < 5; i++)
u.Add(UserList.AddUser($"{username}_{i}", avatar));
List<User> v = UserList.GetUsers();
Assert.AreEqual(v.Count, u.Count);
for (int i = 0; i < 5; i++)
Assert.AreEqual(u[i].GetUsername(), v[i].GetUsername());
}
/// <summary>
/// Test whether the correct current user is returned
/// </summary>
[Test]
public void Test_UserList_GetCurrentUser()
{
User u = UserList.AddUser($"{username}_{'u'}", avatar);
User v = UserList.AddUser($"{username}_{'v'}", avatar);
User w = UserList.AddUser($"{username}_{'w'}", avatar);
UserList.ChangeCurrentUser(2);
User W = UserList.GetCurrentUser();
Assert.AreEqual(w.GetUsername(), W.GetUsername());
}
/// <summary>
/// Test whether a null user is returned when the userlist is empty
/// </summary>
[Test]
public void Test_UserList_GetCurrentUser_Empty()
{
User user = UserList.GetCurrentUser();
Assert.IsNull(user);
}
/// <summary>
/// Test whether the correct index is returned for the current user
/// </summary>
[Test]
public void Test_UserList_IndexOf_Valid()
{
User u = UserList.AddUser($"{username}_{'u'}", avatar);
User v = UserList.AddUser($"{username}_{'v'}", avatar);
User w = UserList.AddUser($"{username}_{'w'}", avatar);
UserList.ChangeCurrentUser(2);
Assert.AreEqual(0, UserList.IndexOf(u.GetUsername()));
Assert.AreEqual(1, UserList.IndexOf(v.GetUsername()));
Assert.AreEqual(2, UserList.IndexOf(w.GetUsername()));
}
/// <summary>
/// Test whether the correct index is returned for the current user
/// </summary>
[Test]
public void Test_UserList_IndexOf_Exception()
{
User u = new User(new PersistentDataController.SavedUserData()
{
username = username,
avatarIndex = 0
});
Assert.Throws<KeyNotFoundException>(delegate { UserList.IndexOf(u.GetUsername()); });
}
/// <summary>
/// Test whether the current user (referenced by index) is correctly changed
/// </summary>
[Test]
public void Test_UserList_ChangeCurrentUser_ValidIndex()
{
User u = UserList.AddUser($"{username}_{'u'}", avatar);
User v = UserList.AddUser($"{username}_{'v'}", avatar);
User w = UserList.AddUser($"{username}_{'w'}", avatar);
UserList.ChangeCurrentUser(2);
User W = UserList.GetCurrentUser();
Assert.AreEqual(w.GetUsername(), W.GetUsername());
}
/// <summary>
/// Test whether the current user is not changed when a bad index is given
/// </summary>
[Test]
public void Test_UserList_ChangeCurrentUser_InvalidIndex()
{
User u = UserList.AddUser($"{username}_{'u'}", avatar);
User v = UserList.AddUser($"{username}_{'v'}", avatar);
User w = UserList.AddUser($"{username}_{'w'}", avatar);
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.ChangeCurrentUser(-1); });
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.ChangeCurrentUser(5); });
}
/// <summary>
/// Test whether the current user is not changed when a bad index is given
/// </summary>
[Test]
public void Test_UserList_ChangeCurrentUser_IndexEmpty()
{
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.ChangeCurrentUser(0); });
}
/// <summary>
/// Test whether the current user is correctly changed
/// </summary>
[Test]
public void Test_UserList_ChangeCurrentUser_ValidUsername()
{
User u = UserList.AddUser($"{username}_{'u'}", avatar);
User v = UserList.AddUser($"{username}_{'v'}", avatar);
User w = UserList.AddUser($"{username}_{'w'}", avatar);
UserList.ChangeCurrentUser(v.GetUsername());
User V = UserList.GetCurrentUser();
Assert.AreEqual(v.GetUsername(), V.GetUsername());
}
/// <summary>
/// Test whether the current user is not changed when a non-existing user is given
/// </summary>
[Test]
public void Test_UserList_ChangeCurrentUser_InvalidUsername()
{
User u = UserList.AddUser($"{username}_{'u'}", avatar);
User v = new User(new PersistentDataController.SavedUserData()
{
username = $"{username}_{'v'}",
avatarIndex = 0
});
Assert.Throws<KeyNotFoundException>(delegate { UserList.ChangeCurrentUser(v.GetUsername()); });
}
/// <summary>
/// Test whether the current user is not changed when a null user is given
/// </summary>
[Test]
public void Test_UserList_ChangeCurrentUser_NullUsername()
{
Assert.Throws<KeyNotFoundException>(delegate { UserList.ChangeCurrentUser(null); });
}
/// <summary>
/// Test whether deleting a existing user (referenced by index) will correctly be removed
/// </summary>
[Test]
public void Test_UserList_DeleteUser_ValidIndex()
{
User u = UserList.AddUser($"{username}_{'u'}", avatar);
User v = UserList.AddUser($"{username}_{'v'}", avatar);
User w = UserList.AddUser($"{username}_{'w'}", avatar);
Assert.IsTrue(UserList.DeleteUser(1));
}
/// <summary>
/// Test whether deleting a non-existing user (referenced by wrong index) will fail
/// </summary>
[Test]
public void Test_UserList_DeleteUser_InvalidIndex()
{
User u = UserList.AddUser($"{username}_{'u'}", avatar);
User v = UserList.AddUser($"{username}_{'v'}", avatar);
User w = UserList.AddUser($"{username}_{'w'}", avatar);
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.DeleteUser(-1); });
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.DeleteUser(5); });
}
/// <summary>
/// Test whether deleting any user from an empty userlist will fail
/// </summary>
[Test]
public void Test_UserList_DeleteUser_IndexEmpty()
{
Assert.Throws<IndexOutOfRangeException>(delegate { UserList.DeleteUser(0); });
}
/// <summary>
/// Test whether deleting an existing user will correctly remove the user and set the currentUserIndex correctly
/// </summary>
[Test]
public void Test_UserList_DeleteUser_BeforeCurrentUser()
{
User u = UserList.AddUser($"{username}_{'u'}", avatar);
User v = UserList.AddUser($"{username}_{'v'}", avatar);
User w = UserList.AddUser($"{username}_{'w'}", avatar);
UserList.ChangeCurrentUser(1);
Assert.AreEqual(3, UserList.GetUsers().Count);
Assert.AreEqual(1, UserList.IndexOf(UserList.GetCurrentUser().GetUsername()));
Assert.IsTrue(UserList.DeleteUser(u.GetUsername()));
Assert.AreEqual(2, UserList.GetUsers().Count);
Assert.AreEqual(0, UserList.IndexOf(UserList.GetCurrentUser().GetUsername()));
}
/// <summary>
/// Test whether deleting an existing user will correctly remove the user and set the currentUserIndex correctly
/// </summary>
[Test]
public void Test_UserList_DeleteUser_CurrentUser()
{
User u = UserList.AddUser($"{username}_{'u'}", avatar);
User v = UserList.AddUser($"{username}_{'v'}", avatar);
User w = UserList.AddUser($"{username}_{'w'}", avatar);
UserList.ChangeCurrentUser(1);
Assert.AreEqual(3, UserList.GetUsers().Count);
Assert.AreEqual(1, UserList.IndexOf(UserList.GetCurrentUser().GetUsername()));
Assert.IsTrue(UserList.DeleteUser(v.GetUsername()));
Assert.AreEqual(2, UserList.GetUsers().Count);
Assert.AreEqual(0, UserList.IndexOf(UserList.GetCurrentUser().GetUsername()));
}
/// <summary>
/// Test whether deleting an existing user will correctly remove the user and set the currentUserIndex correctly
/// </summary>
[Test]
public void Test_UserList_DeleteUser_AfterCurrentUser()
{
User u = UserList.AddUser($"{username}_{'u'}", avatar);
User v = UserList.AddUser($"{username}_{'v'}", avatar);
User w = UserList.AddUser($"{username}_{'w'}", avatar);
UserList.ChangeCurrentUser(1);
Assert.AreEqual(3, UserList.GetUsers().Count);
Assert.AreEqual(1, UserList.IndexOf(UserList.GetCurrentUser().GetUsername()));
Assert.IsTrue(UserList.DeleteUser(w.GetUsername()));
Assert.AreEqual(2, UserList.GetUsers().Count);
Assert.AreEqual(1, UserList.IndexOf(UserList.GetCurrentUser().GetUsername()));
}
/// <summary>
/// Test whether deleting a non-existing user will not affect the userlist
/// </summary>
[Test]
public void Test_UserList_DeleteUser_Invalid()
{
User u = UserList.AddUser($"{username}_{'u'}", avatar);
User v = new User(new PersistentDataController.SavedUserData()
{
username = $"{username}_{'v'}",
avatarIndex = 0
});
Assert.AreEqual(1, UserList.GetUsers().Count);
Assert.Throws<KeyNotFoundException>(delegate { UserList.DeleteUser(v.GetUsername()); });
Assert.AreEqual(1, UserList.GetUsers().Count);
}
/// <summary>
/// Test whether calling the DeleteUser function on an empty list will not affect the userlist
/// </summary>
[Test]
public void Test_UserList_DeleteUser_Empty()
{
User user = new User(new PersistentDataController.SavedUserData()
{
username = username,
avatarIndex = 0
});
Assert.Zero(UserList.GetUsers().Count);
Assert.Throws<KeyNotFoundException>(delegate { UserList.DeleteUser(user.GetUsername()); });
Assert.Zero(UserList.GetUsers().Count);
}
/// <summary>
/// Test whether a savefile is correctly constructed when no savefile is present
/// </summary>
[Test]
public void Test_UserList_Save_New()
{
List<User> u = new List<User>();
for (int i = 0; i < 5; i++)
u.Add(UserList.AddUser($"{username}_{i}", avatar));
UserList.ChangeCurrentUser(3);
UserList.Save();
FileAssert.Exists(PATH);
string content = File.ReadAllText(PATH);
string expected = $"{{\"version\":{PersistentDataController.VERSION},\"users\":[{{\"entries\":[],\"username\":\"u5erNam3_0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_1\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_2\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_3\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_4\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}}],\"currentUser\":3,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
Assert.AreEqual(expected, content);
}
/// <summary>
/// Test whether a savefile is correctly constructed when a savefile already exists
/// </summary>
[Test]
public void Test_UserList_Save_Existing()
{
if (!File.Exists(PATH))
{
File.CreateText(PATH).Close();
File.WriteAllText(PATH, "https://www.youtube.com/watch?v=dQw4w9WgXcQ");
}
List<User> u = new List<User>();
for (int i = 0; i < 5; i++)
u.Add(UserList.AddUser($"{username}_{i}", avatar));
UserList.ChangeCurrentUser(3);
UserList.Save();
FileAssert.Exists(PATH);
string content = File.ReadAllText(PATH);
string expected = $"{{\"version\":{PersistentDataController.VERSION},\"users\":[{{\"entries\":[],\"username\":\"u5erNam3_0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_1\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_2\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_3\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}},{{\"entries\":[],\"username\":\"u5erNam3_4\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}}],\"currentUser\":3,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
Assert.AreEqual(expected, content);
}
/// <summary>
/// Test whether a save file is correctly constructed from an empty userlist
/// </summary>
[Test]
public void Test_UserList_Save_Empty()
{
UserList.Save();
FileAssert.Exists(PATH);
string content = File.ReadAllText(PATH);
string expected = $"{{\"version\":{PersistentDataController.VERSION},\"users\":[],\"currentUser\":-1,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
Assert.AreEqual(expected, content);
}
}

View File

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

View File

@@ -1,225 +0,0 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
/// <summary>
/// Test the User class
/// </summary>
[TestFixture]
public class UserTests
{
/// <summary>
/// Reference to the user to be tested
/// </summary>
private User user;
/// <summary>
/// Setup the tests
/// </summary>
[SetUp]
public void Setup_User()
{
PersistentDataController.SavedUserData data = new PersistentDataController.SavedUserData();
data.username = "username";
data.avatarIndex = 0;
user = new User(data);
}
/// <summary>
/// Test for the creation of a new user
/// </summary>
[Test]
public void Test_New_User()
{
Assert.NotNull(user);
Assert.Zero(user.GetCourses().Count);
Assert.Zero(user.GetMinigames().Count);
}
/// <summary>
/// Test whether the correct username is returned
/// </summary>
[Test]
public void Test_User_GetUsername()
{
Assert.AreEqual("username", user.GetUsername());
}
/// <summary>
/// Test whether the correct avatar is returned
/// </summary>
[Test]
public void Test_User_GetAvatar()
{
Assert.AreEqual(UserList.AVATARS[0], user.GetAvatar());
}
/// <summary>
/// Test whether the correct total playtime is returned
/// </summary>
[Test]
public void Test_User_GetPlaytime()
{
Assert.AreEqual(0.0, user.GetPlaytime());
}
/// <summary>
/// Test whether progress on a new course can be added
/// </summary>
[Test]
public void Test_User_AddCourse()
{
var p = new PersistentDataController.SavedCourseProgress();
user.AddCourseProgress(p);
Assert.AreEqual(user.GetCourses().Count, 1);
Assert.Zero(user.GetMinigames().Count);
}
/// <summary>
/// Test whether progress on a new minigame can be added
/// </summary>
[Test]
public void Test_User_AddMinigame()
{
var p = new PersistentDataController.SavedMinigameProgress();
user.AddMinigameProgress(p);
Assert.Zero(user.GetCourses().Count);
Assert.AreEqual(user.GetMinigames().Count, 1);
}
/// <summary>
/// Test GetRecentCourses will return empty when no progress is stored
/// </summary>
[Test]
public void Test_User_GetRecentCourses_Empty()
{
Assert.Zero(user.GetRecentCourses().Count);
}
/// <summary>
/// TEMPORARY test for GetRecentCourses will return all progress that is stored
/// </summary>
[Test]
public void Test_User_GetRecentCourses_All()
{
var p = new PersistentDataController.SavedCourseProgress();
p.courseIndex = CourseIndex.FINGERSPELLING;
p.progress = 0.5f;
user.AddCourseProgress(p);
List<Tuple<CourseIndex, float>> list = user.GetRecentCourses();
Assert.AreEqual(list.Count, 1);
Assert.AreEqual(list[0].Item1, CourseIndex.FINGERSPELLING);
Assert.AreEqual(list[0].Item2, 0.5f);
}
/// <summary>
/// Test GetRecommendedCourses will return <c>Tuple<CourseIndex.FINGERSPELLING, 0.0></c> when no progress is stored
/// </summary>
[Test]
public void Test_User_GetRecommendedCourses_Empty()
{
List<Tuple<CourseIndex, float>> list = user.GetRecommendedCourses();
Assert.AreEqual(list.Count, 1);
Assert.AreEqual(list[0].Item1, CourseIndex.FINGERSPELLING);
Assert.AreEqual(list[0].Item2, 0.0f);
}
/// <summary>
/// TEMPORARY test for GetRecommenedCourses will return all progress that is stored
/// </summary>
[Test]
public void Test_User_GetRecommendedCourses_All()
{
var p = new PersistentDataController.SavedCourseProgress();
p.courseIndex = CourseIndex.FINGERSPELLING;
p.progress = 0.5f;
user.AddCourseProgress(p);
List<Tuple<CourseIndex, float>> list = user.GetRecommendedCourses();
Assert.AreEqual(list.Count, 1);
Assert.AreEqual(list[0].Item1, CourseIndex.FINGERSPELLING);
Assert.AreEqual(list[0].Item2, 0.5f);
}
/// <summary>
/// Test GetCourseProgress returns null when course cannot be found
/// </summary>
[Test]
public void Test_User_GetCourseProgress_Null()
{
Assert.Null(user.GetCourseProgress(CourseIndex.FINGERSPELLING));
Assert.Null(user.GetCourseProgress((CourseIndex)100));
}
/// <summary>
/// Test GetCourseProgress returns correct progress object
/// </summary>
[Test]
public void Test_User_GetCourseProgress_Valid()
{
var p = new PersistentDataController.SavedCourseProgress();
p.courseIndex = CourseIndex.FINGERSPELLING;
p.progress = 3.14159265f;
user.AddCourseProgress(p);
var q = user.GetCourseProgress(CourseIndex.FINGERSPELLING);
Assert.AreEqual(q.courseIndex, CourseIndex.FINGERSPELLING);
Assert.AreEqual(q.progress, 3.14159265f);
}
/// <summary>
/// Test progress of a course is correctly reset (aka removed)
/// </summary>
[Test]
public void Test_User_ResetCourseProgres()
{
var p = new PersistentDataController.SavedCourseProgress();
p.courseIndex = CourseIndex.FINGERSPELLING;
user.AddCourseProgress(p);
Assert.IsNotNull(user.GetCourseProgress(CourseIndex.FINGERSPELLING));
user.ResetCourseProgress(CourseIndex.FINGERSPELLING);
Assert.IsNull(user.GetCourseProgress(CourseIndex.FINGERSPELLING));
}
/// <summary>
/// Test GetMinigameProgress returns null when minigame cannot be found
/// </summary>
[Test]
public void Test_User_GetMinigameProgress_Null()
{
Assert.Null(user.GetMinigameProgress(MinigameIndex.SPELLING_BEE));
Assert.Null(user.GetMinigameProgress((MinigameIndex)100));
var p = new PersistentDataController.SavedMinigameProgress();
p.minigameIndex = MinigameIndex.SPELLING_BEE;
user.AddMinigameProgress(p);
Assert.Null(user.GetMinigameProgress(MinigameIndex.HANGMAN));
}
/// <summary>
/// Test GetMinigameProgress returns correct progress object
/// </summary>
[Test]
public void Test_User_GetMinigameProgress_Valid()
{
var p = new PersistentDataController.SavedMinigameProgress();
p.minigameIndex = MinigameIndex.SPELLING_BEE;
user.AddMinigameProgress(p);
var q = user.GetMinigameProgress(MinigameIndex.SPELLING_BEE);
Assert.AreEqual(q.minigameIndex, MinigameIndex.SPELLING_BEE);
Assert.Zero(q.latestScores.Count);
Assert.Zero(q.highestScores.Count);
}
/// <summary>
/// Test progress of a minigame is correctly reset (aka removed)
/// </summary>
[Test]
public void Test_User_ResetMinigameProgres()
{
var p = new PersistentDataController.SavedMinigameProgress();
p.minigameIndex = MinigameIndex.SPELLING_BEE;
user.AddMinigameProgress(p);
Assert.IsNotNull(user.GetMinigameProgress(MinigameIndex.SPELLING_BEE));
user.ResetMinigameProgress(MinigameIndex.SPELLING_BEE);
Assert.IsNull(user.GetMinigameProgress(MinigameIndex.SPELLING_BEE));
}
}

View File

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

View File

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

View File

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

View File

@@ -1,379 +0,0 @@
using NUnit.Framework;
using System.Collections;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
using UnityEngine.UI;
/// <summary>
/// Test the ChangeUserScreen class
/// </summary>
[TestFixture]
public class ChangeUserScreenTests
{
/// <summary>
/// Wait time between scene transitions
/// </summary>
private const float WAIT_TIME = 0.2f;
/// <summary>
/// The default current user when dealing with multiple users
/// </summary>
private const int currentUser = 2;
/// <summary>
/// Setup the tests for a single user
/// </summary>
private IEnumerator Setup_ChangeUserScreen_SingleUser(string startScreen = "Accounts/Scenes/ChangeUserScreen")
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string oneUser = "{\"version\":1537,\"users\":[{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene(startScreen);
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Setup the tests for a multiple users
/// </summary>
private IEnumerator Setup_ChangeUserScreen_MultipleUsers(string startScreen = "Accounts/Scenes/ChangeUserScreen")
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string users = "";
for (int i = 0; i < 5; i++)
{
users += $"{{\"entries\":[],\"username\":\"Tester{i}\",\"avatarIndex\":{i},\"playtime\":0.0,\"minigames\":[],\"courses\":[]}}";
if (i < 4) users += ",";
}
const int currentUser = 2;
string fiveUsers = $"{{\"version\":1537,\"users\":[{users}],\"currentUser\":{currentUser},\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
File.WriteAllText(path, fiveUsers);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene(startScreen);
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Cleanup after testing
/// </summary>
[TearDown]
public void TearDown_ChangeUserScreen()
{
PersistentDataController.PATH = null;
}
/// <summary>
/// Test whether every item that needs to be assign in the editor, is assigned
/// </summary>
[UnityTest]
public IEnumerator Test_EditorAssignments()
{
yield return Setup_ChangeUserScreen_SingleUser();
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
Assert.IsNotNull(changeUserController);
Assert.IsNotNull(changeUserController.userPrefab);
Assert.IsNotNull(changeUserController.usersContainer);
Assert.IsNotNull(changeUserController.error);
}
/// <summary>
/// Test whether the screen is correctly initialized (one user)
/// </summary>
[UnityTest]
public IEnumerator Test_Start_SingleUser()
{
yield return Setup_ChangeUserScreen_SingleUser();
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
Assert.IsFalse(changeUserController.error.activeSelf);
}
/// <summary>
/// Test whether the users is correctly displayed (one user)
/// </summary>
[UnityTest]
public IEnumerator Test_DisplayUsers_SingleUser()
{
yield return Setup_ChangeUserScreen_SingleUser();
// The content of the usercard is tested in the `UserCardTests`-script
// Here, we only check the amount of users
Assert.AreEqual(1, UserList.GetUsers().Count);
var cards = GameObject.FindObjectsOfType<UserCard>().ToList();
Assert.AreEqual(1, cards.Count);
Assert.AreEqual(new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f), cards[0].gameObject.GetComponent<Image>().color);
}
/// <summary>
/// Test whether the users are correctly displayed (mulitple users)
/// </summary>
[UnityTest]
public IEnumerator Test_DisplayUsers_MultipleUsers()
{
yield return Setup_ChangeUserScreen_MultipleUsers();
// The content of the usercard is tested in the `UserCardTests`-script
// Here, we only check the amount of users and whether the correct one is selected
Assert.AreEqual(UserList.GetCurrentUser().GetUsername(), UserList.GetUserByIndex(currentUser).GetUsername());
var cards = GameObject.FindObjectsOfType<UserCard>().ToList();
Assert.AreEqual(UserList.GetUsers().Count, cards.Count);
for (int i = 0; i < cards.Count; i++)
{
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
}
}
/// <summary>
/// Test whether selecting a new user before the current one updates the display correctly
/// </summary>
[UnityTest]
public IEnumerator Test_UpdateSelection_BeforeCurrentUser()
{
yield return Setup_ChangeUserScreen_MultipleUsers();
var cards = GameObject.FindObjectsOfType<UserCard>().ToList();
// Before update
for (int i = 0; i < cards.Count; i++)
{
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
}
// Update
const int newUser = 1;
cards[newUser].selectUser.Invoke();
// After update
for (int i = 0; i < cards.Count; i++)
{
Color expected = i == newUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
}
}
/// <summary>
/// Test whether selecting the current user for update the display will change nothing
/// </summary>
[UnityTest]
public IEnumerator Test_UpdateSelection_CurrentUser()
{
yield return Setup_ChangeUserScreen_MultipleUsers();
var cards = GameObject.FindObjectsOfType<UserCard>().ToList();
// Before update
for (int i = 0; i < cards.Count; i++)
{
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
}
// Update
cards[currentUser].selectUser.Invoke();
// After update
for (int i = 0; i < cards.Count; i++)
{
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
}
}
/// <summary>
/// Test whether selecting a new user after the current one updates the display correctly
/// </summary>
[UnityTest]
public IEnumerator Test_UpdateSelection_AfterCurrentUser()
{
yield return Setup_ChangeUserScreen_MultipleUsers();
var cards = GameObject.FindObjectsOfType<UserCard>().ToList();
// Before update
for (int i = 0; i < cards.Count; i++)
{
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
}
// Update
const int newUser = 3;
cards[newUser].selectUser.Invoke();
// After update
for (int i = 0; i < cards.Count; i++)
{
Color expected = i == newUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, cards[i].gameObject.GetComponent<Image>().color);
}
}
/// <summary>
/// Test IChooseYou callback
/// </summary>
[UnityTest]
public IEnumerator Test_IChooseYou()
{
yield return Setup_ChangeUserScreen_SingleUser("Common/Scenes/MainMenuScreen");
SystemController.GetInstance().LoadNextScene("Accounts/Scenes/ChangeUserScreen");
yield return new WaitForSeconds(WAIT_TIME);
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
changeUserController.IChooseYou();
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(SystemController.GetSceneIndex("Common/Scenes/MainMenuScreen"), SystemController.GetInstance().currentScene);
}
/// <summary>
/// Test the GotoUserCreation callback
/// </summary>
[UnityTest]
public IEnumerator Test_GotoUserCreation()
{
yield return Setup_ChangeUserScreen_SingleUser();
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
changeUserController.GotoUserCreation();
yield return new WaitForSeconds(WAIT_TIME);
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
Assert.IsNotNull(userCreationController);
}
/// <summary>
/// Test the user cards DeleteUser callback
/// </summary>
[UnityTest]
public IEnumerator Test_UserCardDeleteUser_BeforeCurrentUser()
{
yield return Setup_ChangeUserScreen_MultipleUsers();
// Before update
var oldCards = GameObject.FindObjectsOfType<UserCard>().ToList();
for (int i = 0; i < oldCards.Count; i++)
{
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, oldCards[i].gameObject.GetComponent<Image>().color);
}
// Update
oldCards[1].DeleteUser();
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
Assert.IsFalse(changeUserController.error.activeSelf);
yield return new WaitForSeconds(WAIT_TIME);
// After update
var newCards = GameObject.FindObjectsOfType<UserCard>().ToList();
Assert.AreEqual(oldCards.Count - 1, newCards.Count);
for (int i = 0; i < newCards.Count; i++)
{
Color expected = i == (currentUser - 1) ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, newCards[i].gameObject.GetComponent<Image>().color);
}
}
/// <summary>
/// Test the user cards DeleteUser callback
/// </summary>
[UnityTest]
public IEnumerator Test_UserCardDeleteUser_CurrentUser()
{
yield return Setup_ChangeUserScreen_MultipleUsers();
// Before update
var oldCards = GameObject.FindObjectsOfType<UserCard>().ToList();
for (int i = 0; i < oldCards.Count; i++)
{
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, oldCards[i].gameObject.GetComponent<Image>().color);
}
// Update
oldCards[currentUser].DeleteUser();
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
Assert.IsFalse(changeUserController.error.activeSelf);
yield return new WaitForSeconds(WAIT_TIME);
// After update
var newCards = GameObject.FindObjectsOfType<UserCard>().ToList();
Assert.AreEqual(oldCards.Count - 1, newCards.Count);
for (int i = 0; i < newCards.Count; i++)
{
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, newCards[i].gameObject.GetComponent<Image>().color);
}
}
/// <summary>
/// Test the user cards DeleteUser callback
/// </summary>
[UnityTest]
public IEnumerator Test_UserCardDeleteUser_AfterCurrentUser()
{
yield return Setup_ChangeUserScreen_MultipleUsers();
// Before update
var oldCards = GameObject.FindObjectsOfType<UserCard>().ToList();
for (int i = 0; i < oldCards.Count; i++)
{
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, oldCards[i].gameObject.GetComponent<Image>().color);
}
// Update
oldCards[3].DeleteUser();
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
Assert.IsFalse(changeUserController.error.activeSelf);
yield return new WaitForSeconds(WAIT_TIME);
// After update
var newCards = GameObject.FindObjectsOfType<UserCard>().ToList();
Assert.AreEqual(oldCards.Count - 1, newCards.Count);
for (int i = 0; i < newCards.Count; i++)
{
Color expected = i == currentUser ? new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f) : new Color(159 / 255f, 231 / 255f, 245 / 255f, 1f);
Assert.AreEqual(expected, newCards[i].gameObject.GetComponent<Image>().color);
}
}
/// <summary>
/// Test the user cards DeleteUser callback
/// </summary>
[UnityTest]
public IEnumerator Test_UserCardDeleteUser_Invalid()
{
yield return Setup_ChangeUserScreen_SingleUser();
// Before update
var oldCards = GameObject.FindObjectsOfType<UserCard>().ToList();
Assert.AreEqual(1, oldCards.Count);
Assert.AreEqual(new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f), oldCards[0].gameObject.GetComponent<Image>().color);
// Update
oldCards[0].DeleteUser();
var changeUserController = GameObject.FindObjectOfType<ChangeUserScreen>();
Assert.IsTrue(changeUserController.error.activeSelf);
// After update
var newCards = GameObject.FindObjectsOfType<UserCard>().ToList();
Assert.AreEqual(1, newCards.Count);
Assert.AreEqual(new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f), newCards[0].gameObject.GetComponent<Image>().color);
}
}

View File

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

View File

@@ -1,80 +0,0 @@
using NUnit.Framework;
using System.Collections;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
/// <summary>
/// Test the CourseProgressCard class
/// </summary>
[TestFixture]
public class CourseProgressCardTests
{
/// <summary>
/// Wait time between scene transitions
/// </summary>
private const float WAIT_TIME = 0.2f;
/// <summary>
/// Setup the CourseProgressCard tests
/// </summary>
[UnitySetUp]
public IEnumerator Setup_CourseProgressCard()
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string course = "{\"entries\":[],\"courseIndex\":0,\"progress\":0.03846153989434242,\"completedLearnables\":1,\"inUseLearnables\":7,\"totalLearnables\":26,\"learnables\":[{\"entries\":[],\"index\":0,\"inUse\":true,\"name\":\"A\",\"progress\":3.0},{\"entries\":[],\"index\":1,\"inUse\":true,\"name\":\"B\",\"progress\":4.5},{\"entries\":[],\"index\":2,\"inUse\":true,\"name\":\"C\",\"progress\":1.5},{\"entries\":[],\"index\":3,\"inUse\":true,\"name\":\"D\",\"progress\":1.5},{\"entries\":[],\"index\":4,\"inUse\":true,\"name\":\"E\",\"progress\":1.5},{\"entries\":[],\"index\":5,\"inUse\":true,\"name\":\"F\",\"progress\":1.5},{\"entries\":[],\"index\":6,\"inUse\":true,\"name\":\"G\",\"progress\":0.0},{\"entries\":[],\"index\":7,\"inUse\":false,\"name\":\"H\",\"progress\":0.0},{\"entries\":[],\"index\":8,\"inUse\":false,\"name\":\"I\",\"progress\":0.0},{\"entries\":[],\"index\":9,\"inUse\":false,\"name\":\"J\",\"progress\":0.0},{\"entries\":[],\"index\":10,\"inUse\":false,\"name\":\"K\",\"progress\":0.0},{\"entries\":[],\"index\":11,\"inUse\":false,\"name\":\"L\",\"progress\":0.0},{\"entries\":[],\"index\":12,\"inUse\":false,\"name\":\"M\",\"progress\":0.0},{\"entries\":[],\"index\":13,\"inUse\":false,\"name\":\"N\",\"progress\":0.0},{\"entries\":[],\"index\":14,\"inUse\":false,\"name\":\"O\",\"progress\":0.0},{\"entries\":[],\"index\":15,\"inUse\":false,\"name\":\"P\",\"progress\":0.0},{\"entries\":[],\"index\":16,\"inUse\":false,\"name\":\"Q\",\"progress\":0.0},{\"entries\":[],\"index\":17,\"inUse\":false,\"name\":\"R\",\"progress\":0.0},{\"entries\":[],\"index\":18,\"inUse\":false,\"name\":\"S\",\"progress\":0.0},{\"entries\":[],\"index\":19,\"inUse\":false,\"name\":\"T\",\"progress\":0.0},{\"entries\":[],\"index\":20,\"inUse\":false,\"name\":\"U\",\"progress\":0.0},{\"entries\":[],\"index\":21,\"inUse\":false,\"name\":\"V\",\"progress\":0.0},{\"entries\":[],\"index\":22,\"inUse\":false,\"name\":\"W\",\"progress\":0.0},{\"entries\":[],\"index\":23,\"inUse\":false,\"name\":\"X\",\"progress\":0.0},{\"entries\":[],\"index\":24,\"inUse\":false,\"name\":\"Y\",\"progress\":0.0},{\"entries\":[],\"index\":25,\"inUse\":false,\"name\":\"Z\",\"progress\":0.0}]}";
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[{course}]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
yield return new WaitForSeconds(WAIT_TIME);
GameObject.FindObjectOfType<UserProgressScreen>().DisplayCourses();
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Cleanup after testing
/// </summary>
[TearDown]
public void TearDown_MinigameProgressCard()
{
PersistentDataController.PATH = null;
}
/// <summary>
/// Test whether every item that needs to be assign in the editor, is assigned
/// </summary>
[Test]
public void Test_EditorAssignments()
{
var card = GameObject.FindObjectOfType<CourseProgressCard>();
Assert.IsNotNull(card);
Assert.IsNotNull(card.button);
Assert.IsNotNull(card.courseProgress);
Assert.IsNotNull(card.courseList);
Assert.IsNotNull(card.thumbnail);
Assert.IsNotNull(card.title);
Assert.IsNotNull(card.progressBar);
}
/// <summary>
/// Test whether the card is correctly initialized
/// </summary>
[Test]
public void Test_Start()
{
var card = GameObject.FindObjectOfType<CourseProgressCard>();
Course course = card.courseList.GetCourseByIndex(card.courseProgress.courseIndex);
Assert.AreEqual(course.thumbnail, card.thumbnail.sprite);
Assert.AreEqual(course.title, card.title.text);
Assert.AreEqual(card.courseProgress.progress, card.progressBar.value);
}
}

View File

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

View File

@@ -1,78 +0,0 @@
using NUnit.Framework;
using System.Collections;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
/// <summary>
/// Test the LearnableProgressCard class
/// </summary>
[TestFixture]
public class LearnableProgressCardTests
{
/// <summary>
/// Wait time between scene transitions
/// </summary>
private const float WAIT_TIME = 0.2f;
/// <summary>
/// Setup the LearnableProgressCard tests
/// </summary>
[UnitySetUp]
public IEnumerator Setup_CourseProgressCard()
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string course = "{\"entries\":[],\"courseIndex\":0,\"progress\":0.03846153989434242,\"completedLearnables\":1,\"inUseLearnables\":7,\"totalLearnables\":26,\"learnables\":[{\"entries\":[],\"index\":0,\"inUse\":true,\"name\":\"A\",\"progress\":3.0},{\"entries\":[],\"index\":1,\"inUse\":true,\"name\":\"B\",\"progress\":4.5},{\"entries\":[],\"index\":2,\"inUse\":true,\"name\":\"C\",\"progress\":1.5},{\"entries\":[],\"index\":3,\"inUse\":true,\"name\":\"D\",\"progress\":1.5},{\"entries\":[],\"index\":4,\"inUse\":true,\"name\":\"E\",\"progress\":1.5},{\"entries\":[],\"index\":5,\"inUse\":true,\"name\":\"F\",\"progress\":1.5},{\"entries\":[],\"index\":6,\"inUse\":true,\"name\":\"G\",\"progress\":0.0},{\"entries\":[],\"index\":7,\"inUse\":false,\"name\":\"H\",\"progress\":0.0},{\"entries\":[],\"index\":8,\"inUse\":false,\"name\":\"I\",\"progress\":0.0},{\"entries\":[],\"index\":9,\"inUse\":false,\"name\":\"J\",\"progress\":0.0},{\"entries\":[],\"index\":10,\"inUse\":false,\"name\":\"K\",\"progress\":0.0},{\"entries\":[],\"index\":11,\"inUse\":false,\"name\":\"L\",\"progress\":0.0},{\"entries\":[],\"index\":12,\"inUse\":false,\"name\":\"M\",\"progress\":0.0},{\"entries\":[],\"index\":13,\"inUse\":false,\"name\":\"N\",\"progress\":0.0},{\"entries\":[],\"index\":14,\"inUse\":false,\"name\":\"O\",\"progress\":0.0},{\"entries\":[],\"index\":15,\"inUse\":false,\"name\":\"P\",\"progress\":0.0},{\"entries\":[],\"index\":16,\"inUse\":false,\"name\":\"Q\",\"progress\":0.0},{\"entries\":[],\"index\":17,\"inUse\":false,\"name\":\"R\",\"progress\":0.0},{\"entries\":[],\"index\":18,\"inUse\":false,\"name\":\"S\",\"progress\":0.0},{\"entries\":[],\"index\":19,\"inUse\":false,\"name\":\"T\",\"progress\":0.0},{\"entries\":[],\"index\":20,\"inUse\":false,\"name\":\"U\",\"progress\":0.0},{\"entries\":[],\"index\":21,\"inUse\":false,\"name\":\"V\",\"progress\":0.0},{\"entries\":[],\"index\":22,\"inUse\":false,\"name\":\"W\",\"progress\":0.0},{\"entries\":[],\"index\":23,\"inUse\":false,\"name\":\"X\",\"progress\":0.0},{\"entries\":[],\"index\":24,\"inUse\":false,\"name\":\"Y\",\"progress\":0.0},{\"entries\":[],\"index\":25,\"inUse\":false,\"name\":\"Z\",\"progress\":0.0}]}";
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[{course}]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
yield return new WaitForSeconds(WAIT_TIME);
GameObject.FindObjectOfType<UserProgressScreen>().DisplayCourses();
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Cleanup after testing
/// </summary>
[TearDown]
public void TearDown_MinigameProgressCard()
{
PersistentDataController.PATH = null;
}
/// <summary>
/// Test whether every item that needs to be assign in the editor, is assigned
/// </summary>
[Test]
public void Test_EditorAssignments()
{
var card = GameObject.FindObjectOfType<LearnableProgressCard>();
Assert.IsNotNull(card);
Assert.IsNotNull(card.learnable);
Assert.IsNotNull(card.thumbnail);
Assert.IsNotNull(card.stars);
Assert.AreEqual(3, card.stars.Count);
}
/// <summary>
/// Test whether the card is correctly initialized
/// </summary>
[Test]
public void Test_Start()
{
var card = GameObject.FindObjectOfType<LearnableProgressCard>();
Assert.AreEqual(card.learnable.image, card.thumbnail.sprite);
var starRewards = new float[] { 1.0f, 2.5f, 4.0f, };
for (int i = 0; i < 3; i++)
Assert.AreEqual(starRewards[i] < card.progress.progress ? Color.white : Color.black, card.stars[i].color);
}
}

View File

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

View File

@@ -1,120 +0,0 @@
using NUnit.Framework;
using System.Collections;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
/// <summary>
/// Test the MinigameProgressCard class
/// </summary>
[TestFixture]
public class MinigameProgressCardTests
{
/// <summary>
/// Wait time between scene transitions
/// </summary>
private const float WAIT_TIME = 0.2f;
/// <summary>
/// Setup the MinigameProgressCard tests
/// </summary>
private IEnumerator Setup_MinigameProgressCard()
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string minigame = "{\"entries\":[],\"minigameIndex\":1,\"latestScores\":[{\"scoreValue\":70,\"time\":\"19/04/2023 22:32:39\"},{\"scoreValue\":55,\"time\":\"20/04/2023 11:50:10\"},{\"scoreValue\":55,\"time\":\"20/04/2023 13:27:15\"}],\"highestScores\":[{\"scoreValue\":70,\"time\":\"19/04/2023 22:32:39\"},{\"scoreValue\":55,\"time\":\"20/04/2023 11:50:10\"},{\"scoreValue\":55,\"time\":\"20/04/2023 13:27:15\"}]}";
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[{minigame}],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
yield return new WaitForSeconds(WAIT_TIME);
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Setup the MinigameProgressCard tests
/// </summary>
private IEnumerator Setup_MinigameProgressCard_Empty()
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string minigame = "{\"entries\":[],\"minigameIndex\":0,\"latestScores\":[],\"highestScores\":[]}";
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[{minigame}],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
yield return new WaitForSeconds(WAIT_TIME);
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Cleanup after testing
/// </summary>
[TearDown]
public void TearDown_MinigameProgressCard()
{
PersistentDataController.PATH = null;
}
/// <summary>
/// Test whether every item that needs to be assign in the editor, is assigned
/// </summary>
[UnityTest]
public IEnumerator Test_EditorAssignments()
{
yield return Setup_MinigameProgressCard();
var card = GameObject.FindObjectOfType<MinigameProgressCard>();
Assert.IsNotNull(card);
Assert.IsNotNull(card.button);
Assert.IsNotNull(card.minigameProgress);
Assert.IsNotNull(card.minigameList);
Assert.IsNotNull(card.thumbnail);
Assert.IsNotNull(card.title);
Assert.IsNotNull(card.highscore);
}
/// <summary>
/// Test whether the card is correctly initialized
/// </summary>
[UnityTest]
public IEnumerator Test_Start()
{
yield return Setup_MinigameProgressCard();
var card = GameObject.FindObjectOfType<MinigameProgressCard>();
Minigame minigame = card.minigameList.GetMinigameByIndex(card.minigameProgress.minigameIndex);
Assert.AreEqual(minigame.thumbnail, card.thumbnail.sprite);
Assert.AreEqual(minigame.title, card.title.text);
Assert.AreEqual($"TOPSCORE: {card.minigameProgress.highestScores[0].scoreValue}", card.highscore.text);
}
/// <summary>
/// Test whether an empty card is correctly initialized
/// </summary>
[UnityTest]
public IEnumerator Test_Start_Empty()
{
yield return Setup_MinigameProgressCard_Empty();
var card = GameObject.FindObjectOfType<MinigameProgressCard>();
Minigame minigame = card.minigameList.GetMinigameByIndex(card.minigameProgress.minigameIndex);
Assert.AreEqual(minigame.thumbnail, card.thumbnail.sprite);
Assert.AreEqual(minigame.title, card.title.text);
Assert.AreEqual("(NOG) GEEN TOPSCORE", card.highscore.text);
}
}

View File

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

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -1,199 +0,0 @@
using NUnit.Framework;
using System.Collections;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
using UnityEngine.UI;
/// <summary>
/// Test the PanelMinigameProgress class
/// </summary>
[TestFixture]
public class PanelMinigameProgressTests
{
/// <summary>
/// Wait time between scene transitions
/// </summary>
private const float WAIT_TIME = 0.2f;
/// <summary>
/// Setup the PanelMinigameProgress tests
/// </summary>
private IEnumerator Setup_PanelMinigameProgress()
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string minigame = "{\"entries\":[],\"minigameIndex\":1,\"latestScores\":[{\"scoreValue\":70,\"time\":\"19/04/2023 22:32:39\"},{\"scoreValue\":55,\"time\":\"20/04/2023 11:50:10\"},{\"scoreValue\":55,\"time\":\"20/04/2023 13:27:15\"}],\"highestScores\":[{\"scoreValue\":70,\"time\":\"19/04/2023 22:32:39\"},{\"scoreValue\":55,\"time\":\"20/04/2023 11:50:10\"},{\"scoreValue\":55,\"time\":\"20/04/2023 13:27:15\"}]}";
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[{minigame}],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
yield return new WaitForSeconds(WAIT_TIME);
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Setup the PanelMinigameProgress tests
/// </summary>
private IEnumerator Setup_PanelMinigameProgress_Empty()
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
yield return new WaitForSeconds(WAIT_TIME);
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Setup the PanelMinigameProgress tests
/// </summary>
private IEnumerator Setup_PanelMinigameProgress_NoScorePresent()
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string minigame = "{\"entries\":[],\"minigameIndex\":1,\"latestScores\":[],\"highestScores\":[]}";
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[{minigame}],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
yield return new WaitForSeconds(WAIT_TIME);
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Setup the PanelMinigameProgress tests
/// </summary>
private IEnumerator Setup_PanelMinigameProgress_Multiple()
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string minigame = "[{\"entries\":[],\"minigameIndex\":1,\"latestScores\":[{\"scoreValue\":70,\"time\":\"20/04/2023 16:08:43\"},{\"scoreValue\":20,\"time\":\"20/04/2023 16:11:53\"}],\"highestScores\":[{\"scoreValue\":70,\"time\":\"20/04/2023 16:08:43\"},{\"scoreValue\":20,\"time\":\"20/04/2023 16:11:53\"}]},{\"entries\":[],\"minigameIndex\":2,\"latestScores\":[{\"scoreValue\":194,\"time\":\"20/04/2023 15:27:41\"},{\"scoreValue\":155,\"time\":\"20/04/2023 15:28:56\"},{\"scoreValue\":84,\"time\":\"20/04/2023 15:42:10\"},{\"scoreValue\":465,\"time\":\"20/04/2023 16:14:22\"}],\"highestScores\":[{\"scoreValue\":465,\"time\":\"20/04/2023 16:14:22\"},{\"scoreValue\":194,\"time\":\"20/04/2023 15:27:41\"},{\"scoreValue\":155,\"time\":\"20/04/2023 15:28:56\"},{\"scoreValue\":84,\"time\":\"20/04/2023 15:42:10\"}]},{\"entries\":[],\"minigameIndex\":0,\"latestScores\":[{\"scoreValue\":1090,\"time\":\"20/04/2023 16:02:14\"},{\"scoreValue\":1180,\"time\":\"20/04/2023 16:07:02\"}],\"highestScores\":[{\"scoreValue\":1180,\"time\":\"20/04/2023 16:07:02\"},{\"scoreValue\":1090,\"time\":\"20/04/2023 16:02:14\"}]}]";
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":{minigame},\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
yield return new WaitForSeconds(WAIT_TIME);
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Cleanup after testing
/// </summary>
[TearDown]
public void TearDown_PanelMinigameProgress()
{
PersistentDataController.PATH = null;
}
/// <summary>
/// Test whether every item that needs to be assign in the editor, is assigned
/// </summary>
[UnityTest]
public IEnumerator Test_EditorAssignments()
{
yield return Setup_PanelMinigameProgress();
var panel = GameObject.FindObjectOfType<PanelMinigameProgress>();
Assert.IsNotNull(panel);
Assert.IsNotNull(panel.minigameList);
Assert.IsNotNull(panel.minigameCardPrefab);
Assert.IsNotNull(panel.minigamesContainer);
Assert.IsNotNull(panel.minigameInfo);
Assert.IsNotNull(panel.emptyMinigames);
Assert.IsNotNull(panel.minigameTitle);
Assert.IsNotNull(panel.progressGraph);
Assert.IsNotNull(panel.emptyHighscore);
}
/// <summary>
/// Test whether the panel is correctly initialized
/// </summary>
[UnityTest]
public IEnumerator Test_Start()
{
yield return Setup_PanelMinigameProgress();
var panel = GameObject.FindObjectOfType<PanelMinigameProgress>();
Assert.IsTrue(panel.minigameInfo.gameObject.activeSelf);
Assert.IsFalse(panel.emptyMinigames.gameObject.activeSelf);
Assert.IsFalse(panel.emptyHighscore.gameObject.activeSelf);
Assert.IsTrue(panel.progressGraph.gameObject.activeSelf);
var minigame = panel.minigameList.GetMinigameByIndex(MinigameIndex.HANGMAN);
Assert.AreEqual(minigame.title, panel.minigameTitle.text);
}
/// <summary>
/// Test whether the panel is correctly initialized when there is no minigame progress
/// </summary>
[UnityTest]
public IEnumerator Test_Start_Empty()
{
yield return Setup_PanelMinigameProgress_Empty();
var panel = GameObject.FindObjectOfType<PanelMinigameProgress>();
Assert.IsFalse(panel.minigameInfo.gameObject.activeSelf);
Assert.IsTrue(panel.emptyMinigames.gameObject.activeSelf);
}
/// <summary>
/// Test whether the panel is correctly initialized when there are minigames, but these don't have any score
/// </summary>
[UnityTest]
public IEnumerator Test_Start_NoScorePresent()
{
yield return Setup_PanelMinigameProgress_NoScorePresent();
var panel = GameObject.FindObjectOfType<PanelMinigameProgress>();
Assert.IsTrue(panel.minigameInfo.gameObject.activeSelf);
Assert.IsFalse(panel.emptyMinigames.gameObject.activeSelf);
Assert.IsTrue(panel.emptyHighscore.gameObject.activeSelf);
Assert.IsFalse(panel.progressGraph.gameObject.activeSelf);
}
/// <summary>
/// Test whether we can select a minigame
/// </summary>
[UnityTest]
public IEnumerator Test_UpdateSelection()
{
yield return Setup_PanelMinigameProgress_Multiple();
var panel = GameObject.FindObjectOfType<PanelMinigameProgress>();
var minigames = GameObject.FindObjectsOfType<MinigameProgressCard>();
var currentMinigame = minigames[0];
currentMinigame.selectActivity.Invoke();
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(new Color(66 / 255f, 158 / 255f, 189 / 255f, 1f), currentMinigame.GetComponent<Image>().color);
for (int i = 1; i < minigames.Length; i++)
Assert.AreEqual(new Color(159 / 255f, 231 / 255f, 245 / 255f, 120 / 255f), minigames[i].GetComponent<Image>().color);
Assert.AreEqual(currentMinigame.title.text, panel.minigameTitle.text);
}
}

View File

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

View File

@@ -1,152 +0,0 @@
using NUnit.Framework;
using System;
using System.Collections;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
/// <summary>
/// Test the ProgressGraph class
/// </summary>
[TestFixture]
public class ProgressGraphTests
{
/// <summary>
/// Wait time between scene transitions
/// </summary>
private const float WAIT_TIME = 0.2f;
/// <summary>
/// Setup the ProgressGraph tests
/// </summary>
private IEnumerator Setup_ProgressGraph(int amount, Func<int, int> f)
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string score = "";
for (int i = 0; i < amount; i++)
{
score += $"{{\"scoreValue\":{f(i)},\"time\":\"19/04/2023 22:32:39\"}}";
if (i < amount - 1)
score += ",";
}
string minigame = $"{{\"entries\":[],\"minigameIndex\":1,\"latestScores\":[{score}],\"highestScores\":[{score}]}}";
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[{minigame}],\"courses\":[]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
yield return new WaitForSeconds(WAIT_TIME);
GameObject.FindObjectOfType<UserProgressScreen>().DisplayMinigames();
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Test whether every item that needs to be assign in the editor, is assigned
/// </summary>
[UnityTest]
public IEnumerator Test_EditorAssignments()
{
yield return Setup_ProgressGraph(1, (i) => i);
var graph = GameObject.FindObjectOfType<ProgressGraph>();
Assert.IsNotNull(graph);
Assert.IsNotNull(graph.progressGraph);
Assert.IsNotNull(graph.highscoreMarker);
Assert.IsNotNull(graph.axesTickMarker);
}
/// <summary>
/// Test whether negative values are correctly plotted
/// </summary>
[UnityTest]
public IEnumerator Test_PlotGraph_Negative()
{
yield return Setup_ProgressGraph(4, (i) => -5 * (i + 1));
yield return new WaitForSeconds(5.0f);
Assert.IsTrue(true);
}
/// <summary>
/// Test whether values between 0 and 1 are correctly plotted
/// </summary>
[UnityTest]
public IEnumerator Test_PlotGraph_SmallerThen1()
{
yield return Setup_ProgressGraph(4, (i) => (3 * i + 20) / 100);
yield return new WaitForSeconds(5.0f);
Assert.IsTrue(true);
}
/// <summary>
/// Test whether values around 0 are correctly plotted
/// </summary>
[UnityTest]
public IEnumerator Test_PlotGraph_AroundZero()
{
yield return Setup_ProgressGraph(4, (i) => 5 * i - 10);
yield return new WaitForSeconds(5.0f);
Assert.IsTrue(true);
}
/// <summary>
/// Test whether all 0 values are correctly plotted
/// </summary>
[UnityTest]
public IEnumerator Test_PlotGraph_AllZeros()
{
yield return Setup_ProgressGraph(4, (i) => 0);
yield return new WaitForSeconds(5.0f);
Assert.IsTrue(true);
}
/// <summary>
/// Test whether values between -1 and 1 are correctly plotted
/// </summary>
[UnityTest]
public IEnumerator Test_PlotGraph_BetweenPos1AndNeg1()
{
yield return Setup_ProgressGraph(10, (i) => (i % 3) - 1);
yield return new WaitForSeconds(5.0f);
Assert.IsTrue(true);
}
/// <summary>
/// Test whether a single value is correctly plotted
/// </summary>
[UnityTest]
public IEnumerator Test_PlotGraph_Single()
{
yield return Setup_ProgressGraph(1, (i) => i + 500);
yield return new WaitForSeconds(5.0f);
Assert.IsTrue(true);
}
/// <summary>
/// Test whether multiple values are correctly plotted
/// </summary>
[UnityTest]
public IEnumerator Test_PlotGraph_Multiple()
{
yield return Setup_ProgressGraph(5, (i) => 5 * i);
yield return new WaitForSeconds(5.0f);
Assert.IsTrue(true);
}
/// <summary>
/// Test whether too many values (capped at 10) are correctly plotted
/// </summary>
[UnityTest]
public IEnumerator Test_PlotGraph_TooMany()
{
yield return Setup_ProgressGraph(10, (i) => 5 * i);
yield return new WaitForSeconds(5.0f);
Assert.IsTrue(true);
}
}

View File

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

View File

@@ -1,71 +0,0 @@
using NUnit.Framework;
using System.Collections;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
/// <summary>
/// Test the UserCard class
/// </summary>
[TestFixture]
public class UserCardTests
{
/// <summary>
/// Wait time between scene transitions
/// </summary>
private const float WAIT_TIME = 0.2f;
/// <summary>
/// Setup the tests
/// </summary>
[UnitySetUp]
public IEnumerator Setup_UserCard()
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string oneUser = "{\"version\":1537,\"users\":[{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene("Accounts/Scenes/ChangeUserScreen");
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Cleanup after testing
/// </summary>
[TearDown]
public void TearDown_UserCard()
{
PersistentDataController.PATH = null;
}
/// <summary>
/// Test whether every item that needs to be assign in the editor, is assigned
/// </summary>
[Test]
public void Test_EditorAssignments()
{
var card = GameObject.FindObjectOfType<UserCard>();
Assert.IsNotNull(card);
Assert.IsNotNull(card.user);
Assert.IsNotNull(card.button);
Assert.IsNotNull(card.avatar);
Assert.IsNotNull(card.username);
}
/// <summary>
/// Test whether the card is correctly initialized
/// </summary>
[Test]
public void Test_Start()
{
var card = GameObject.FindObjectOfType<UserCard>();
Assert.AreEqual(card.user.GetAvatar(), card.avatar.sprite);
Assert.AreEqual(card.user.GetUsername(), card.username.text);
}
}

View File

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

View File

@@ -1,173 +0,0 @@
using NUnit.Framework;
using System.Collections;
using System.IO;
using System.Linq;
using TMPro;
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
using UnityEngine.UI;
/// <summary>
/// Test the UserCreationScreen class
/// </summary>
[TestFixture]
public class UserCreationScreenTests
{
/// <summary>
/// Wait time between scene transitions
/// </summary>
private const float WAIT_TIME = 0.2f;
/// <summary>
/// Setup the UserCreationScreen tests
/// </summary>
private IEnumerator Setup_UserCreationScreen(string startScreen = "Accounts/Scenes/UserCreationScreen")
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string oneUser = "{\"version\":1537,\"users\":[{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[],\"courses\":[]}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene(startScreen);
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Cleanup after testing
/// </summary>
[TearDown]
public void TearDown_UserCreationScreen()
{
PersistentDataController.PATH = null;
}
/// <summary>
/// Test whether every item that needs to be assign in the editor, is assigned
/// </summary>
[UnityTest]
public IEnumerator Test_EditorAssignments()
{
yield return Setup_UserCreationScreen();
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
Assert.IsNotNull(userCreationController);
Assert.IsNotNull(userCreationController.errorMessage);
Assert.IsNotNull(userCreationController.inputName);
Assert.IsNotNull(userCreationController.avatarsContainer);
Assert.IsNotNull(userCreationController.avatarPrefab);
Assert.IsNotNull(userCreationController.backButton);
Assert.IsTrue(UserCreationScreen.canGoBack);
}
/// <summary>
/// Test whether the screen is correctly initialized
/// </summary>
[UnityTest]
public IEnumerator Test_Start()
{
yield return Setup_UserCreationScreen();
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
Assert.IsFalse(userCreationController.errorMessage.activeSelf);
Assert.IsTrue(userCreationController.backButton.activeSelf);
var avatars = userCreationController.avatarsContainer.GetComponentsInChildren<Button>().ToList()
.ConvertAll((b) => b.GetComponentsInChildren<Image>().Except(b.GetComponents<Image>()).First());
Assert.AreEqual(UserList.AVATARS.Count, avatars.Count);
for (int i = 0; i < avatars.Count; i++)
Assert.AreEqual(UserList.AVATARS[i], avatars[i].sprite);
}
/// <summary>
/// Test whether the screen is correctly initialized (from invalid savefile)
/// </summary>
[UnityTest]
public IEnumerator Test_Start_InvalidSavefile()
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
File.Delete(path);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene("Common/Scenes/Boot");
yield return new WaitForSeconds(WAIT_TIME);
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
Assert.IsNotNull(userCreationController);
Assert.IsFalse(userCreationController.backButton.activeSelf);
}
/// <summary>
/// Test whether a new user can be created
/// </summary>
[UnityTest]
public IEnumerator Test_CreateUser_Valid()
{
yield return Setup_UserCreationScreen("Common/Scenes/MainMenuScreen");
SystemController.GetInstance().LoadNextScene("Accounts/Scenes/UserCreationScreen");
yield return new WaitForSeconds(WAIT_TIME);
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
userCreationController.inputName.text = "newTester";
userCreationController.CreateUser();
Assert.IsFalse(userCreationController.errorMessage.activeSelf);
yield return new WaitForSeconds(WAIT_TIME);
Assert.AreEqual(SystemController.GetSceneIndex("Common/Scenes/MainMenuScreen"), SystemController.GetInstance().currentScene);
}
/// <summary>
/// Test whether no new user is created when the username is too long
/// </summary>
[UnityTest]
public IEnumerator Test_CreateUser_UsernameTooLong()
{
yield return Setup_UserCreationScreen();
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
userCreationController.inputName.text = "aninvalidsuperduperlongusername";
userCreationController.CreateUser();
Assert.IsTrue(userCreationController.errorMessage.activeSelf);
Assert.AreEqual("Je gebruikersnaam moet bestaan uit minimum 1 en maximum 12 letters (a-z en A-Z) of cijfers (0-9).", userCreationController.errorMessage.GetComponent<TMP_Text>().text);
}
/// <summary>
/// Test whether no new user is created when the username contains invalid characters
/// </summary>
[UnityTest]
public IEnumerator Test_CreateUser_UsernameInvalidChars()
{
yield return Setup_UserCreationScreen();
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
userCreationController.inputName.text = "! an invalid username !";
userCreationController.CreateUser();
Assert.IsTrue(userCreationController.errorMessage.activeSelf);
Assert.AreEqual("Je gebruikersnaam moet bestaan uit minimum 1 en maximum 12 letters (a-z en A-Z) of cijfers (0-9).", userCreationController.errorMessage.GetComponent<TMP_Text>().text);
}
/// <summary>
/// Test whether no new user is created when the username already exists
/// </summary>
[UnityTest]
public IEnumerator Test_CreateUser_UsernameAlreadyExists()
{
yield return Setup_UserCreationScreen();
var userCreationController = GameObject.FindObjectOfType<UserCreationScreen>();
userCreationController.inputName.text = "Tester0";
userCreationController.CreateUser();
Assert.IsTrue(userCreationController.errorMessage.activeSelf);
Assert.AreEqual("Deze gebruikersnaam bestaat al! Kies een andere.", userCreationController.errorMessage.GetComponent<TMP_Text>().text);
}
}

View File

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

View File

@@ -1,138 +0,0 @@
using NUnit.Framework;
using System.Collections;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
/// <summary>
/// Test the UserProgressScreen class
/// </summary>
[TestFixture]
public class UserProgressScreenTests
{
/// <summary>
/// Wait time between scene transitions
/// </summary>
private const float WAIT_TIME = 0.2f;
/// <summary>
/// Setup the UserProgressScreen tests
/// </summary>
private IEnumerator Setup_UserProgressScreen(bool progress = true)
{
string path = $"{Application.persistentDataPath}/wesign_unit_test.json";
string course = "{\"entries\":[],\"courseIndex\":0,\"progress\":0.03846153989434242,\"completedLearnables\":1,\"inUseLearnables\":7,\"totalLearnables\":26,\"learnables\":[{\"entries\":[],\"index\":0,\"inUse\":true,\"name\":\"A\",\"progress\":3.0},{\"entries\":[],\"index\":1,\"inUse\":true,\"name\":\"B\",\"progress\":4.5},{\"entries\":[],\"index\":2,\"inUse\":true,\"name\":\"C\",\"progress\":1.5},{\"entries\":[],\"index\":3,\"inUse\":true,\"name\":\"D\",\"progress\":1.5},{\"entries\":[],\"index\":4,\"inUse\":true,\"name\":\"E\",\"progress\":1.5},{\"entries\":[],\"index\":5,\"inUse\":true,\"name\":\"F\",\"progress\":1.5},{\"entries\":[],\"index\":6,\"inUse\":true,\"name\":\"G\",\"progress\":0.0},{\"entries\":[],\"index\":7,\"inUse\":false,\"name\":\"H\",\"progress\":0.0},{\"entries\":[],\"index\":8,\"inUse\":false,\"name\":\"I\",\"progress\":0.0},{\"entries\":[],\"index\":9,\"inUse\":false,\"name\":\"J\",\"progress\":0.0},{\"entries\":[],\"index\":10,\"inUse\":false,\"name\":\"K\",\"progress\":0.0},{\"entries\":[],\"index\":11,\"inUse\":false,\"name\":\"L\",\"progress\":0.0},{\"entries\":[],\"index\":12,\"inUse\":false,\"name\":\"M\",\"progress\":0.0},{\"entries\":[],\"index\":13,\"inUse\":false,\"name\":\"N\",\"progress\":0.0},{\"entries\":[],\"index\":14,\"inUse\":false,\"name\":\"O\",\"progress\":0.0},{\"entries\":[],\"index\":15,\"inUse\":false,\"name\":\"P\",\"progress\":0.0},{\"entries\":[],\"index\":16,\"inUse\":false,\"name\":\"Q\",\"progress\":0.0},{\"entries\":[],\"index\":17,\"inUse\":false,\"name\":\"R\",\"progress\":0.0},{\"entries\":[],\"index\":18,\"inUse\":false,\"name\":\"S\",\"progress\":0.0},{\"entries\":[],\"index\":19,\"inUse\":false,\"name\":\"T\",\"progress\":0.0},{\"entries\":[],\"index\":20,\"inUse\":false,\"name\":\"U\",\"progress\":0.0},{\"entries\":[],\"index\":21,\"inUse\":false,\"name\":\"V\",\"progress\":0.0},{\"entries\":[],\"index\":22,\"inUse\":false,\"name\":\"W\",\"progress\":0.0},{\"entries\":[],\"index\":23,\"inUse\":false,\"name\":\"X\",\"progress\":0.0},{\"entries\":[],\"index\":24,\"inUse\":false,\"name\":\"Y\",\"progress\":0.0},{\"entries\":[],\"index\":25,\"inUse\":false,\"name\":\"Z\",\"progress\":0.0}]}";
string minigame = "{\"entries\":[],\"minigameIndex\":1,\"latestScores\":[{\"scoreValue\":70,\"time\":\"19/04/2023 22:32:39\"},{\"scoreValue\":55,\"time\":\"20/04/2023 11:50:10\"},{\"scoreValue\":55,\"time\":\"20/04/2023 13:27:15\"}],\"highestScores\":[{\"scoreValue\":70,\"time\":\"19/04/2023 22:32:39\"},{\"scoreValue\":55,\"time\":\"20/04/2023 11:50:10\"},{\"scoreValue\":55,\"time\":\"20/04/2023 13:27:15\"}]}";
if (!progress) course = minigame = "";
string oneUser = $"{{\"version\":1537,\"users\":[{{\"entries\":[],\"username\":\"Tester0\",\"avatarIndex\":0,\"playtime\":0.0,\"minigames\":[{minigame}],\"courses\":[{course}]}}],\"currentUser\":0,\"currentMinigame\":0,\"currentCourse\":0,\"currentTheme\":0,\"useGPU\":false}}";
File.WriteAllText(path, oneUser);
PersistentDataController.PATH = path;
PersistentDataController.GetInstance().Load();
AssetDatabase.LoadAssetAtPath<UserAvatarList>("Assets/Accounts/ScriptableObjects/UserAvatarList.asset").Awake();
SystemController.GetInstance().SwapScene("Accounts/Scenes/UserProgressScreen");
yield return new WaitForSeconds(WAIT_TIME);
}
/// <summary>
/// Cleanup after testing
/// </summary>
[TearDown]
public void TearDown_UserProgressScreen()
{
PersistentDataController.PATH = null;
}
/// <summary>
/// Test whether every item that needs to be assign in the editor, is assigned
/// </summary>
[UnityTest]
public IEnumerator Test_EditorAssignments()
{
yield return Setup_UserProgressScreen();
var userProgressController = GameObject.FindObjectOfType<UserProgressScreen>();
Assert.IsNotNull(userProgressController.username);
Assert.IsNotNull(userProgressController.avatar);
Assert.IsNotNull(userProgressController.coursesPanel);
Assert.IsNotNull(userProgressController.coursesTabButton);
Assert.IsNotNull(userProgressController.minigamesPanel);
Assert.IsNotNull(userProgressController.minigamesTabButton);
}
/// <summary>
/// Test whether the screen is correctly initialized
/// </summary>
[UnityTest]
public IEnumerator Test_Start_NoProgress()
{
yield return Setup_UserProgressScreen(false);
var userProgressController = GameObject.FindObjectOfType<UserProgressScreen>();
var user = UserList.GetCurrentUser();
Assert.AreEqual(user.GetUsername(), userProgressController.username.text);
Assert.AreEqual(user.GetAvatar(), userProgressController.avatar.sprite);
Assert.IsTrue(userProgressController.coursesPanel.activeSelf);
Assert.Zero(GameObject.FindObjectsOfType<CourseProgressCard>().Length);
Assert.IsFalse(userProgressController.minigamesPanel.activeSelf);
}
/// <summary>
/// Test whether the screen is correctly initialized
/// </summary>
[UnityTest]
public IEnumerator Test_Start_WithProgress()
{
yield return Setup_UserProgressScreen();
var userProgressController = GameObject.FindObjectOfType<UserProgressScreen>();
var user = UserList.GetCurrentUser();
Assert.AreEqual(user.GetUsername(), userProgressController.username.text);
Assert.AreEqual(user.GetAvatar(), userProgressController.avatar.sprite);
Assert.IsTrue(userProgressController.coursesPanel.activeSelf);
var courses = GameObject.FindObjectsOfType<CourseProgressCard>().ToList();
Assert.AreEqual(user.GetCourses().Count, courses.Count);
Assert.IsFalse(userProgressController.minigamesPanel.activeSelf);
}
/// <summary>
/// Test whether the course panel is displayed
/// </summary>
[UnityTest]
public IEnumerator Test_DisplayCourses()
{
yield return Setup_UserProgressScreen();
var userProgressController = GameObject.FindObjectOfType<UserProgressScreen>();
userProgressController.DisplayCourses();
yield return new WaitForSeconds(WAIT_TIME);
Assert.IsTrue(userProgressController.coursesPanel.activeSelf);
Assert.IsFalse(userProgressController.minigamesPanel.activeSelf);
}
/// <summary>
/// Test whether the minigames panel is displayed
/// </summary>
/// <returns></returns>
[UnityTest]
public IEnumerator Test_DisplayMinigames()
{
yield return Setup_UserProgressScreen();
var userProgressController = GameObject.FindObjectOfType<UserProgressScreen>();
userProgressController.DisplayMinigames();
yield return new WaitForSeconds(WAIT_TIME);
Assert.IsFalse(userProgressController.coursesPanel.activeSelf);
Assert.IsTrue(userProgressController.minigamesPanel.activeSelf);
}
}

View File

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

View File

@@ -0,0 +1,233 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using UnityEngine;
/// <summary>
/// Test the Progress class
/// </summary>
public class TestProgress
{
/// <summary>
/// A dummy serializable struct to perform test operations on
/// </summary>
[Serializable]
private struct SerializableStruct
{
public int r, g, b;
public float x, y, z;
}
/// <summary>
/// A dummy non-serializable struct to perform test operations on
/// </summary>
private struct NonSerializableStruct
{
public int r, g, b;
public float x, y, z;
}
/// <summary>
/// Helper method
/// </summary>
/// <returns><c>true</c> if <c>Progress.AddOrUpdate(...)</c> throws a <c>SerializationException</c></returns>
private bool AddNonSerializableStruct()
{
Progress progress = new Progress();
NonSerializableStruct nss = new NonSerializableStruct();
try { progress.AddOrUpdate<NonSerializableStruct>("key", nss); }
catch (SerializationException) { return true; }
return false;
}
/// <summary>
/// Helper method
/// </summary>
/// <returns><c>true</c> if <c>Progress.Get(...)</c> throws a <c>KeyNotFoundException</c></returns>
private bool AccessInvalidKey()
{
Progress progress = new Progress();
try { progress.Get<int>("non-existing key"); }
catch (KeyNotFoundException) { return true; }
return false;
}
/// <summary>
/// Helper method
/// </summary>
/// <returns><c>true</c> if <c>Progress.Get(...)</c> throws a <c>InvalidCastException</c></returns>
private bool AccessInvalidType()
{
Progress progress = new Progress();
progress.AddOrUpdate<int>("key", 123456789);
try { progress.Get<double>("key"); }
catch (InvalidCastException) { return true; }
return false;
}
/// <summary>
/// Test for creation of a new progress
/// </summary>
[Test]
public void TestNewProgress()
{
Progress progress = new Progress();
Debug.Assert(progress != null);
}
/// <summary>
/// Test whether invalid data will not be added
/// </summary>
[Test]
public void TestProgressAddInvalidData()
{
Progress progress = new Progress();
Debug.Assert(!progress.AddOrUpdate<GameObject>("key", null));
}
/// <summary>
/// Test whether a duplicated key will be added
/// </summary>
[Test]
public void TestProgressAddDuplicateKey()
{
Progress progress = new Progress();
progress.AddOrUpdate<int>("key 1", 0);
Debug.Assert(progress.AddOrUpdate<int>("key 1", 1));
}
/// <summary>
/// Test whether a <c>int</c> value can be added
/// </summary>
[Test]
public void TestProgressAddInt()
{
Progress progress = new Progress();
Debug.Assert(progress.AddOrUpdate<int>("key", 1));
}
/// <summary>
/// Test whether a <c>double</c> value can be added
/// </summary>
[Test]
public void TestProgressAddDouble()
{
Progress progress = new Progress();
Debug.Assert(progress.AddOrUpdate<double>("key", 1.0));
}
/// <summary>
/// Test whether a <c>string</c> value can be added
/// </summary>
[Test]
public void TestProgressAddString()
{
Progress progress = new Progress();
Debug.Assert(progress.AddOrUpdate<string>("key", "Hello World!"));
}
/// <summary>
/// Test whether a serializable struct can be added
/// </summary>
[Test]
public void TestProgressAddSerializableStruct()
{
Progress progress = new Progress();
Debug.Assert(progress.AddOrUpdate<SerializableStruct>("key", new SerializableStruct()));
}
/// <summary>
/// Test whether a non-serializable struct will throw an error
/// </summary>
[Test]
public void TestProgressAddNonSerializableStruct()
{
Debug.Assert(AddNonSerializableStruct());
}
/// <summary>
/// Test whether an invalid key will throw an error
/// </summary>
[Test]
public void TestProgressGetInvalidKey()
{
Debug.Assert(AccessInvalidKey());
}
/// <summary>
/// Test whether an invalid type will throw an error
/// </summary>
[Test]
public void TestProgressGetInvalidType()
{
Debug.Assert(AccessInvalidType());
}
/// <summary>
/// Test whether a value is correctly updated
/// </summary>
[Test]
public void TestProgressUpdate()
{
Progress progress = new Progress();
progress.AddOrUpdate<int>("key", 1);
Debug.Assert(progress.Get<int>("key") == 1);
progress.AddOrUpdate<int>("key", 2);
Debug.Assert(progress.Get<int>("key") == 2);
}
/// <summary>
/// Test whether a <c>int</c> value can be read
/// </summary>
[Test]
public void TestProgressGetInt()
{
Progress progress = new Progress();
progress.AddOrUpdate<int>("key", 1);
Debug.Assert(progress.Get<int>("key") == 1);
}
/// <summary>
/// Test whether a <c>double</c> value can be read
/// </summary>
[Test]
public void TestProgressGetDouble()
{
Progress progress = new Progress();
progress.AddOrUpdate<double>("key", 1.0);
Debug.Assert(progress.Get<double>("key") == 1.0);
}
/// <summary>
/// Test whether a <c>string</c> value can be read
/// </summary>
[Test]
public void TestProgressGetString()
{
Progress progress = new Progress();
progress.AddOrUpdate<string>("key", "Hello World!");
Debug.Assert(progress.Get<string>("key") == "Hello World!");
}
/// <summary>
/// Test whether a serializable struct can be read
/// </summary>
[Test]
public void TestProgressGetStruct()
{
Progress progress = new Progress();
int R = 1, G = 10, B = 100;
float X = 0.1f, Y = 0.01f, Z = 0.001f;
SerializableStruct data = new SerializableStruct { r = R, g = G, b = B, x = X, y = Y, z = Z };
progress.AddOrUpdate<SerializableStruct>("key", data);
SerializableStruct result = progress.Get<SerializableStruct>("key");
Debug.Assert(result.r == R);
Debug.Assert(result.g == G);
Debug.Assert(result.b == B);
Debug.Assert(result.x == X);
Debug.Assert(result.y == Y);
Debug.Assert(result.z == Z);
}
}

View File

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

View File

@@ -0,0 +1,30 @@
using UnityEngine;
/// <summary>
/// Test the UserCreationScreen class
/// </summary>
public class TestUserCreationScreen
{
/// <summary>
/// Tets IsValidUsername will return <c>true</c> for an valid username
/// </summary>
public void TestIsValidUsernameTrue()
{
foreach (char c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
Debug.Assert(UserCreationScreen.IsValidUsername(c.ToString()));
Debug.Assert(UserCreationScreen.IsValidUsername("123456789AbC"));
}
/// <summary>
/// Tets IsValidUsername will return <c>false</c> for an invalid username
/// </summary>
public void TestIsValidUsernameFalse()
{
Debug.Assert(!UserCreationScreen.IsValidUsername(string.Empty));
foreach (char c in " \n\t+-*/%_.,;:!?(){}[]\\'\"|&~^$")
Debug.Assert(!UserCreationScreen.IsValidUsername(c.ToString()));
Debug.Assert(!UserCreationScreen.IsValidUsername("123456789_10_11_12_13"));
}
}

View File

@@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Test the User class
/// </summary>
public class TestUser
{
/// <summary>
/// Test for the creation of a new user
/// </summary>
public void TestNewUser()
{
User user = new User();
Debug.Assert(user != null);
Debug.Assert(user.courses.Count == 0);
Debug.Assert(user.minigames.Count == 0);
}
/// <summary>
/// Test whether progress on a new course can be added
/// </summary>
public void TestUserAddCourse()
{
User user = new User();
Progress p = new Progress();
user.courses.Add(p);
Debug.Assert(user.courses.Count == 1);
Debug.Assert(user.minigames.Count == 0);
}
/// <summary>
/// Test whether progress on a new minigame can be added
/// </summary>
public void TestUserAddMinigame()
{
User user = new User();
Progress p = new Progress();
user.minigames.Add(p);
Debug.Assert(user.courses.Count == 0);
Debug.Assert(user.minigames.Count == 1);
}
/// <summary>
/// Test GetRecentCourses will return empty when no progress is stored
/// </summary>
public void TestGetRecentCoursesEmpty()
{
User user = new User();
Debug.Assert(user.GetRecentCourses().Count == 0);
}
/// <summary>
/// Temporary test for GetRecentCourses will return all progress that is stored
/// </summary>
public void TestGetRecentCoursesAll()
{
User user = new User();
Progress p = new Progress();
p.AddOrUpdate<CourseIndex>("courseIndex", CourseIndex.FINGERSPELLING);
p.AddOrUpdate<float>("courseProgress", 0.5f);
user.courses.Add(p);
List<Tuple<CourseIndex, float>> list = user.GetRecentCourses();
Debug.Assert(list.Count == 1);
Debug.Assert(list[0].Item1 == CourseIndex.FINGERSPELLING);
Debug.Assert(list[0].Item2 == 0.5f);
}
/// <summary>
/// Test GetRecommendedCourses will return <c>Tuple<CourseIndex.FINGERSPELLING, 0.0></c> when no progress is stored
/// </summary>
public void TestGetRecommendedCoursesEmpty()
{
User user = new User();
List<Tuple<CourseIndex, float>> list = user.GetRecommendedCourses();
Debug.Assert(list.Count == 1);
Debug.Assert(list[0].Item1 == CourseIndex.FINGERSPELLING);
Debug.Assert(list[0].Item2 == 0.0f);
}
/// <summary>
/// Temporary test for GetRecommenedCourses will return all progress that is stored
/// </summary>
public void TestGetRecommendedCoursesAll()
{
User user = new User();
Progress p = new Progress();
p.AddOrUpdate<CourseIndex>("courseIndex", CourseIndex.FINGERSPELLING);
p.AddOrUpdate<float>("courseProgress", 0.5f);
user.courses.Add(p);
List<Tuple<CourseIndex, float>> list = user.GetRecommendedCourses();
Debug.Assert(list.Count == 1);
Debug.Assert(list[0].Item1 == CourseIndex.FINGERSPELLING);
Debug.Assert(list[0].Item2 == 0.5f);
}
/// <summary>
/// Test GetCourseProgress returns null when course cannot be found
/// </summary>
public void TestGetCourseProgressNull()
{
User user = new User();
Debug.Assert(user.GetCourseProgress(CourseIndex.FINGERSPELLING) == null);
Debug.Assert(user.GetCourseProgress((CourseIndex)100) == null);
}
/// <summary>
/// Test GetCourseProgress returns correct progress object
/// </summary>
public void TestGetCourseProgressValid()
{
User user = new User();
Progress p = new Progress();
p.AddOrUpdate<CourseIndex>("courseIndex", CourseIndex.FINGERSPELLING);
p.AddOrUpdate<float>("courseProgress", 3.14159265f);
user.courses.Add(p);
Progress q = user.GetCourseProgress(CourseIndex.FINGERSPELLING);
Debug.Assert(q.Get<CourseIndex>("courseIndex") == CourseIndex.FINGERSPELLING);
Debug.Assert(q.Get<float>("courseProgress") == 3.14159265f);
}
/// <summary>
/// Test GetMinigameProgress returns null when minigame cannot be found
/// </summary>
public void TestGetMinigameProgressNull()
{
User user = new User();
Debug.Assert(user.GetMinigameProgress(MinigameIndex.SPELLING_BEE) == null);
Debug.Assert(user.GetMinigameProgress((MinigameIndex)100) == null);
Progress p = new Progress();
p.AddOrUpdate<MinigameIndex>("minigameIndex", MinigameIndex.SPELLING_BEE);
user.minigames.Add(p);
Debug.Assert(user.GetMinigameProgress(MinigameIndex.HANGMAN) == null);
}
/// <summary>
/// Test GetMinigameProgress returns correct progress object
/// </summary>
public void TestGetMinigameProgressValid()
{
User user = new User();
Progress p = new Progress();
p.AddOrUpdate<MinigameIndex>("minigameIndex", MinigameIndex.SPELLING_BEE);
user.minigames.Add(p);
Progress q = user.GetMinigameProgress(MinigameIndex.SPELLING_BEE);
Debug.Assert(q.Get<CourseIndex>("minigameIndex") == CourseIndex.FINGERSPELLING);
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,674 +0,0 @@
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 = 0x06_01;
/// <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>();
/// <summary>
/// Create a new PersistentDataEntry
/// </summary>
/// <param name="key"></param>
/// <param name="data"></param>
public PersistentDataEntry(string key, byte[] data) : this(key, data.ToList())
{ }
/// <summary>
/// Create a new PersistentDataEntry
/// </summary>
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
{
/// <summary>
/// The user's username
/// </summary>
public string username = null;
/// <summary>
/// The index of the user's avatar in the UserList.AVATARS list
/// </summary>
public int avatarIndex = -1;
/// <summary>
/// The total playtime of the user
/// </summary>
/// <remarks>Not implemented yet</remarks>
public double playtime = 0.0;
/// <summary>
/// A list of progress on minigames the user has
/// </summary>
public List<SavedMinigameProgress> minigames = new List<SavedMinigameProgress>();
/// <summary>
/// A list of progress on courses the user has
/// </summary>
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>
/// Check whether there are enough inUse Learnables
/// </summary>
/// <returns></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
{
/// <summary>
/// Index of the Learnbable in its Theme
/// </summary>
public int index;
/// <summary>
/// Bool that indicated whether the user already started learning this Learnable
/// </summary>
public bool inUse = false;
/// <summary>
/// Display name of the Learnable
/// </summary>
public string name;
/// <summary>
/// Progress of the learnabe, a number between -5.0 and +5.0
/// </summary>
public float progress = 0.0f;
}
/// <summary>
/// Stored minigame progress data record
/// </summary>
[Serializable]
public class SavedMinigameProgress : PersistentDataContainer
{
/// <summary>
/// Index of the minigame
/// </summary>
public MinigameIndex minigameIndex;
/// <summary>
/// The 10 last scores of a user
/// </summary>
public List<Score> latestScores = new List<Score>();
/// <summary>
/// Top 10 scores of a user
/// </summary>
public List<Score> highestScores = new List<Score>();
}
/// <summary>
/// Stored WeSign data record
/// </summary>
[Serializable]
private class SavedDataStructure
{
/// <summary>
/// The version of the PersistentDataController with which this savefile is created
/// </summary>
public int version = VERSION;
/// <summary>
/// A list of all users
/// </summary>
public List<SavedUserData> users = new List<SavedUserData>();
/// <summary>
/// The index of the current user in the this.users list
/// </summary>
public int currentUser = -1;
/// <summary>
/// The index of the current minigame
/// </summary>
public MinigameIndex currentMinigame;
/// <summary>
/// The index of the current course
/// </summary>
public CourseIndex currentCourse;
/// <summary>
/// The index of the current theme
/// </summary>
public ThemeIndex currentTheme;
/// <summary>
/// The use hardware acceleration user preferences
/// </summary>
public bool useGPU = false;
/// <summary>
/// Initiate the SavedDataStructure, by setting the user preferences
/// </summary>
public SavedDataStructure()
{
RestoreSettings();
}
/// <summary>
/// Reset the user preferences to the default values
/// </summary>
public void RestoreSettings()
{
useGPU = false;
}
}
/// <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;
json.useGPU = false;
}
/// <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();
}
/// <summary>
/// Whether the user wants to use hardware acceleration or not
/// </summary>
public bool IsUsingGPU()
{
return json.useGPU;
}
/// <summary>
/// Set the preference of the user for hardware acceleration
/// </summary>
/// <param name="value">Value of the preference</param>
/// <param name="save">Whether to save the change immediately to disk</param>
public void SetGPUUsage(bool value, bool save = true)
{
json.useGPU = value;
if (save)
Save();
}
/// <summary>
/// Restore preferences to default factory settings
/// </summary>
/// <param name="save">Whether to save the change immediately to disk</param>
public void RestoreSettings(bool save = true)
{
json.RestoreSettings();
if (save)
Save();
}
}

View File

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

View File

@@ -1,19 +0,0 @@
using System;
/// <summary>
/// Score class
/// </summary>
[Serializable]
public class Score
{
/// <summary>
/// The actual score
/// </summary>
public int scoreValue;
/// <summary>
/// The time when the score is achieved, in string format
/// </summary>
public string time;
}

View File

@@ -1,647 +0,0 @@
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

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

View File

@@ -1,133 +0,0 @@
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

@@ -1,19 +0,0 @@
/// <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_COUNTRIES,
SPELLING_WILD,
SPELLING_FARM,
SPELLING_CAPITALS
}

View File

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

View File

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

View File

@@ -1,24 +0,0 @@
{
"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

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

View File

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

View File

@@ -1,57 +0,0 @@
using NUnit.Framework;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
/// <summary>
/// Test the SystemController class
/// </summary>
[TestFixture]
public class SystemControllerTests
{
/// <summary>
/// Test whether the singleton instance is correctly returned
/// </summary>
[Test]
public void Test_SystemController_GetInstance()
{
Assert.IsNotNull(SystemController.GetInstance());
}
/// <summary>
/// Test whether a non valid scene also yields a non valid index
/// </summary>
[Test]
public void Test_GetSceneIndex_InvalidScene()
{
Assert.AreEqual(-1, SystemController.GetSceneIndex("a/non/existing/scene"));
}
/// <summary>
/// Test whether a valid scene also yields a valid index
/// </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",
};
Assert.AreEqual(SceneManager.sceneCountInBuildSettings, scenes.Count);
// Testing wether the names and indices are correct needs to be done in PlayMode
}
}

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More