/**
 * DatasetReader application (C#, .NET Framework 4.6.1)
 * for the motor impairments stroke-gesture dataset.
 *
 * 	    Radu-Daniel Vatavu, Ph.D.
 *      MintViz Lab, MANSiD Research Center
 *	    University Stefan cel Mare of Suceava
 *	    Suceava 720229, Romania
 *	    radu.vatavu@usm.ro
 *      http://www.eed.usv.ro/~vatavu
 *
 * 	    Ovidiu-Ciprian Ungurean, Ph.D.
 *      MintViz Lab, MANSiD Research Center
 *	    University Stefan cel Mare of Suceava
 *	    Suceava 720229, Romania
 *	    ungurean.ovidiu@gmail.com 
 *
 * The academic publication for this dataset, and what should be used to cite it, is:
 *
 *	  Vatavu, R.-D. and Ungurean, O.-C. (2019).  
 *	  Stroke-Gesture Input for People with Motor Impairments: Empirical Results & Research Roadmap.
 *    Proceedings of CHI '19, the 37th ACM Conference on Human Factors in Computing Systems (Glasgow, Scottland, UK). 
 *    New York, NY, USA: ACM Press, Paper 215
 *    https://doi.org/10.1145/3290605.3300445
 *
 * This software is distributed under the "New BSD License" agreement:
 *
 * Copyright (c) 2019, Radu-Daniel Vatavu and Ovidiu-Ciprian Ungurean. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the name of the University Stefan cel Mare of Suceava, nor 
 *      the names of its contributors may be used to endorse or promote products 
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Radu-Daniel Vatavu OR 
 * Ovidiu-Ciprian Ungurean BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
**/

using System;
using System.Linq;
using System.IO;
using System.Collections.Generic;

namespace DatasetReader
{
    static class Program
    {
        #region dataset description

        static string datasetFolder = "Dataset";

        static string[] gestureTypes = new string[]
        {
            "down", "up", "left", "right",
            "alpha", "check", "energy",
            "euro", "heart", "letter M",
            "letter R", "paperclip", "pi",
            "six-point star", "spiral", "X"
        };

        const int MAX_NUMBER_OF_SAMPLES_PER_GESTURE_TYPE = 9;

        private static bool IsSymbolicGesture(string gestureType)
        {
            return (gestureType != "down" && gestureType != "up" && gestureType != "left" && gestureType != "right");
        }

        struct Participant
        {
            public string ID;
            public bool MotorImpairment;
            public int Age;
            public char Gender;
            public string Description;
        };

        static Participant[] participants = new Participant[]
        {
            // participants with motor impairments (35)
            new Participant(){ID = "1", Gender = 'M', Age = 37, MotorImpairment = true, Description = "SCI (C6)"},
            new Participant(){ID = "2", Gender = 'M', Age = 37, MotorImpairment = true, Description = "SCI (C6)"},
            new Participant(){ID = "3", Gender = 'M', Age = 53, MotorImpairment = true, Description = "SCI (C7)"},
            new Participant(){ID = "4", Gender = 'M', Age = 40, MotorImpairment = true, Description = "Cerebral Palsy"},
            new Participant(){ID = "5", Gender = 'M', Age = 34, MotorImpairment = true, Description = "SCI (C5)"},
            new Participant(){ID = "6", Gender = 'M', Age = 28, MotorImpairment = true, Description = "SCI (C6)"},
            new Participant(){ID = "7", Gender = 'M', Age = 44, MotorImpairment = true, Description = "SCI (C6)"},
            new Participant(){ID = "8", Gender = 'M', Age = 34, MotorImpairment = true, Description = "Cerebral Palsy"},
            new Participant(){ID = "9", Gender = 'M', Age = 34, MotorImpairment = true, Description = "SCI (C6)"},
            new Participant(){ID = "10", Gender = 'M', Age = 14, MotorImpairment = true, Description = "SCI (C5)"},
            new Participant(){ID = "11", Gender = 'M', Age = 54, MotorImpairment = true, Description = "SCI (C5)"},
            new Participant(){ID = "12", Gender = 'M', Age = 48, MotorImpairment = true, Description = "SCI (C5)"},
            new Participant(){ID = "13", Gender = 'F', Age = 37, MotorImpairment = true, Description = "Meningitis"},
            new Participant(){ID = "14", Gender = 'M', Age = 45, MotorImpairment = true, Description = "SCI (C6)"},
            new Participant(){ID = "15", Gender = 'M', Age = 14, MotorImpairment = true, Description = "SCI (C5)"},
            new Participant(){ID = "16", Gender = 'M', Age = 14, MotorImpairment = true, Description = "SCI (C5)"},
            new Participant(){ID = "17", Gender = 'M', Age = 42, MotorImpairment = true, Description = "SCI (C4-C5)"},
            new Participant(){ID = "18", Gender = 'F', Age = 15, MotorImpairment = true, Description = "SCI (C6)"},
            new Participant(){ID = "19", Gender = 'M', Age = 28, MotorImpairment = true, Description = "SCI (C7)"},
            new Participant(){ID = "20", Gender = 'M', Age = 22, MotorImpairment = true, Description = "SCI (C5)"},
            new Participant(){ID = "21", Gender = 'M', Age = 26, MotorImpairment = true, Description = "SCI (C7)"},
            new Participant(){ID = "22", Gender = 'M', Age = 29, MotorImpairment = true, Description = "SCI (C5)"},
            new Participant(){ID = "23", Gender = 'M', Age = 42, MotorImpairment = true, Description = "SCI (C6)"},
            new Participant(){ID = "24", Gender = 'M', Age = 43, MotorImpairment = true, Description = "SCI (C6)"},
            new Participant(){ID = "25", Gender = 'M', Age = 23, MotorImpairment = true, Description = "Phocomelia"},
            new Participant(){ID = "26", Gender = 'F', Age = 22, MotorImpairment = true, Description = "Cerebral Palsy"},
            new Participant(){ID = "27", Gender = 'M', Age = 21, MotorImpairment = true, Description = "Spastic Tetraparesis"},
            new Participant(){ID = "28", Gender = 'M', Age = 32, MotorImpairment = true, Description = "Spastic Tetraparesis"},
            new Participant(){ID = "29", Gender = 'M', Age = 42, MotorImpairment = true, Description = "SCI (C5)"},
            new Participant(){ID = "30", Gender = 'M', Age = 30, MotorImpairment = true, Description = "Spinal muscular atrophy (Kugelberg Welander type III)"},
            new Participant(){ID = "31", Gender = 'M', Age = 31, MotorImpairment = true, Description = "SCI (C5)"},
            new Participant(){ID = "32", Gender = 'F', Age = 22, MotorImpairment = true, Description = "Muscular Dystrophy (Limb-girdle)"},
            new Participant(){ID = "33", Gender = 'M', Age = 34, MotorImpairment = true, Description = "Muscular Dystrophy (Duchenne)"},
            new Participant(){ID = "34", Gender = 'M', Age = 67, MotorImpairment = true, Description = "Parkinson’s disease"},
            new Participant(){ID = "35", Gender = 'M', Age = 23, MotorImpairment = true, Description = "Spastic Tetraparesis"},

            // participants without motor impairments (35)
            new Participant(){ID = "1001", Gender = 'M', Age = 21, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1002", Gender = 'F', Age = 20, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1003", Gender = 'F', Age = 21, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1004", Gender = 'M', Age = 23, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1005", Gender = 'M', Age = 23, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1006", Gender = 'M', Age = 21, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1007", Gender = 'M', Age = 21, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1008", Gender = 'M', Age = 21, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1009", Gender = 'F', Age = 21, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1010", Gender = 'M', Age = 20, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1011", Gender = 'F', Age = 21, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1012", Gender = 'M', Age = 23, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1013", Gender = 'F', Age = 24, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1014", Gender = 'F', Age = 22, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1015", Gender = 'F', Age = 20, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1016", Gender = 'M', Age = 21, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1017", Gender = 'F', Age = 21, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1018", Gender = 'M', Age = 22, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1019", Gender = 'M', Age = 22, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1020", Gender = 'M', Age = 33, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1021", Gender = 'M', Age = 35, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1022", Gender = 'M', Age = 20, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1023", Gender = 'M', Age = 20, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1024", Gender = 'F', Age = 21, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1025", Gender = 'M', Age = 41, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1026", Gender = 'F', Age = 41, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1027", Gender = 'F', Age = 36, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1028", Gender = 'M', Age = 38, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1029", Gender = 'M', Age = 37, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1030", Gender = 'M', Age = 37, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1031", Gender = 'F', Age = 43, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1032", Gender = 'F', Age = 37, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1033", Gender = 'F', Age = 38, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1034", Gender = 'F', Age = 45, MotorImpairment = false, Description = ""},
            new Participant(){ID = "1035", Gender = 'F', Age = 35, MotorImpairment = false, Description = ""}
        };

        #endregion

        #region main function: reads the dataset

        [STAThread]
        static void Main()
        {
            // print a summary of the dataset
            Console.WriteLine("=====================================");
            Console.WriteLine("Dataset summary");
            Console.WriteLine("=====================================");
            Console.Write("Number of participants: {0}, ", participants.Length);
            Console.WriteLine("of which {0} participants with motor impairments", participants.Where(p => p.MotorImpairment).Count());
            Console.WriteLine("Gender: {0} males and {1} females", participants.Where(p => p.Gender == 'M').Count(), participants.Where(p => p.Gender == 'F').Count());
            Console.WriteLine(
                "Mean age {0:.0} years for participants with motor impairments and {1:.0} years for participants without motor impairments.",
                participants.Where(p => p.MotorImpairment).Average(p => p.Age),
                participants.Where(p => !p.MotorImpairment).Average(p => p.Age)
            );
            Console.WriteLine();

            // read the gestures
            int[] numSamples = new int[] { 0, 0 };
            foreach (Participant participant in participants)
            {
                Console.Write("reading data for participant ID# {0,-4} ...", participant.ID);

                List<Gesture[]> gestures = new List<Gesture[]>();
                foreach (string gestureType in gestureTypes)
                {
                    string fileName = String.Format("{0}\\{1}\\{2}.xml", datasetFolder, participant.ID, gestureType);
                    if (File.Exists(fileName))
                    {
                        Gesture[] samples = GestureIO.Read(fileName);
                        gestures.Add(samples);
                        numSamples[participant.MotorImpairment ? 0 : 1] += samples.Length;
                    }
                }

                int n = gestures.Sum(g => g.Length);
                Console.WriteLine(" {0,3} samples (completion rate: {1:.0}%)", n, n * 100.0 / MAX_NUMBER_OF_SAMPLES_PER_GESTURE_TYPE / gestureTypes.Length);
            }

            Console.WriteLine();
            Console.WriteLine(
                "Total: {0} gesture samples, of which {1} from participants with motor impairments.", 
                numSamples[0] + numSamples[1], numSamples[0]
            );
            Console.WriteLine();
            Console.Read();
        }

        #endregion
    }
}