Resolve WES-133 "Multiple choice"
This commit is contained in:
committed by
Jelle De Geest
parent
04d9a4bf2b
commit
4e9d801e61
@@ -12,6 +12,9 @@ using UnityEngine.Video;
|
||||
/// </summary>
|
||||
public class CoursesController : AbstractFeedback
|
||||
{
|
||||
/// <summary>
|
||||
/// Reference to the objet holding the title
|
||||
/// </summary>
|
||||
public TMP_Text courseTitle;
|
||||
|
||||
/// <summary>
|
||||
@@ -44,12 +47,6 @@ public class CoursesController : AbstractFeedback
|
||||
/// </summary>
|
||||
private int maxWords;
|
||||
|
||||
/// <summary>
|
||||
/// Number of correct words so far
|
||||
/// (can be modified to a list or something like that to give better feedback)
|
||||
/// </summary>
|
||||
private int correctWords = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The "finished" screen
|
||||
/// </summary>
|
||||
@@ -112,11 +109,55 @@ public class CoursesController : AbstractFeedback
|
||||
/// </summary>
|
||||
protected string previousIncorrectSign = null;
|
||||
|
||||
/// <summary>
|
||||
/// Keeps track of what type of panel is currently being used
|
||||
/// </summary>
|
||||
protected int panelId = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Boolean used to check whether the user has already answered the question
|
||||
/// </summary>
|
||||
private bool hasAnswered = false;
|
||||
|
||||
/// <summary>
|
||||
/// Boolean used to check whether SlideIn animation is playing
|
||||
/// </summary>
|
||||
private bool isNextSignInTransit = false;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to course progress bar
|
||||
/// </summary>
|
||||
public Slider progressBar;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the animator of the confetti animation
|
||||
/// </summary>
|
||||
public Animator confettiAnimation;
|
||||
|
||||
/// <summary>
|
||||
/// Panel with video&image prefab
|
||||
/// </summary>
|
||||
public GameObject panelSignWithVideoAndImagePrefab;
|
||||
|
||||
/// <summary>
|
||||
/// Panel with image prefab
|
||||
/// </summary>
|
||||
public GameObject panelSignWithImagePrefab;
|
||||
|
||||
/// <summary>
|
||||
/// Panel with multiplechoice prefab
|
||||
/// </summary>
|
||||
public GameObject panelMultipleChoicePrefab;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the canvas to put the panels into
|
||||
/// </summary>
|
||||
public Transform canvas;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the previous panel,
|
||||
/// so it can be deleted when its done playing its exit animation
|
||||
/// </summary>
|
||||
private GameObject previousPanel = null;
|
||||
|
||||
/// <summary>
|
||||
@@ -142,19 +183,24 @@ public class CoursesController : AbstractFeedback
|
||||
course = courselist.courses[courselist.currentCourseIndex];
|
||||
maxWords = course.theme.learnables.Count;
|
||||
|
||||
// Reload from disk (course may be reset)
|
||||
PersistentDataController.GetInstance().Load();
|
||||
// Create entry in current user for keeping track of progress
|
||||
//PersistentDataController pdc = PersistentDataController.GetInstance();
|
||||
//pdc.Load();
|
||||
user = UserList.GetCurrentUser();
|
||||
progress = user.GetCourseProgress(course.index);
|
||||
if (progress == null)
|
||||
{
|
||||
progress = new PersistentDataController.SavedCourseProgress();
|
||||
progress.courseIndex = course.index;
|
||||
int index = 0;
|
||||
foreach (Learnable learnable in course.theme.learnables)
|
||||
{
|
||||
progress.AddLearnable(learnable.name, index++);
|
||||
}
|
||||
user.AddCourseProgress(progress);
|
||||
}
|
||||
UserList.Save();
|
||||
courseTitle.text = course.title;
|
||||
progressBar.value = progress.progress;
|
||||
|
||||
currentWordIndex = 0;
|
||||
previousPanel = SetupPanel();
|
||||
@@ -165,29 +211,38 @@ public class CoursesController : AbstractFeedback
|
||||
startMoment = DateTime.Now;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetch the next sign and its panel type
|
||||
/// </summary>
|
||||
/// <returns>A tuple of {next sign index, panel type}</returns>
|
||||
/// <remarks>
|
||||
/// The different panel types:<br></br>
|
||||
/// 0 : panelSignWithVideoAndImagePrefab<br></br>
|
||||
/// 1 : panelMultipleChoicePrefab<br></br>
|
||||
/// 2 : panelSignWithImagePrefab
|
||||
/// </remarks>
|
||||
private Tuple<int, int> FetchSign()
|
||||
{
|
||||
// TODO: @Tibe here you need to provide other signs and there question method
|
||||
|
||||
/**************************
|
||||
* TODO: @Tibe
|
||||
*
|
||||
* In deze functie beslist welk panel je nu nodig hebt
|
||||
* Momenteel doe ik gwn iets om te wisselen tussen de twee (moet zeker weg want je begint ALTIJD met een imageANDvideo
|
||||
*
|
||||
* Je ziet zelf maar hoe groot je de sets van woorden maakt, om de 5 ofzo
|
||||
* Altijd eerst video and image, nadien kan je afwisselen, mag random
|
||||
*
|
||||
* ALSO:
|
||||
* Hiervoor moet ge bij Dries zijn, maar man is verdwenen. (100 jaar gingen voorbij en mijn broer en ik vonden een nieuwe oorzaak voor hoofdpijn)
|
||||
* Progress gaat ook aangepast moeten worden, als een user terugkeert tijdens een course en later hervat ga je moeten weten welke set die zat
|
||||
* Zeker als ge woorden in een andere volgorde zou willen doen, gaat ge echt nog aan uw 40u geraken :)
|
||||
* --> dat gaat bijgehouden worden in een van die user files. (Stalk Dries indien nodig, voor andere zaken kan je mij ook vragen stellen)
|
||||
*
|
||||
* *************************/
|
||||
|
||||
int panelChosen = currentWordIndex % 2 + 1;
|
||||
return Tuple.Create(currentWordIndex, panelChosen);
|
||||
PersistentDataController.SavedLearnableProgress learnable = progress.GetRandomLearnable();
|
||||
int panelChosen;
|
||||
if (course.theme.modelIndex == ModelIndex.NONE)
|
||||
{
|
||||
// only multiple choice works in preview mode
|
||||
panelChosen = 1;
|
||||
}
|
||||
else if (learnable.progress > 2.0f)
|
||||
{
|
||||
panelChosen = 2;
|
||||
}
|
||||
else if (learnable.progress > 1.0f)
|
||||
{
|
||||
panelChosen = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
panelChosen = 0;
|
||||
}
|
||||
return Tuple.Create(learnable.index, panelChosen);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -197,78 +252,59 @@ public class CoursesController : AbstractFeedback
|
||||
/// </summary>
|
||||
public void NextSign()
|
||||
{
|
||||
// If the currentindex >= maxwords, it indicated that the course is already finished, running the next code is the meaningless.
|
||||
if (currentWordIndex >= maxWords) { return; }
|
||||
// This function is also called (async) when pressing the 'Gebaar overslaan' button,
|
||||
// so check for condition so we don't skip multiple signs
|
||||
if (isNextSignInTransit || maxWords <= progress.completedLearnables)
|
||||
return;
|
||||
|
||||
confettiAnimation.SetTrigger("Display Confetti");
|
||||
|
||||
// Goto the next word/letter
|
||||
currentWordIndex++;
|
||||
|
||||
// TODO: fix correct word count
|
||||
correctWords++;
|
||||
progress.progress = (float)correctWords / (float)maxWords;
|
||||
UserList.Save();
|
||||
progress.progress = (float)progress.completedLearnables / (float)maxWords;
|
||||
progressBar.value = progress.progress;
|
||||
|
||||
// Update UI if course is not finished yet
|
||||
if (currentWordIndex < maxWords)
|
||||
if (progress.completedLearnables < maxWords)
|
||||
{
|
||||
// Set next sign/video/image
|
||||
StartCoroutine(CRNextSign());
|
||||
}
|
||||
// Finish course and record progress
|
||||
else
|
||||
if (progress.completedLearnables == maxWords)
|
||||
{
|
||||
FinishCourse();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine for going to the next sign
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerator CRNextSign()
|
||||
{
|
||||
isNextSignInTransit = true;
|
||||
GameObject newPanel = SetupPanel();
|
||||
previousPanel.transform.SetAsFirstSibling();
|
||||
newPanel.GetComponent<Animator>().SetTrigger("Slide Panel");
|
||||
newPanel.GetComponent<Animator>().SetTrigger("Slide Panel In");
|
||||
if (previousPanel != null)
|
||||
previousPanel.GetComponent<Animator>().SetTrigger("Slide Panel Out");
|
||||
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
confettiAnimation.ResetTrigger("Display Confetti");
|
||||
GameObject.Destroy(previousPanel);
|
||||
previousPanel = newPanel;
|
||||
hasAnswered = false;
|
||||
isNextSignInTransit = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setup a new panel
|
||||
/// </summary>
|
||||
/// <returns>Reference to the GameObject of the panel</returns>
|
||||
private GameObject SetupPanel()
|
||||
{
|
||||
int panelId;
|
||||
(currentWordIndex, panelId) = FetchSign().ToValueTuple();
|
||||
switch (panelId)
|
||||
{
|
||||
case 0: return null; // TODO: @Tibe multiple choice setup
|
||||
/**************************
|
||||
* TODO: @Tibe
|
||||
*
|
||||
* Hier moet de panelMultipleChoice worden aangemaakt
|
||||
* Geef publieke dingen mee aan uw script.
|
||||
* Kan je eventueel zelf aanpassen,
|
||||
* naargelang hoe je het wilt implementeren
|
||||
*
|
||||
* *************************/
|
||||
case 1:
|
||||
{
|
||||
GameObject panel = GameObject.Instantiate(panelSignWithImagePrefab, canvas);
|
||||
panel.transform.SetAsFirstSibling();
|
||||
|
||||
PanelWithImage script = panel.GetComponent<PanelWithImage>();
|
||||
script.signs = course.theme.learnables;
|
||||
script.currentSignIndex = currentWordIndex;
|
||||
script.isPreview = (course.theme.modelIndex == ModelIndex.NONE);
|
||||
feedbackProgress = script.feedbackProgressBar;
|
||||
feedbackProgressImage = script.feedbackProgressImage;
|
||||
feedbackText = script.feedbackText;
|
||||
script.Display();
|
||||
signPredictor.SwapScreen(script.webcamScreen);
|
||||
return panel;
|
||||
}
|
||||
case 2:
|
||||
case 0:
|
||||
{
|
||||
GameObject panel = GameObject.Instantiate(panelSignWithVideoAndImagePrefab, canvas);
|
||||
panel.transform.SetAsFirstSibling();
|
||||
@@ -283,6 +319,41 @@ public class CoursesController : AbstractFeedback
|
||||
feedbackText = script.feedbackText;
|
||||
script.Display();
|
||||
signPredictor.SwapScreen(script.webcamScreen);
|
||||
courseTitle.text = "Voer het gebaar uit voor \"" + course.theme.learnables[currentWordIndex].name + "\"";
|
||||
return panel;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
GameObject panel = GameObject.Instantiate(panelMultipleChoicePrefab, canvas);
|
||||
panel.transform.SetAsFirstSibling();
|
||||
|
||||
PanelMultipleChoice script = panel.GetComponent<PanelMultipleChoice>();
|
||||
script.signs = course.theme.learnables;
|
||||
script.currentSignIndex = currentWordIndex;
|
||||
script.videoPlayer = videoPlayer;
|
||||
script.courseController = this;
|
||||
script.progress = progress;
|
||||
script.isFingerSpelling = course.theme.title == "Handalfabet";
|
||||
script.Display();
|
||||
signPredictor.SwapScreen(script.webcamScreen);
|
||||
courseTitle.text = "Welk gebaar wordt uitgebeeld?";
|
||||
return panel;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
GameObject panel = GameObject.Instantiate(panelSignWithImagePrefab, canvas);
|
||||
panel.transform.SetAsFirstSibling();
|
||||
|
||||
PanelWithImage script = panel.GetComponent<PanelWithImage>();
|
||||
script.signs = course.theme.learnables;
|
||||
script.currentSignIndex = currentWordIndex;
|
||||
script.isPreview = (course.theme.modelIndex == ModelIndex.NONE);
|
||||
feedbackProgress = script.feedbackProgressBar;
|
||||
feedbackProgressImage = script.feedbackProgressImage;
|
||||
feedbackText = script.feedbackText;
|
||||
script.Display();
|
||||
signPredictor.SwapScreen(script.webcamScreen);
|
||||
courseTitle.text = "Voer het gebaar uit voor \"" + course.theme.learnables[currentWordIndex].name + "\"";
|
||||
return panel;
|
||||
}
|
||||
}
|
||||
@@ -320,7 +391,8 @@ public class CoursesController : AbstractFeedback
|
||||
/// <returns></returns>
|
||||
protected override IEnumerator UpdateFeedback()
|
||||
{
|
||||
if (currentWordIndex < course.theme.learnables.Count)
|
||||
// Check if the current word index is still in bounds, and if the current panel type is not multiple choice
|
||||
if (currentWordIndex < course.theme.learnables.Count && panelId != 1 && !hasAnswered)
|
||||
{
|
||||
// Get current sign
|
||||
Learnable sign = course.theme.learnables[currentWordIndex];
|
||||
@@ -368,7 +440,7 @@ public class CoursesController : AbstractFeedback
|
||||
|
||||
float oldValue = feedbackProgress.value;
|
||||
// use an exponential scale
|
||||
float newValue = Mathf.Exp(4 * (accCurrentSign - 1.0f));
|
||||
float newValue = Mathf.Exp(4 * (Mathf.Clamp(accCurrentSign / sign.thresholdPercentage, 0.0f, 1.0f) - 1.0f));
|
||||
feedbackProgress.gameObject.Tween("FeedbackUpdate", oldValue, newValue, 0.2f, TweenScaleFunctions.CubicEaseInOut, (t) =>
|
||||
{
|
||||
if (feedbackProgress != null)
|
||||
@@ -419,11 +491,59 @@ public class CoursesController : AbstractFeedback
|
||||
/// Function to check equality between the current sign and the sign that the model predicted, if they are equal then the next sign is fetched.
|
||||
/// </summary>
|
||||
/// <param name="predicted"></param>
|
||||
private void NextSignIfCorrect(string current, string predicted)
|
||||
public void NextSignIfCorrect(string current, string predicted)
|
||||
{
|
||||
if (current == predicted)
|
||||
NextSign();
|
||||
if (!hasAnswered)
|
||||
{
|
||||
if (current == predicted)
|
||||
{
|
||||
hasAnswered = true;
|
||||
progress.UpdateLearnable(predicted, 1.5f);
|
||||
confettiAnimation.SetTrigger("Display Confetti");
|
||||
StartCoroutine(WaitNextSign());
|
||||
}
|
||||
else
|
||||
{
|
||||
// currently ignore wrong signs as "J" doesn't work well enough
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: @Tibe cache the incorrect values here
|
||||
}
|
||||
|
||||
private IEnumerator WaitNextSign()
|
||||
{
|
||||
// Wait for 0.75 seconds
|
||||
yield return new WaitForSeconds(0.75f);
|
||||
NextSign();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function to check equality between the current sign and the sign that the model predicted, if they are equal then the next sign is fetched.
|
||||
/// </summary>
|
||||
/// <param name="predicted"></param>
|
||||
public void NextSignMultipleChoice(string current, string predicted)
|
||||
{
|
||||
if (!hasAnswered)
|
||||
{
|
||||
hasAnswered = true;
|
||||
if (current == predicted)
|
||||
{
|
||||
progress.UpdateLearnable(predicted, 1.5f);
|
||||
confettiAnimation.SetTrigger("Display Confetti");
|
||||
}
|
||||
else
|
||||
{
|
||||
progress.UpdateLearnable(predicted, -1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback for the 'back' button
|
||||
/// </summary>
|
||||
public void ReturnToActivityScreen()
|
||||
{
|
||||
UserList.Save();
|
||||
SystemController.GetInstance().BackToPreviousScene();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user