void StopPlaying(int e)
    {
        //Debug.Log("Stopped playing" + e);
        if (e != -1)
        {
            eventsPlaying[e].eventIndex      = 0;
            eventsPlaying[e].isPlaying       = false;
            eventsPlaying[e].isDetected      = false;
            eventsPlaying[e].advancedIndex   = false;
            eventsPlaying[e].playStartTime   = 0.0f;
            eventsPlaying[e].eventStartTime  = 0.0f;
            eventsPlaying[e].eventEndTime    = 0.0f;
            eventsPlaying[e].eventStartFrame = 0;
            eventsPlaying[e].eventEndFrame   = 0;
            //eventsPlaying[e].ActivatedDoms = new List<DomState>();

            alreadyFaded = false;
            //turn off all event visualization - 11/16/2017 - Ross - yes, since we aren't doing multiple events anyways
            //fixes a random null reference that could occur in commented out code below.

            /*for (int i = 0; i < events[e].eventData.Count; ++i)
             * {
             *  float lastTime = Time.time;
             *  //Debug.Log(lastTime);
             *  //while (Mathf.Abs(Time.time - lastTime) < 100)
             *  //{
             *  //    Debug.Log("x");
             *  //}
             *
             *  GameObject d = arrayGenerator.DOMArray[events[e].eventData[i].dom, events[e].eventData[i].str];
             *  if (d != null)
             *  {
             *      d.GetComponent<DOMController>().TurnOff();
             *  }
             * }*/

            GameObject da = GameObject.Find("DomArray");
            for (int i = 0; i < DomArrayGenerator.NUM_STRINGS; ++i)
            {
                for (int j = 0; j < DomArrayGenerator.NUM_DOMS_PER_STRING; ++j)
                {
                    GameObject d = arrayGenerator.DOMArray[i, j];
                    if (d != null)
                    {
                        DOMController dc = d.GetComponent <DOMController>();
                        if (dc != null)
                        {
                            dc.GetComponent <DOMController>().TurnOff();
                        }
                    }
                }
            }
        }
    }
    private void FinishEvent(bool forceAllVisible)
    {
        if (!forceAllVisible)
        {
            while (eventsPlaying[currEventNumber].eventIndex < events[currEventNumber].eventData.Count - 1)
            {
                //todo - to handle sped up play back, need to potentially loop ahead here, until we calculate a frame count beyond the current...
                if (eventsPlaying[currEventNumber].eventIndex < events[currEventNumber].eventData.Count && eventsPlaying[currEventNumber].advancedIndex)
                {
                    GameObject d = arrayGenerator.DOMArray[events[currEventNumber].eventData[eventsPlaying[currEventNumber].eventIndex].dom, events[currEventNumber].eventData[eventsPlaying[currEventNumber].eventIndex].str];

                    float fTimeFrac = 0.0f;
                    if (d != null)
                    {
                        totalEnergy += events[currEventNumber].eventData[eventsPlaying[currEventNumber].eventIndex].charge;

                        //fTimeFrac = (events[e].eventData[eventsPlaying[e].eventIndex].time - eventsPlaying[e].eventStartTime) / (eventsPlaying[e].eventEndTime - eventsPlaying[e].eventStartTime);
                        //Ross - changed coloring to just be always rainbow, not dependent on time stamps..
                        fTimeFrac = (float)eventsPlaying[currEventNumber].eventIndex / (float)events[currEventNumber].eventData.Count;
                        DOMController dc = d.GetComponent <DOMController>();
                        if (dc != null)
                        {
                            float charge = Mathf.Log(60000.0f * events[currEventNumber].eventData[eventsPlaying[currEventNumber].eventIndex].charge * events[currEventNumber].eventData[eventsPlaying[currEventNumber].eventIndex].charge);
                            dc.TurnOn(fTimeFrac, charge);

                            AudioSource asource = dc.GetComponent <AudioSource>();
                            if (asource != null && asource.isActiveAndEnabled)
                            {
                                asource.Play();
                            }
                        }
                    }

                    //Vector3 dir = (events[e].endPos - events[e].startPos);
                    //float mag = (events[e].endPos - events[e].startPos).magnitude;
                    //particle.transform.position = events[e].startPos + dir * fTimeFrac;
                }

                //advance index depending on timing...
                if (eventsPlaying[currEventNumber].eventIndex < events[currEventNumber].eventData.Count - 1)
                {
                    //time scale here is probably off...
                    //these time values are in nanoseconds, so really huge, so this will probably be true every frame...
                    //instead let's do this based on frame count..
                    //given the event's time and our frame range, we can figure map the single event's time to which frame it should play...
                    float timeFrac   = (events[currEventNumber].eventData[eventsPlaying[currEventNumber].eventIndex].time - eventsPlaying[currEventNumber].eventStartTime) / (eventsPlaying[currEventNumber].eventEndTime - eventsPlaying[currEventNumber].eventStartTime);
                    int   frameRange = eventsPlaying[currEventNumber].eventEndFrame - eventsPlaying[currEventNumber].eventStartFrame;

                    float frameFrac = (float)eventsPlaying[currEventNumber].eventStartFrame + (timeFrac * (float)frameRange);

                    eventsPlaying[currEventNumber].eventIndex++;
                    eventsPlaying[currEventNumber].advancedIndex = true;
                }
            }
        }
        else
        {
            int i = 0;
            while (i < events[currEventNumber].eventData.Count)
            {
                GameObject    d         = arrayGenerator.DOMArray[events[currEventNumber].eventData[i].dom, events[currEventNumber].eventData[i].str];
                float         fTimeFrac = (float)i / (float)events[currEventNumber].eventData.Count;
                DOMController dc        = d.GetComponent <DOMController>();
                if (dc != null)
                {
                    float charge = Mathf.Log(60000.0f * events[currEventNumber].eventData[i].charge * events[currEventNumber].eventData[i].charge);
                    dc.TurnOn(fTimeFrac, charge);
                }

                i++;
            }
        }
    }
    // Update is called once per frame
    void Update()
    {
        if (!swipeGameMode.GetComponent <SwipeGameMode>().isGamePlaying() && !playingTutorial)
        {
            return;
        }

        for (int j = 0; j < sparkList.Count; ++j)
        {
            GameObject s = sparkList[j];
            sparkList[j].transform.Translate(0f, 20f, 0f);
            //-1127 is y value of ground - add this as a reference..
            if (sparkList[j].transform.position.y > -47f)
            {
                sparkList.RemoveAt(j);
                DestroyObject(s);
            }
        }

        if (donePlaying && !isSwiped)
        {
            timer -= Time.deltaTime;
            if (timer <= 0f)
            {
                timer = 2.0f;
                StopPlaying(currEventNumber);
                //set this back to -1 as we don't necessarily want to replay the same event if it wasn't swiped..
                lastEventNumber = currEventNumber;
                currEventNumber = -1;
                donePlaying     = false;
            }
        }

        if (!keepPlaying)
        {
            return;
        }

        float t = UnityEngine.Time.time;

        totalEnergy = 0.0f;
        //r or every eventFrequency seconds
        if ((t - lastPlayTime) > eventFrequency && !IsEventPlaying())
        {
            if (firstPlay || (t - lastPlayTime) > eventFrequency + secondsBeforeHelp + secondsBeforeDissappear)
            {
                //Debug.Log("Playing new");
                firstPlay = false;

                if (playingTutorial)
                {
                    //always just play first event when not in game mode.
                    currEventNumber = 0;
                    lastEventNumber = currEventNumber;
                }
                else
                {
                    if (currEventNumber == -1)
                    {
                        currEventNumber = UnityEngine.Random.Range(0, events.Count);// incrEventNumber;
                        if (swipeGameMode.GetComponent <SwipeGameMode>().isSoftTutorial())
                        {
                            currEventNumber = 0;
                        }

                        Debug.Log("Playing event: " + currEventNumber);
                        if (lineGrapher != null)
                        {
                            lineGrapher.GetComponent <LineEnergyGrapher>().ResetEnergy();
                        }

                        lastEventNumber = currEventNumber;
                        incrEventNumber++;
                    }
                }

                lastPlayTime = t;

                //todo - don't allow same event to replay until it's done...
                eventsPlaying[currEventNumber].newPlayTime     = t;
                eventsPlaying[currEventNumber].eventStartTime  = events[currEventNumber].eventData[0].time;
                eventsPlaying[currEventNumber].eventStartFrame = UnityEngine.Time.frameCount;

                eventsPlaying[currEventNumber].eventEndFrame = UnityEngine.Time.frameCount + (int)((float)events[currEventNumber].eventData.Count / playSpeed);

                eventsPlaying[currEventNumber].playStartTime = t;
                eventsPlaying[currEventNumber].eventEndTime  = events[currEventNumber].eventData[events[currEventNumber].eventData.Count - 1].time;
                eventsPlaying[currEventNumber].advancedIndex = true;
                eventsPlaying[currEventNumber].eventIndex    = 0;
                eventsPlaying[currEventNumber].isPlaying     = true;
                eventsPlaying[currEventNumber].isDetected    = false;

                if (alarm != null && alarm.isActiveAndEnabled)
                {
                    alarm.Play();
                }

                if (truePath != null)
                {
                    truePath.SetPosition(0, events[currEventNumber].startPos);
                    truePath.SetPosition(1, events[currEventNumber].endPos);
                }

                if (particle != null)
                {
                    /*if ((swipeGameMode.GetComponent<SwipeGameMode>().isSoftTutorial()))
                     * {
                     *  particle.GetComponent<SpawnParticle>().particlePrefab.transform.GetChild(0).gameObject.SetActive(true);
                     * }
                     * else
                     * {
                     *  particle.GetComponent<SpawnParticle>().particlePrefab.transform.GetChild(0).gameObject.SetActive(false);
                     * }*/

                    if (swipeGameMode.GetComponent <SwipeGameMode>().isSoftTutorial())
                    {
                        particle.GetComponent <SpawnParticle>().startThrowing();
                        //Debug.Log("Throwing particle");
                    }
                }
            }
        }

        if (IsEventPlaying())
        {
            //todo - to handle sped up play back, need to potentially loop ahead here, until we calculate a frame count beyond the current...
            if (eventsPlaying[currEventNumber].eventIndex < events[currEventNumber].eventData.Count && eventsPlaying[currEventNumber].advancedIndex)
            {
                GameObject d = arrayGenerator.DOMArray[events[currEventNumber].eventData[eventsPlaying[currEventNumber].eventIndex].dom, events[currEventNumber].eventData[eventsPlaying[currEventNumber].eventIndex].str];

                float fTimeFrac = 0.0f;
                if (d != null)
                {
                    totalEnergy += events[currEventNumber].eventData[eventsPlaying[currEventNumber].eventIndex].charge;

                    //fTimeFrac = (events[e].eventData[eventsPlaying[e].eventIndex].time - eventsPlaying[e].eventStartTime) / (eventsPlaying[e].eventEndTime - eventsPlaying[e].eventStartTime);
                    //Ross - changed coloring to just be always rainbow, not dependent on time stamps..
                    fTimeFrac = (float)eventsPlaying[currEventNumber].eventIndex / (float)events[currEventNumber].eventData.Count;
                    DOMController dc = d.GetComponent <DOMController>();
                    if (dc != null)
                    {
                        float charge = Mathf.Log(60000.0f * events [currEventNumber].eventData [eventsPlaying [currEventNumber].eventIndex].charge * events [currEventNumber].eventData [eventsPlaying [currEventNumber].eventIndex].charge);
                        //Debug.Log(eventsPlaying[currEventNumber].eventIndex);
                        dc.TurnOn(fTimeFrac, charge);
                        //DomState toAdd = new DomState ();
                        //toAdd.charge = charge;
                        //toAdd.timeFrac = fTimeFrac;

                        //eventsPlaying [currEventNumber].ActivatedDoms.Add (toAdd);

                        if (sparks != null)
                        {
                            GameObject spark = Instantiate(sparks, transform);
                            spark.transform.position = d.transform.position;
                            spark.GetComponent <ParticleSystem>().Play();
                            sparkList.Add(spark);
                        }

                        AudioSource asource = dc.GetComponent <AudioSource>();
                        if (asource != null && asource.isActiveAndEnabled)
                        {
                            asource.Play();
                        }
                    }
                }

                //Vector3 dir = (events[e].endPos - events[e].startPos);
                //float mag = (events[e].endPos - events[e].startPos).magnitude;
                //particle.transform.position = events[e].startPos + dir * fTimeFrac;
            }

            //advance index depending on timing...
            if (eventsPlaying[currEventNumber].eventIndex < events[currEventNumber].eventData.Count - 1)
            {
                //time scale here is probably off...
                //these time values are in nanoseconds, so really huge, so this will probably be true every frame...
                //instead let's do this based on frame count..
                //given the event's time and our frame range, we can figure map the single event's time to which frame it should play...
                //float timeFrac = (events[currEventNumber].eventData[eventsPlaying[currEventNumber].eventIndex].time - eventsPlaying[currEventNumber].eventStartTime) / (eventsPlaying[currEventNumber].eventEndTime - eventsPlaying[currEventNumber].eventStartTime);
                //int frameRange = eventsPlaying[currEventNumber].eventEndFrame - eventsPlaying[currEventNumber].eventStartFrame;

                //float frameFrac = (float)eventsPlaying[currEventNumber].eventStartFrame + (timeFrac * (float)frameRange);

                eventsPlaying[currEventNumber].eventIndex++;
                eventsPlaying[currEventNumber].advancedIndex = true;
            }
            else
            {
                if (beginFade)
                {
                    if (fadeStart == -1.0f)
                    {
                        fadeStart = t;
                    }

                    if (t - fadeStart < fadeTime)
                    {
                        //loop through all DOMs...
                        for (int k = 0; k < events[currEventNumber].eventData.Count; ++k)
                        {
                            GameObject d = arrayGenerator.DOMArray[events[currEventNumber].eventData[k].dom, events[currEventNumber].eventData[k].str];
                            d.GetComponent <DOMController>().Fade(1.0f - ((t - fadeStart) / fadeTime));
                        }
                    }
                    else
                    {
                        beginFade    = false;
                        alreadyFaded = true;
                        fadeStart    = -1.0f;
                    }
                }
            }

            if (eventsPlaying[currEventNumber].eventIndex >= events[currEventNumber].eventData.Count - 1)
            {
                if (swipeGameMode.GetComponent <SwipeGameMode>().isSoftTutorial())
                {
                    swipeGameMode.GetComponent <SwipeGameMode>().softTutorialText.GetComponent <UnityEngine.UI.Text>().text = "Swipe in the direction of the event.";
                }

                if (!playingTutorial && !swipeGameMode.GetComponent <SwipeGameMode>().isSoftTutorial())
                {
                    if ((t - lastPlayTime) > eventFrequency + secondsBeforeHelp + secondsBeforeDissappear - fadeTime)
                    {
                        if (!alreadyFaded)
                        {
                            beginFade = true;
                        }
                    }
                    //Debug.Log(eventFrequency + secondsBeforeHelp);
                    if ((t - lastPlayTime) > eventFrequency + secondsBeforeHelp)
                    {
                        if (helpSwipe != null && !playingTutorial)
                        {
                            /*float pressTime = helpSwipe.GetComponent<LiveHelpTimer>().pressTime;
                             * if (t - pressTime > secondsBeforeHelp)
                             * {
                             *  Vector3 diff = (events[currEventNumber].startPos - events[currEventNumber].endPos).normalized;
                             *  //helpSwipe.transform.position = (events[currEventNumber].startPos + events[currEventNumber].endPos) / 2;
                             *  float angle = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
                             *  //helpSwipe.transform.localRotation = Quaternion.Euler(helpSwipe.transform.localRotation.x, helpSwipe.transform.localRotation.y, angle);
                             *  helpSwipe.SetActive(true);
                             *  //TODO: set 2d rotation of helpSwipe to match current event
                             * }
                             * else
                             * {
                             *  helpSwipe.SetActive(false);
                             * }*/
                        }
                    }

                    // Event done playing
                    if ((t - lastPlayTime) > eventFrequency + secondsBeforeHelp + secondsBeforeDissappear)
                    {
                        donePlaying = true;
                        //also need to deactivate if successful swipe occurs...

                        /*if (helpSwipe != null)
                         * {
                         *  helpSwipe.SetActive(false);
                         * }*/
                    }
                }
            }
        }
    }
    // Update is called once per frame
    void Update()
    {
        float t = UnityEngine.Time.time;

        totalEnergy = 0.0f;
        //r or every 60 seconds
        if (UnityEngine.Input.GetKeyDown(UnityEngine.KeyCode.R) || (t - lastPlayTime) > eventFrequency)
        {
            lastPlayTime = t;

            //todo - don't allow same event to replay until it's done...
            int currEvent = UnityEngine.Random.Range(0, events.Count);
            Debug.Log("Playing event " + currEvent);

            eventsPlaying[currEvent].newPlayTime     = t;
            eventsPlaying[currEvent].eventStartTime  = events[currEvent].eventData[0].time;
            eventsPlaying[currEvent].eventStartFrame = UnityEngine.Time.frameCount;
            Debug.Log("Start Frame:" + eventsPlaying[currEvent].eventStartFrame);

            eventsPlaying[currEvent].eventEndFrame = UnityEngine.Time.frameCount + (int)((float)events[currEvent].eventData.Count / playSpeed);
            Debug.Log("End Frame:" + eventsPlaying[currEvent].eventEndFrame);

            eventsPlaying[currEvent].playStartTime = t;
            eventsPlaying[currEvent].eventEndTime  = events[currEvent].eventData[events[currEvent].eventData.Count - 1].time;
            eventsPlaying[currEvent].advancedIndex = true;
            eventsPlaying[currEvent].eventIndex    = 0;
            eventsPlaying[currEvent].isPlaying     = true;
            eventsPlaying[currEvent].isDetected    = false;
            if (alarm.isActiveAndEnabled)
            {
                alarm.Play();
            }

            //Debug.Log("Source: " + events[currEvent].eventSource.name);
        }

        if (IsEventPlaying())
        {
            for (int e = 0; e < eventsPlaying.Length; ++e)
            {
                if (eventsPlaying[e].isPlaying)
                {
                    //todo - to handle sped up play back, need to potentially loop ahead here, until we calculate a frame count beyond the current...
                    if (eventsPlaying[e].eventIndex < events[e].eventData.Count && eventsPlaying[e].advancedIndex)
                    {
                        if (domData == null)
                        {
                            domData = gameObject.GetComponent <DomData>();
                        }

                        GameObject d = domData.DOMArray[events[e].eventData[eventsPlaying[e].eventIndex].dom, events[e].eventData[eventsPlaying[e].eventIndex].str].tableDom;

                        float fTimeFrac = 0.0f;
                        if (d != null)
                        {
                            totalEnergy += events[e].eventData[eventsPlaying[e].eventIndex].charge;
                            totalEnergyText.GetComponent <UnityEngine.UI.Text>().text = "Total Energy: " + totalEnergy;
                            //fTimeFrac = (events[e].eventData[eventsPlaying[e].eventIndex].time - eventsPlaying[e].eventStartTime) / (eventsPlaying[e].eventEndTime - eventsPlaying[e].eventStartTime);
                            //Ross - changed coloring to just be always rainbow, not dependent on time stamps..
                            fTimeFrac = (float)eventsPlaying[e].eventIndex / (float)events[e].eventData.Count;
                            DOMController dc = d.GetComponent <DOMController>();
                            if (dc != null)
                            {
                                float charge = Mathf.Log(20000.0f * events [e].eventData [eventsPlaying [e].eventIndex].charge * events [e].eventData [eventsPlaying [e].eventIndex].charge);
                                dc.TurnOn(fTimeFrac, charge);
                                //DomState toAdd = new DomState ();
                                //toAdd.charge = charge;
                                //toAdd.timeFrac = fTimeFrac;
                                //toAdd.Dom = domData.DOMArray[events[e].eventData[eventsPlaying[e].eventIndex].dom, events[e].eventData[eventsPlaying[e].eventIndex].str].puzzleDom;
                                //eventsPlaying [e].ActivatedDoms.Add (toAdd);

                                AudioSource asource = dc.GetComponent <AudioSource>();
                                if (asource != null && asource.isActiveAndEnabled)
                                {
                                    asource.Play();
                                }
                            }
                        }

                        //Vector3 dir = (events[e].endPos - events[e].startPos);
                        //float mag = (events[e].endPos - events[e].startPos).magnitude;
                        //particle.transform.position = events[e].startPos + dir * fTimeFrac;
                    }

                    //advance index depending on timing...
                    if (eventsPlaying[e].eventIndex < events[e].eventData.Count - 1)
                    {
                        //time scale here is probably off...
                        //these time values are in nanoseconds, so really huge, so this will probably be true every frame...
                        //instead let's do this based on frame count..
                        //given the event's time and our frame range, we can figure map the single event's time to which frame it should play...
                        float timeFrac   = (events[e].eventData[eventsPlaying[e].eventIndex].time - eventsPlaying[e].eventStartTime) / (eventsPlaying[e].eventEndTime - eventsPlaying[e].eventStartTime);
                        int   frameRange = eventsPlaying[e].eventEndFrame - eventsPlaying[e].eventStartFrame;
                        //Debug.Log("Range: " + frameRange);
                        float frameFrac = (float)eventsPlaying[e].eventStartFrame + (timeFrac * (float)frameRange);
                        //Debug.Log("Fraction: " + frameFrac);
                        //Debug.Log("Frame Count: " + UnityEngine.Time.frameCount);
                        //Debug.Log("Event Index: " + eventsPlaying[e].eventIndex);
                        //need to double check this...
                        //if (frameFrac < (float)UnityEngine.Time.frameCount)
                        //{
                        eventsPlaying[e].eventIndex++;
                        eventsPlaying[e].advancedIndex = true;

                        /*}
                         * else if(UnityEngine.Time.frameCount > eventsPlaying[e].eventEndFrame)
                         * {
                         *  StopPlaying(e);
                         * }
                         * else
                         * {
                         *  //spin the existing spheres?
                         *  //fade out option?
                         *  eventsPlaying[e].advancedIndex = false;
                         * }*/
                    }

                    if (eventsPlaying[e].eventIndex >= events[e].eventData.Count - 1)
                    {
                        //StopPlaying(e);
                        StartCoroutine(DelayedReset(1.0f, e));
                    }
                }
            }
        }
    }