/// <summary>
 /// Resumes a paused experiment by re-enabling the Client state change listener and
 /// starting a new trial.If the experiment is uninitialized, it will initialize it.
 ///
 /// </summary>
 public void Resume()
 {
     // Skip initialization if the experiment has already started
     isPaused = false;
     if (hasStarted)
     {
         client.onStatusChanged += OnStatusChanged;
         if (config != null)
         {
             AEPsychClient.Log("Resuming prior trial: " + config);
             SetState(ExperimentState.ConfigReady);
             if (!client.finished)
             {
                 ShowStimuli(config);
             }
         }
         else
         {
             StartCoroutine(AskForNewConfig(strategy));
         }
     }
     else
     {
         StartCoroutine(ConnectAndGenerateStrategies());
     }
 }
        public virtual void PauseExperiment()
        {
            AEPsychClient.Log("Pausing " + name);

            isPaused = true;
            Disconnect();
            gameObject.SetActive(false);
        }
        // ______________________________ Section 5 ________________________________
        //
        //   Unity Built-in Methods
        // _________________________________________________________________________
        #region
        private void Awake()
        {
            // Find Query Model Canvas Group, if model querying is enabled in Inspector
            if (useModelExploration)
            {
                queryModel = FindObjectOfType <QueryModel>(true);
                if (queryModel == null)
                {
                    ModelExplorerPrefab = AssetDatabase.LoadAssetAtPath <GameObject>(modelExplorerPath);
                    if (ModelExplorerPrefab != null)
                    {
                        queryModel = Instantiate(ModelExplorerPrefab).GetComponent <QueryModel>();
                    }
                    else
                    {
                        Debug.LogError(string.Format("Prefab not found at: {0}. Please Manually add the ModelExploreInterface prefab to use model exploration.", modelExplorerPath));
                    }
                    Debug.Log("No Query Model game object detected in scene. Loading default ModelExploreInterface Prefab.");
                }

                // Add Event System if there isn't one already
                if (FindObjectOfType <EventSystem>() == null)
                {
                    new GameObject("EventSystem", typeof(EventSystem), typeof(StandaloneInputModule));
                }
            }
            // Find client within Unity scene
            client = FindObjectOfType <AEPsychClient>();
            if (client == null)
            {
                Debug.LogError("AEPsych Client is missing. Please add the AEPsych " +
                               "Client to the scene and ensure that it is enabled.");
                TerminateExperiment();
            }
            configGenerator = GetComponent <ConfigGenerator>();
            if (configGenerator == null)
            {
                Debug.LogError("Experiement script running without a ConfigGenerator attached. " +
                               "Please attach a ConfigGenerator component to " + GetName());
                TerminateExperiment();
            }
            if (configGenerator.isAutomatic)
            {
                //AEPsychClient.Log("Automatic Config Generated:\n" + PlayerPrefs.GetString(configGenerator.experimentName + "config"));
                AEPsychClient.Log("Automatic Config Generated:\n" + configGenerator.GetConfigText());
            }
            if (useDefaultUI)
            {
                defaultUI = FindObjectOfType <DefaultUI>();
                if (defaultUI == null)
                {
                    Debug.LogError("Using default UI, but DefaultUI not found in scene. " +
                                   "Please add the DefaultUI component to your scene or uncheck \"Use " +
                                   "Default UI\" for your Experiment.");
                    TerminateExperiment();
                }
            }
        }
 void Disconnect()
 {
     AEPsychClient.Log("Disconnecting " + GetName());
     StopAllCoroutines();
     if (client)
     {
         client.onStatusChanged -= OnStatusChanged;
     }
     SetState(ExperimentState.NotConnected);
 }
        // ______________________________ Section 2 ________________________________
        //
        //        Virtual Methods that you may want to override in child class
        // _________________________________________________________________________
        #region

        // SetText (optional)
        // Helper function to increase default visibility of trial text
        public virtual void SetText(string text)
        {
            if (useDefaultUI)
            {
                defaultUI.SetText(text);
            }
            else
            {
                AEPsychClient.Log(text);
            }
        }
 /// <summary>
 /// Starts experiment by beginning the first sample request
 /// </summary>
 public virtual void BeginExperiment()
 {
     AEPsychClient.Log("Starting Experiment: Strategy " + strategy.stratId);
     hasStarted = true;
     if (strategy != null)
     {
         StartCoroutine(AskForNewConfig(strategy));
     }
     else
     {
         Debug.LogError("Manual config selected, but config file field is empty. " +
                        "To use manual config files, assign one in the AEPsychClient inspector " +
                        "window. To use automatic Configs, toggle \"Use Automatic Config " +
                        "Generation\" in the AEPsychClient inspector window.");
         TerminateExperiment();
     }
 }
 /// <summary>
 /// Called when user is ready for the next trial. Queries AEPsych server for the optimal test case.
 /// </summary>
 /// <param name="strategyId"></param>
 IEnumerator AskForNewConfig(AEPsychStrategy strat)
 {
     // Initialize strat if we haven't yet
     if (strat.stratId == -1)
     {
         yield return(StartCoroutine(strat.InitStrat(client, configPath: configPath, true)));
     }
     // Resume this strat if AEPsych Client was previously handling a different one
     if (client.currentStrat != strat.stratId)
     {
         SetState(ExperimentState.WaitingForResumeResponse);
         yield return(StartCoroutine(client.Resume(strat.stratId)));
     }
     strategy.currentTrial++;
     AEPsychClient.Log("strat " + strategy.stratId + " trial# "
                       + strat.currentTrial);
     SetState(ExperimentState.WaitingForAskResponse);
     yield return(StartCoroutine(client.Ask()));
 }
 /// <summary>
 /// Called when user makes a judgement and selects a response. Updates the AEPsych model with a new data point.
 /// </summary>
 public void ReportResultToServer(int outcome, TrialMetadata metadata = null)
 {
     if (recordToCSV)
     {
         TrialData trial = new TrialData(DateTime.Now.ToString("hh:mm:ss"), config, outcome, metadata);
         csvFile.WriteTrial(trial);
     }
     AEPsychClient.Log(string.Format("ReportResult: {0}", outcome));
     SetState(ExperimentState.WaitingForTellResponse);
     if (metadata != null)
     {
         StartCoroutine(client.Tell(config, outcome, metadata));
     }
     else
     {
         StartCoroutine(client.Tell(config, outcome));
     }
     if (useModelExploration)
     {
         queryModel.QueryEnabled(false);
     }
 }
        /// <summary>
        /// Callback for AEPsych Client Status Changes. This syncs the Experiment class with the AEPsychClient class and manages state transitions.
        /// // Expected order of transitions:
        /// NotConnected =>                           occurs before the experiment begins.
        ///   WaitingForResumeResponse =>             occurs after sending Resume() query to server.
        ///     WaitingForAsk =>                      occurs when resume confirmation is received.
        ///       WaitingForAskResponse =>            occurs while client awaits AEPsych server's test case selection
        ///         ConfigReady =>                    occurs when suggested test case is received from server
        ///           WaitingForTell =>               occurs while waiting for the user to respond to stimulus
        ///            WaitingForTellResponse =>     occurs as soon as user response is sent to server
        ///   WaitingForAsk => ...
        /// </summary>
        /// <param name="oldStatus"></param>
        /// <param name="newStatus"></param>
        void OnStatusChanged(AEPsychClient.ClientStatus oldStatus, AEPsychClient.ClientStatus newStatus)
        {
            AEPsychClient.Log(string.Format("OnStatusChanged Callback. Experiment status: {0}, " +
                                            "old client: {1}, new client: {2}", _experimentState, oldStatus, newStatus));
            if (_experimentState == ExperimentState.NotConnected)
            {
                if (newStatus == AEPsychClient.ClientStatus.GotResponse)
                {
                    OnConnectToServer();
                }
            }
            else if (_experimentState == ExperimentState.Exploring)
            {
                if (newStatus == AEPsychClient.ClientStatus.QuerySent)
                {
                    SetState(ExperimentState.WaitingForQueryResponse);
                }
            }
            else if (_experimentState == ExperimentState.WaitingForTellResponse)
            {
                if (newStatus == AEPsychClient.ClientStatus.GotResponse)
                {
                    if (useModelExploration && !readyToQuery)
                    {
                        // Check if the model is built and ready for queries
                        StartCoroutine(CheckQueryReady());
                    }
                    else
                    {
                        StartCoroutine(EndTrial());
                    }
                }
            }
            else if (_experimentState == ExperimentState.WaitingForResumeResponse)
            {
                if (newStatus == AEPsychClient.ClientStatus.GotResponse)
                {
                    SetState(ExperimentState.WaitingForAsk);
                }
            }
            else if (_experimentState == ExperimentState.WaitingForAskResponse)
            {
                if (newStatus == AEPsychClient.ClientStatus.GotResponse)
                {
                    // We recieved a new config. Store it.
                    config = client.GetConfig();
                    SetState(ExperimentState.ConfigReady);
                    if (!client.finished)
                    {
                        ShowStimuli(config);
                    }
                    else
                    {
                        isDone = true;
                        StartCoroutine(EndTrial());
                    }
                }
            }

            else if (_experimentState == ExperimentState.ConfigReady)
            {
                if (newStatus == AEPsychClient.ClientStatus.Ready)
                {
                    SetState(ExperimentState.WaitingForTell);
                    // Enable or Disable Model Querying based on client status
                    CheckUserResponse(); // Should call ReportResultToServer()
                                         // when response is collected
                }
            }
            else if (_experimentState == ExperimentState.WaitingForAsk)
            {
                if (newStatus == AEPsychClient.ClientStatus.QuerySent)
                {
                    SetState(ExperimentState.WaitingForAskResponse);
                }
            }
            else if (_experimentState == ExperimentState.WaitingForTell)
            {
                if (newStatus == AEPsychClient.ClientStatus.QuerySent)
                {
                    SetState(ExperimentState.WaitingForTellResponse);
                }
            }
            else if (_experimentState == ExperimentState.WaitingForQueryResponse)
            {
                if (newStatus == AEPsychClient.ClientStatus.GotResponse)
                {
                    //QueryMessage m = client.GetQueryResponse();
                    //ReceiveExplorationQuery(m.x);
                    SetState(ExperimentState.Exploring);
                }
            }
            else if (_experimentState == ExperimentState.WaitingForCanModelResponse)
            {
                if (newStatus == AEPsychClient.ClientStatus.GotResponse)
                {
                    readyToQuery = client.GetModelResponse();
                    StartCoroutine(EndTrial());
                }
            }
        }