Resolve WES-131-Feedback-REfactor

This commit is contained in:
Jerome Coudron
2023-04-02 12:27:59 +00:00
committed by Dries Van Schuylenbergh
parent b955d2164c
commit a808e73a29
27 changed files with 663 additions and 560 deletions

View File

@@ -1,62 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HangManWebcam : WebCam
{
/// <summary>
/// The display for player 1
/// </summary>
public RawImage display1;
/// <summary>
/// The display for player 2
/// </summary>
public RawImage display2;
/// <summary>
/// We use a different awake, since we dont want the camera to start immediatelly
/// </summary>
void Awake()
{
WebCamDevice device = WebCamTexture.devices[camdex];
tex = new WebCamTexture(device.name);
display.texture = tex;
}
/// <summary>
/// Hangman uses two different webcam_textures, we need to be able to toggle between them
/// </summary>
public void Switch_texture()
{
if(display == display1)
{
display = display2;
}
else
{
display = display1;
}
// Give the webcamTexture to the new webcam
display.texture = tex;
}
/// <summary>
/// Scene changing is implemented here to avoid problems with webcam
/// </summary>
public new void GotoThemeSelection()
{
//minigameList.GetIndexInMinigameList(MinigameIndex.HANGMAN);
if (tex != null)
{
if (tex.isPlaying)
{
display.texture = null;
tex.Stop();
tex = null;
}
}
SystemController.GetInstance().BackToPreviousScene();
}
}

View File

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

View File

@@ -1,11 +1,13 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using DigitalRuby.Tween;
public class HangmanController : MonoBehaviour
public class HangmanController : AbstractFeedback
{
/// <summary>
/// The scriptable with all the themes, will be used to select a random word for hangman.
@@ -18,11 +20,6 @@ public class HangmanController : MonoBehaviour
/// </summary>
private string currentWord;
/// <summary>
/// All of the words that can be used in this session
/// </summary>
private string[] words;
/// <summary>
/// This integer holds the total amount of wrong guesses the player has made
/// </summary>
@@ -200,11 +197,6 @@ public class HangmanController : MonoBehaviour
/// </summary>
public GameObject scoreboardEntry;
/// <summary>
/// Accuracy feeback object
/// </summary>
public Feedback feedback;
/// <summary>
/// The button to go into the game
/// </summary>
@@ -215,8 +207,50 @@ public class HangmanController : MonoBehaviour
/// </summary>
private String currentsign = "";
// Start is called before the first frame update
/// <summary>
/// Reference to the feedback field
/// </summary>
public TMP_Text feedbackText;
/// <summary>
/// Reference to the progress bar
/// </summary>
public Slider feedbackProgress;
/// <summary>
/// Reference to the progress bar image, so we can add fancy colors
/// </summary>
public Image feedbackProgressImage;
/// <summary>
/// Timer to keep track of how long a incorrect sign is performed
/// </summary>
protected DateTime timer;
/// <summary>
/// Current predicted sign
/// </summary>
protected string predictedSign = null;
/// <summary>
/// Previous incorrect sign, so we can keep track whether the user is wrong or the user is still changing signs
/// </summary>
protected string previousIncorrectSign = null;
/// <summary>
/// Start is called before the first frame update
/// </summary>
void Start()
{
StartController();
signPredictor.SetModel(ModelIndex.FINGERSPELLING);
AddSelfAsListener();
}
/// <summary>
/// Called at the start of the scene AND when the scene is replayed
/// </summary>
public void StartController()
{
// Make sure the mode starts at zero
mode = 0;
@@ -240,19 +274,6 @@ public class HangmanController : MonoBehaviour
user.minigames.Add(progress);
}
userList.Save();
// Hangman always uses fingerspelling
feedback.signPredictor.ChangeModel(ModelIndex.FINGERSPELLING);
// Set calllbacks
feedback.getSignCallback = () =>
{
return "A";
};
feedback.predictSignCallback = (sign) =>
{
currentsign = sign;
};
}
/// <summary>
@@ -281,7 +302,7 @@ public class HangmanController : MonoBehaviour
DeleteWord();
DisplayWord(currentWord);
replayButton.onClick.AddListener(Start);
replayButton.onClick.AddListener(StartController);
// Call to display the first image, corresponding to a clean image.
ChangeSprite();
}
@@ -352,7 +373,7 @@ public class HangmanController : MonoBehaviour
{
if (mode == 1)
{
if (currentsign != "")
if (currentsign != null && currentsign != "")
{
char letter = currentsign.ToLower()[0];
currentsign = "";
@@ -393,7 +414,7 @@ public class HangmanController : MonoBehaviour
// For the first input char given by the user, check if the letter is in the word that needs to be spelled.
// Check to make sure the inputfield is not empty
if (currentsign != "")
if (currentsign != null && currentsign != "")
{
char firstLetter = currentsign.ToLower()[0];
currentsign = "";
@@ -543,21 +564,6 @@ public class HangmanController : MonoBehaviour
}
}
/// <summary>
/// Randomly shuffle the list of words
/// </summary>
private void ShuffleWords()
{
for (int i = words.Length - 1; i > 0; i--)
{
// Generate a random index between 0 and i (inclusive)
int j = UnityEngine.Random.Range(0, i + 1);
// Swap the values at indices i and j
(words[j], words[i]) = (words[i], words[j]);
}
}
/// <summary>
/// Update and save the scores
/// </summary>
@@ -731,4 +737,97 @@ public class HangmanController : MonoBehaviour
rank++;
}
}
/// <summary>
/// The updateFunction that is called when new probabilities become available
/// </summary>
/// <returns></returns>
protected override IEnumerator UpdateFeedback()
{
// Get current sign
string currentSign = "A";
// Get the predicted sign
if (signPredictor != null && signPredictor.learnableProbabilities != null &&
currentSign != null && signPredictor.learnableProbabilities.ContainsKey(currentSign))
{
float accuracy = signPredictor.learnableProbabilities[currentSign];
if (feedbackText != null && feedbackProgressImage != null)
{
if (accuracy > 0.90)
{
feedbackText.text = "Goed";
feedbackText.color = Color.green;
feedbackProgressImage.color = Color.green;
}
else if (accuracy > 0.80)
{
feedbackText.text = "Bijna...";
Color col = new Color(0xff / 255.0f, 0x66 / 255.0f, 0x00 / 255.0f);
feedbackText.color = col;
feedbackProgressImage.color = col;
}
else
{
feedbackText.text = "Detecteren...";
feedbackText.color = Color.red;
feedbackProgressImage.color = Color.red;
}
float oldValue = feedbackProgress.value;
// use an exponential scale
float newValue = Mathf.Exp(4 * (accuracy - 1.0f));
feedbackProgress.gameObject.Tween("FeedbackUpdate", oldValue, newValue, 0.2f, TweenScaleFunctions.CubicEaseInOut, (t) =>
{
if (feedbackProgress != null)
{
feedbackProgress.value = t.CurrentValue;
}
});
}
// Check whether (in)correct sign has high accuracy
foreach (var kv in signPredictor.learnableProbabilities)
{
if (kv.Value > 0.90)
{
predictedSign = kv.Key;
// Correct sign
if (predictedSign == currentSign)
{
yield return new WaitForSeconds(1.0f);
CheckEquality(predictedSign);
timer = DateTime.Now;
predictedSign = null;
previousIncorrectSign = null;
}
// Incorrect sign
else
{
if (previousIncorrectSign != predictedSign)
{
timer = DateTime.Now;
previousIncorrectSign = predictedSign;
}
else if (DateTime.Now - timer > TimeSpan.FromSeconds(2.0f))
{
CheckEquality(predictedSign);
timer = DateTime.Now;
predictedSign = null;
previousIncorrectSign = null;
}
}
break;
}
}
}
else if (feedbackProgress != null)
{
feedbackProgress.value = 0.0f;
}
}
private void CheckEquality(string sign)
{
currentsign = sign;
}
}

View File

@@ -1,95 +0,0 @@
using UnityEngine.UI;
using UnityEngine;
public class WebCam : MonoBehaviour
{
/// <summary>
/// Index of the current camera
/// </summary>
protected int camdex = 0;
/// <summary>
/// Texture to paste on the display
/// </summary>
protected WebCamTexture tex;
/// <summary>
/// Display for the video feed
/// </summary>
public RawImage display;
/// <summary>
/// Setup the webcam correctly
/// </summary>
void Awake()
{
WebCamDevice device = WebCamTexture.devices[camdex];
tex = new WebCamTexture(device.name);
display.texture = tex;
tex.Play();
}
/// <summary>
/// Function to toggle between stopping and starting
/// </summary>
/*
public void toggle()
{
if (tex.isPlaying)
{
tex.Stop();
}
else
{
tex.Play();
}
}
*/
public void PlayCam()
{
if (!tex.isPlaying) tex.Play();
}
public void StopCam()
{
if (tex.isPlaying) tex.Stop();
}
/// <summary>
/// Swap webcam by cycling through the `WebCamTexture.devices` list
/// </summary>
public void SwapCam()
{
if (WebCamTexture.devices.Length > 0)
{
// Stop the old camera
display.texture = null;
tex.Stop();
tex = null;
// Find the new camera
camdex += 1;
camdex %= WebCamTexture.devices.Length;
// Start the new camera
WebCamDevice device = WebCamTexture.devices[camdex];
tex = new WebCamTexture(device.name);
display.texture = tex;
tex.Play();
}
}
/// <summary>
/// Scene changing is implemented here to avoid problems with webcam
/// </summary>
public void GotoThemeSelection()
{
display.texture = null;
tex.Stop();
tex = null;
SystemController.GetInstance().BackToPreviousScene();
}
}

View File

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