Измерьте время, которое человек смотрел на несколько объектов - PullRequest
0 голосов
/ 31 января 2019

Я пытаюсь создать приложение UWP, которое измеряет время, которое человек смотрел на несколько объектов.Есть около 300 объектов, и все они должны измерить время и отобразить его в текстовом файле.Я успешно закодировал это только для одного объекта, но я не знаю, как я могу сделать это с несколькими объектами.Я видел этот пост Как более эффективно создавать 300 секундомеров в C #? , и ответ на этот вопрос мне очень помог, но код не очень хорошо работает с моим кодом.Поэтому мне нравится идея создания списка объектов, а затем, когда человек смотрит на объект [o], соответствующий секундомер запускается, когда глаза вошли в объект, и останавливается, когда глаза покидают объект.Проблема, как я уже упоминал, решение не работает с кодом, с которым я работаю.Это код, который я использовал, который работает только для одного элемента.

public sealed partial class BlankPage1 : Page
{
    private GazeElement gazeButtonControl;
    private GazePointer gazePointer;

    public BlankPage1()
    {
        this.InitializeComponent();
        Stopwatch Timer = new Stopwatch();
        gazePointer = GazeInput.GetGazePointer(null);
        gazeButtonControl = GazeInput.GetGazeElement(GazeBlock);
        gazeButtonControl = new GazeElement();
        GazeInput.SetGazeElement(GazeBlock, gazeButtonControl);
        gazeButtonControl.StateChanged += GazeButtonControl_StateChanged;

        void GazeButtonControl_StateChanged(object sender, StateChangedEventArgs ea)
        {
            if (ea.PointerState == PointerState.Enter)
            {
                Timer.Start();
            }

            if (ea.PointerState == PointerState.Exit)
            {
                Timer.Stop();
                CreateStatistics();
            }
        }

        void CreateStatistics()
        {
            File.WriteAllText(@"C:\Users\Vincent Korpelshoek\AppData\Local\Packages\app.a264e06e2-5084-4424-80a9-bee5f5fbb6b6_8wekyb3d8bbwe\LocalState\Resultaten.txt", Timer.Elapsed.ToString(););
        }
    }
}

«GazeBlock» - это имя первого объекта, который был создан в файле XAML.Короче говоря, я бы хотел реализовать это решение:

static Dictionary<object, Stopwatch> stopwatchesByObject;

static void Main(string[] args)
{
    List<object> objects = new List<object>();

    // now you have to fill the objects list...

    stopwatchesByObject = new Dictionary<object, Stopwatch>();
    foreach (var o in objects)
    {
        stopwatchesByObject.Add(o, new Stopwatch());
    }
}

// Call this method when the user starts gazing at object o
static void StartGazingAt(object o)
{
    stopwatchesByObject[o].Start();
}

// Call this method when the user stops gazing at object o
static void StopGazingAt(object o)
{
    stopwatchesByObject[o].Stop();
}

static void CreateStatistics()
{
    StringBuilder sb = new StringBuilder();
    foreach (var entry in stopwatchesByObject)
    {
        sb.AppendLine($"Gazed at {entry.Key.ToString()} for {entry.Value.Elapsed.TotalSeconds} seconds.");
    }
    File.WriteAllText("c:\\temp\\statictics.txt", sb.ToString());
}

Но я не знаю, как «объединить» эти два элемента вместе, чтобы решение работало не только для одного объекта, но и для всего300 из них.Если кто-нибудь знает, как помочь мне сделать эту работу, спасибо!

Винсент

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019

@ Винсент, возможно, стоило бы взглянуть на это по-другому.

С помощью отслеживания глаз пользователь может смотреть только на одно место на экране в любой момент времени, поэтому, если ваши объекты не наслоеныперекрывая друг друга в 2D-пространстве или потенциально выровненные по линии прямой видимости в 3D-пространстве, вас может интересовать только время, в течение которого точка наблюдения пользователя остается в текущем верхнем объекте.Одного секундомера может быть достаточно для отслеживания времени от OnEnter до OnExit для активного объекта.

Если в OnExit вы добавляете продолжительность времени для этого конкретного взгляда в совокупный счетчик времени lastGazedObject, вам, вероятно, не нужно (или не нужно) управлять 300 секундомерами и, вероятно, вы просто можете повторно использовать один и тот же секундомер каждыйвремя, когда взгляд пользователя входит в объект, затем покидает объект.Когда он покидает один объект, следующая точка взгляда падает либо на другой объект, либо на пустое пространство без объекта.

Вы смотрели на этот образец ?Он имеет множество частей для определения того, как долго остается взгляд в одном объекте, с некоторой дополнительной логикой для отслеживания объекта lastGazedObject, который вы могли бы выполнить за тем, что вам нужно, без управления целой кучей секундомеров или таймеров.

Однако, даже если сценарий, для которого вы пытаетесь решить, действительно приближается к проблеме, как приведение лучей, которое может пересекать более одного объекта за раз (из-за наложения или выравнивания в пространстве), он все равно долженлегко иметь один длительный секундомер и просто отслеживать свойство флага для каждого объекта UserIsGazingAt вместе с моментом, когда выполняется GazeAtStarted, а затем вычислить продолжительность, как только взгляд отходит от объекта, и добавить продолжительность к общей сумме объектов.продолжительность.

HTH

0 голосов
/ 31 января 2019

Кажется, что для каждого объекта, который вы создаете, вам нужно добавить его в словарь (вместе с новым Stopwatch), затем добавить к нему обработчик события GazeButtonControl_StateChanged (вы можете добавить этот же обработчик события ко всемэлементов управления), то в этом обработчике событий вы будете ссылаться на правильный секундомер, используя аргумент sender: stopwatchesByObject[sender].Start();

Это может быть не совсем правильно, но вот то, что я думаю, вам нужносделать, чтобы объединить две части кода:

public sealed partial class BlankPage1 : Page
{
    private GazeElement gazeButtonControl;
    private GazePointer gazePointer;
    static Dictionary<object, Stopwatch> stopwatchesByObject;

    public BlankPage1()
    {
        this.InitializeComponent();
        gazePointer = GazeInput.GetGazePointer(null);
        gazeButtonControl = GazeInput.GetGazeElement(GazeBlock);
        gazeButtonControl = new GazeElement();
        GazeInput.SetGazeElement(GazeBlock, gazeButtonControl);
        gazeButtonControl.StateChanged += GazeButtonControl_StateChanged;

        // Add the object to our dictionary along with a new stopwatch
        stopwatchesByObject.Add(gazeButtonControl, new Stopwatch());

        private void GazeButtonControl_StateChanged(object sender, StateChangedEventArgs ea)
        {
            // Use the sender argument to choose the correct timer
            if (ea.PointerState == PointerState.Enter)
            {
                if (stopwatchesByObject.ContainsKey(sender))
                {
                    stopwatchesByObject[sender].Start();
                }
            }
            else if (ea.PointerState == PointerState.Exit)
            {
                if (stopwatchesByObject.ContainsKey(sender))
                {
                    stopwatchesByObject[sender].Stop();
                    CreateStatistics();
                }
            }
        }

        private void CreateStatistics()
        {
            StringBuilder sb = new StringBuilder();

            foreach (var entry in stopwatchesByObject)
            {
                sb.AppendLine($"Gazed at {entry.Key} for {entry.Value.Elapsed.TotalSeconds} seconds.");
            }

            File.WriteAllText("c:\\temp\\statictics.txt", sb.ToString());
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...