PlayerManager.cs 9.21 KB
using UnityEngine;
using System.Collections;
using System;
using UnityEngine.UI;
using LAViD.VLibras.Utils;
using System.Text.RegularExpressions;
using System.Threading;
using LAViD.Utils;
using LAViD.Structures;
using System.Diagnostics;
using System.Collections.Generic;

public class PlayerManager : GenericPlayerManager {

#if UNITY_IOS
	//private const string BASE_URL = "http://150.165.205.9/anims/IOS/";//old
	private const string BASE_URL = "http://dicionario.vlibras.gov.br/IOS/";
#else
	//private const string BASE_URL = "http://150.165.205.9/anims/ANDROID/";//old
	private const string BASE_URL = "http://dicionario.vlibras.gov.br/ANDROID/";
#endif

	//private const string SERVER_URL = "http://vlibras.lavid.ufpb.br/glosa?texto=";//old
	private const string SERVER_URL = "http://traducao.vlibras.gov.br/translate?text=";
	private const int VERSION = 1;

	public enum ERROR_STATUS_MESSAGE
	{
		INTERNET_CONNECTION_FAILURE,
		TRANSLATOR_CONNECTION_FAILURE,
		CONNECTION_TIMEOUT_FAILURE
	}

	private string[] randomAnimationNames = new string[] {
		"[RELAXAR]",
		"[BOCEJAR]",
		"[COCHILAR]",
		"[ESPREGUI_ADA]"
	};

	protected VoiceRecognition voiceRecognizer;
	public InputField translateScreenText;
	public ScreenManager screenManager;
	private string dictWord = null;
	private string regionPath = "";
	private int regionHash = 1;

	public Trie signs = null;


	public static string get_connection_status_message(ERROR_STATUS_MESSAGE msg)
	{
		switch(msg)
		{
			case ERROR_STATUS_MESSAGE.TRANSLATOR_CONNECTION_FAILURE:
				return "Problema na conexão. Usaremos português sinalizado e datilologia.";
			case ERROR_STATUS_MESSAGE.INTERNET_CONNECTION_FAILURE:
				return "Não há acesso à internet. Usaremos português sinalizado e datilologia.";
			case ERROR_STATUS_MESSAGE.CONNECTION_TIMEOUT_FAILURE:
				return "Não há acesso à internet. Usaremos português sinalizado e datilologia.";
				//return "A conexão está lenta. Usaremos português sinalizado e datilologia.";
			default:
				return "Ocorreu um erro. Estamos trabalhando para solucioná-lo!";
		}

	}

	public override void Start()
	{
#if UNITY_EDITOR
		Caching.CleanCache();
#endif

		base.setRandomAnimations(randomAnimationNames);
		base.Start();
		
		voiceRecognizer = new VoiceRecognition();
		Screen.fullScreen = false;
		
		StartCoroutine(WaitForResponse(
			new WWW("http://dicionario.vlibras.gov.br/signs"),
			// Success
			delegate(WWW www)
			{
				string response = www.text;

				new Thread(
					() => {
						Thread.CurrentThread.IsBackground = true;

						Stopwatch watch = new Stopwatch();
						watch.Start();

						try {
							PlayerLogger.Log("T", "FJ", "Starting trie parsing.");
							this.signs = Trie.FromJSON(new JSONParser(Regex.Unescape(response)));

							char[] charactersSigns = new char[]
							{
								'A', 'B', 'C', 'Ç', 'D', 'E', 'F', 'G', 'H', 'I',
								'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
								'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
								'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
							};

							foreach (char c in charactersSigns)
							{
								this.signs.Add(c.ToString());
							}
						} catch (Exception e) {
							PlayerLogger.Log("PM", "S", "Exception at trie JSON parser: " + e.ToString());
						}

						watch.Stop();
						PlayerLogger.Log("T", "FJ", "Parsed in " + watch.ElapsedMilliseconds + " ms.");
					}
				).Start();
			},
			// Error
			delegate (WWW www)
			{
				if (www.error == null)
					PlayerLogger.Log("PM", "S<d>", "Timeout.");
				else
					PlayerLogger.Log("PM", "S<d>", "WWW error: " + www.error);
			}
		));
	}

	public void playDict(string word)
	{
		PlayerLogger.Log("Requesting dictionary: " + word);

		this.dictWord = word;
		base.gloss = word;
		base.playNow(word);

		this.screenManager.hideScreen();
		this.screenManager.setPauseMenuState(false);
	}

	public void playTranslate()
	{
		stopTranslation();
		base.stopAll();

		string text = translateScreenText.text;
		translateScreenText.text = "";

		StartCoroutine("translate", text);

		this.screenManager.setPauseMenuState(false);
	}

	public void stopTranslation()
	{
		StopCoroutine("translate");
		this.randomAnimations.unlockFor("translate");
	}

	public void catchTranslationError()
	{
		this.randomAnimations.unlockFor("translate");
		base.repeat();
	}

	public void setRegion(string path)
	{
		this.regionPath = String.IsNullOrEmpty(path) ? "" : path;
		this.regionHash = this.regionPath == "" ? 1 : (int)this.regionPath[0] * 255 + (int)this.regionPath[1];
	}

	public void clearRegion() {
		setRegion("");
	}

	protected override WWW loadAssetBundle(string aniName)
	{
		if (this.regionHash == 1 && !this.signs.Contains(aniName))
			return null;

		string address = BASE_URL + this.regionPath + WWW.EscapeURL(aniName);
		
		PlayerLogger.Log("PM", "lAB", "Requesting bundle: " + address);
		return WWW.LoadFromCacheOrDownload(address, this.regionHash);
	}

	public override void onPlayingStateChange() {
		this.screenManager.changeStates(base.isPlaying(), base.isPaused(), ! String.IsNullOrEmpty(base.gloss));
	}

	public override void onConnectionError(string gloss, string word)
	{
		if (gloss.Equals(this.dictWord))
		{
			this.dictWord = "";
			this.screenManager.showConnectionErrorDialog(
				PlayerManager.ERROR_STATUS_MESSAGE.INTERNET_CONNECTION_FAILURE);

			base.stopAll();
		}
	}

	// Called from microphone icon at main interface
	public void callVoiceRecognizer()
	{
		PlayerLogger.Log("Requesting voice recognizer");
		
		string gloss = voiceRecognizer.callRecognition();
		this.translateScreenText.text = gloss;
		PlayerLogger.Log("Voice recognizer answer: " + gloss);

		this.screenManager.switchScreen("translate");
	}
	
	protected override WWW getCheckConnectionRequest()
	{
		return new WWW(BASE_URL);


		/*WWW connection = new WWW(SERVER_URL);
		yield return connection;
		//while (!glossRequest.isDone)

		if (connection.error == null)
		{
			if (connection.responseHeaders.Count > 0)
				PlayerLogger.Log(connection.responseHeaders["STATUS"]);
			else
				PlayerLogger.Log("No STATUS");
		}
		else PlayerLogger.Log("ERROR: " + connection.error);

		return false;*/


		/*HttpWebRequest request = (HttpWebRequest)WebRequest.Create(BASE_URL);
		request.Method = "HEAD";
		request.Timeout = 2000;

		try {
			HttpWebResponse response = (HttpWebResponse) request.GetResponse();
		}
		catch (WebException e)
		{
			if (e.Response != null)
			{
				PlayerLogger.Log(((HttpWebResponse)e.Response).StatusCode);
				return ((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotFound;
			}
		}
		catch (Exception)
		{
		}

		return false;*/
	}

	protected delegate void SuccessEvent(WWW request);
	protected delegate void ErrorEvent(WWW request);

	protected IEnumerator WaitForResponse(WWW www, SuccessEvent success, ErrorEvent error)
	{
		PlayerLogger.Log("PM", "WFR", "Stating time check.");

		const float timeoutLimit = 20f;
		float timer = 0;

		while (!www.isDone)
		{
			if (timer > timeoutLimit)
			{
				PlayerLogger.Log("PM", "WFR", "Timeout (" + timer + ").");
				if (error != null) error(www);
				yield break;
			}

#if UNITY_ANDROID
			timer += Time.deltaTime;
			yield return null;
#elif UNITY_IOS
			timer += 0.1f;
			yield return new WaitForSeconds(0.1f);
#endif
		}

		PlayerLogger.Log("PM", "WFR", "Done (" + timer + ").");

		if (www.error == null) {
			if (success != null) success(www);
		} else {
			if (error != null) error(www);
		}
	}

	protected override IEnumerator WaitForResponse(WWW www) {
		yield return WaitForResponse(www, null, null);
	}

	private IEnumerator translate(string gloss)
	{
		base.randomAnimations.lockFor("translate");
		this.screenManager.setLoadingSnippetState(true);

		WWW glossRequest = new WWW(SERVER_URL + WWW.EscapeURL(gloss));

		PlayerLogger.Log("PM", "t", "Gloss: " + gloss);
		PlayerLogger.Log("PM", "t", "Request: " + SERVER_URL + WWW.EscapeURL(gloss));
		
		yield return WaitForResponse(glossRequest);

		try {
			if ( ! glossRequest.isDone)
			{
				this.screenManager.showConnectionErrorDialog(
					PlayerManager.ERROR_STATUS_MESSAGE.CONNECTION_TIMEOUT_FAILURE);

				PlayerLogger.Log("PM", "t", "Timeout.");
			}
			else if (glossRequest.error != null)
			{
				this.screenManager.showConnectionErrorDialog(
					PlayerManager.ERROR_STATUS_MESSAGE.INTERNET_CONNECTION_FAILURE);

				PlayerLogger.Log("PM", "t", "(WWW) Error: " + glossRequest.error);
			}
			else if (glossRequest.responseHeaders.Count == 0)
			{
				PlayerLogger.Log("PM", "t", "Unsuccessful answer (0).");

				this.screenManager.showConnectionErrorDialog(
					PlayerManager.ERROR_STATUS_MESSAGE.TRANSLATOR_CONNECTION_FAILURE);
			}
			else if (!glossRequest.responseHeaders["STATUS"].Contains("200"))
			{
				PlayerLogger.Log("PM", "t", "Unsuccessful answer (" + glossRequest.responseHeaders["STATUS"] + ").");

				this.screenManager.showConnectionErrorDialog(
					PlayerManager.ERROR_STATUS_MESSAGE.TRANSLATOR_CONNECTION_FAILURE);
			}
			else if (String.IsNullOrEmpty(glossRequest.text))
			{
				PlayerLogger.Log("PM", "t", "Empty answer.");
			}
			else
			{
				PlayerLogger.Log("PM", "t", "Answer: " + glossRequest.text);

				gloss = glossRequest.text;

				base.gloss = gloss;
				base.playNow(base.gloss);

				yield break;
			}

			base.gloss = gloss.ToUpper();
		}
		finally
		{
			this.screenManager.setLoadingSnippetState(false);
			base.randomAnimations.unlockFor("translate");
		}
	}

}