/// <summary>
        /// Linearly goes through all records looking for the highest and lowest record for given target property
        /// </summary>
        /// <typeparam name="T">Generic type for compiler to infer for the delegate</typeparam>
        /// <param name="region">Region's records to search through</param>
        /// <param name="targetProperty">for a property to find min max versions</param>
        public static void FindMinMax <T>(ref RecordCollection region, Func <SeismicRecord, T> targetProperty) where T : IComparable
        {
            //seed values to compare against
            T min = targetProperty(region.Records[0]);
            T max = targetProperty(region.Records[0]);
            //Indexes to retrieve the max and min records when the search is done
            int minIndex = 0; int maxIndex = 0;

            for (int i = 0; i < region.Records.currentCapacity; i++)
            {
                //when the current min is bigger than the next value in the array
                if (min.CompareTo(targetProperty(region.Records[i])) > 0)
                {
                    //set the current min to that lower value
                    min      = targetProperty(region.Records[i]);
                    maxIndex = i; //record the most up-to-date min record's position
                }
                //when the current max is lower than the next value in the array
                else if (max.CompareTo(targetProperty(region.Records[i])) < 0)
                {
                    //set the current max to higher value
                    max      = targetProperty(region.Records[i]);
                    minIndex = i;//record the most up-to-date max record's position
                }
            }

            //informs user for which parameter the min max request was and tells which column to look for.
            string paramName = targetProperty.Method.GetParameters()[0].Name;
            string maxOutput = RecordCollection.formatPrinter(paramName, region.Records[minIndex], targetProperty);
            string minOutput = RecordCollection.formatPrinter(paramName, region.Records[maxIndex], targetProperty);

            Console.WriteLine($"Minimum Value for {paramName.ToUpper()}:\n{minOutput}\n" +
                              $"Maximum Value for {paramName.ToUpper()}:\n{maxOutput}");
        }
예제 #2
0
        /// <summary>
        /// Decide upon which type of input to ask user based on the type of property being passed as arg
        /// </summary>
        /// <typeparam name="T">Generic type for the delegate's 'out TResult'</typeparam>
        /// <param name="region">Region record data</param>
        /// <param name="propertyField">record's property the search operation to be performed</param>
        static public void TypeSafeSearch <T>(RecordCollection region, Func <SeismicRecord, T> propertyField)
            where T : IComparable
        {
            //paramName; a name of currently passed propertField parameter i.e. month => month.Month is month
            string paramName = propertyField.Method.GetParameters()[0].Name;
            //retrieves the type from a selected record property
            Type propertyType = propertyField(region.Records[0]).GetType();

            //if the current property integer type, then the user is searching by either year, month or day etc.
            if (propertyType == typeof(int))
            {
                int key;
                //months can be searched by string name or integer equivalent, so it makes sense to see if the current parameter is of name month
                if (paramName == "month")
                {
                    //then notify user of possible search inputs
                    Console.WriteLine("You're searching for month; you can use numbers (1-12) or words like june");
                    //a variable to test what type of input the user provided
                    string tempInput = Console.ReadLine();
                    //if it's true that you can't parse the user input as an integer, it's a string
                    if (!int.TryParse(tempInput, out key))
                    {
                        //take the string equivalent for the month input and parse it to months integer for the key
                        key = DateTime.ParseExact(tempInput, "MMMM", CultureInfo.InvariantCulture).Month;
                    }
                }
                else
                {
                    //if input is parasable as an int, then parse it as ant integer and assign it to the key
                    Console.WriteLine($"You're searching for {paramName}; expected input is integer");
                    key = int.Parse(Console.ReadLine());
                }
                //after acquiring the key from the condition statement, it's passed to the search algorithm.
                SearchAlgorithms.BinarySearchAll(key, 0, region.Records.currentCapacity - 1, ref region, propertyField);
            }
            //when the property is of string type
            else if (propertyType == typeof(string))
            {
                //ask user for string input for the key
                Console.WriteLine($"You're searching for {paramName}; expected input is string (lower or upper-case)");
                string key = Console.ReadLine().ToUpper();
                SearchAlgorithms.BinarySearchAll(key, 0, region.Records.currentCapacity - 1, ref region, propertyField);
            }
            //when the property is of TimeSpan, it's clear the user wants to search by the Time property
            else if (propertyType == typeof(TimeSpan))
            {
                //Parse the the input as a TimeSpan type
                Console.WriteLine($"You're searching for {paramName}; expected input is HH:MM:SS");
                TimeSpan key = TimeSpan.Parse(Console.ReadLine());
                SearchAlgorithms.BinarySearchAll(key, 0, region.Records.currentCapacity - 1, ref region, propertyField);
            }
            //when property of type double (magnituded, latitude etc)
            else if (propertyType == typeof(double))
            {
                //Parse the input as a double
                Console.WriteLine($"You're searching for {paramName}; expected input is double (DDD.DDD or -DDD.DDDD)");
                double key = double.Parse(Console.ReadLine());
                SearchAlgorithms.BinarySearchAll(key, 0, region.Records.currentCapacity - 1, ref region, propertyField);
            }
        }
 /// <summary>
 /// To join the current instance of Record collection to another instance
 /// </summary>
 /// <param name="target">Target array you wish to combine with the source</param>
 public void JoinArrays(RecordCollection target)
 {
     //loops through each record in the target and adds it to the current records.
     for (int i = 0; i < target.Records.currentCapacity; i++)
     {
         Records.AddRecord(target.Records[i]);
     }
     SortAlgorithms.HeapSort(this, c => c.Timestamp);
 }
예제 #4
0
        /// <summary>
        /// Once the region is initialized, then you want to choose region specific fields to operate upon
        /// </summary>
        /// <param name="regionData">The initialized instance of the selected region</param>
        static private void FieldMenu(RecordCollection regionData)
        {
            int userInput;

            do
            {
                Console.WriteLine("Which field do you want to perform an operation on?" +
                                  "\n1)Years" +
                                  "\n2)Months" +
                                  "\n3)Days" +
                                  "\n4)Times" +
                                  "\n5)Magnitude" +
                                  "\n6)Latitude" +
                                  "\n7)Longitude" +
                                  "\n8)Depth" +
                                  "\n9)Region" +
                                  "\n10)IRIS_ID" +
                                  "\n11)Timestamp" +
                                  "\n12)List current records" +
                                  "\n13)Go back");
                userInput = short.Parse(Console.ReadLine());
                switch (userInput)
                {
                //selected field should refer to OperationMenu with lambda expression to satisfy the delegate condition and the region's data
                case 1: OperationMenu(regionData, year => year.Year); break;

                case 2: OperationMenu(regionData, month => int.Parse(month.Month[0])); break;     //month integer equivalents (for sorting and searching)

                case 3: OperationMenu(regionData, day => day.Day); break;

                case 4: OperationMenu(regionData, time => time.Time); break;

                case 5: OperationMenu(regionData, magnitude => magnitude.Magnitude); break;

                case 6: OperationMenu(regionData, latitude => latitude.Latitude); break;

                case 7: OperationMenu(regionData, longitude => longitude.Longitude); break;

                case 8: OperationMenu(regionData, depth => depth.Depth); break;

                case 9: OperationMenu(regionData, region => region.Region); break;

                case 10: OperationMenu(regionData, iris_id => iris_id.Iris_id); break;

                case 11: OperationMenu(regionData, timestamp => timestamp.Timestamp); break;

                case 12: regionData.Records.ListRecords(); break;    //if the user wants to view the current state of the records before performing any operation

                case 13: break;

                default:
                    Console.WriteLine("Such field option doesn't exist!");
                    break;
                }
            } while (userInput != 13); //loops until the input is a correct case or intention to quit
        }
예제 #5
0
        /// <summary>
        /// The root menu is gateway to other sub-menu's depending on the path chosen by the user in the root menu.
        /// </summary>
        static public void RootMenu()
        {
            int userInput;

            do
            {
                //clearing the console when making back to root
                Console.Clear();
                Console.WriteLine("Seismic Data Manager - Antanas Skiudulas" +
                                  "\nInstructions: The application is navigated using numbers i.e. to select first option, type 1.");
                Console.WriteLine("Please select which region you want to analyse" +
                                  "\n1)Region 1" +
                                  "\n2)Region 2" +
                                  "\n3)Region 1 & 2" +
                                  "\n4)Quit");
                userInput = short.Parse(Console.ReadLine());
                //since the choice here are regions, it makes sense to instantiate and initialize in the cases selected
                RecordCollection tempReg  = new RecordCollection();
                RecordCollection tempReg2 = new RecordCollection();
                //Initializes certain region(s) depending on the input
                switch (userInput)
                {
                case 1:
                    tempReg.InitializeCollections(1);
                    FieldMenu(tempReg);
                    break;

                case 2:
                    tempReg2.InitializeCollections(2);
                    FieldMenu(tempReg2);
                    break;

                case 3:
                    //intializing all these objects.
                    tempReg.InitializeCollections(1);
                    tempReg2.InitializeCollections(2);
                    //joining the regions into one array.
                    tempReg.JoinArrays(tempReg2);
                    FieldMenu(tempReg);
                    break;

                case 4: Environment.Exit(0); break;

                default:
                    Console.WriteLine("The region you've entered doesn't exist!");
                    break;
                }
            } while (userInput != 4); //loops until the input is a correct case or intention to quit
        }
예제 #6
0
        /// <summary>
        /// sorts the heap into parent nodes higher than children
        /// </summary>
        /// <typeparam name="T">Generic type</typeparam>
        /// <param name="region">region to sort</param>
        /// <param name="HeapSize">the size of the array</param>
        /// <param name="Index">where to point</param>
        /// <param name="properyField">by which property to sort</param>
        private static void Max_Heapify <T>(RecordCollection region, int HeapSize, int Index, Func <SeismicRecord, T> properyField) where T : IComparable
        {
            int Left    = (Index + 1) * 2 - 1;
            int Right   = (Index + 1) * 2;
            int largest = 0;

            //sorting ascendingly
            if (region.SortOrder)
            {
                //when the left node from the middle is more than indexed node
                if (Left < HeapSize && properyField(region.Records[Left]).CompareTo(properyField(region.Records[Index])) > 0)
                {
                    largest = Left; //set largest index
                }
                else
                {
                    largest = Index;
                }
                if (Right < HeapSize && properyField(region.Records[Right]).CompareTo(properyField(region.Records[largest])) > 0)
                {
                    largest = Right;
                }
            }
            //sorting descendingly
            else
            {
                if (Left < HeapSize && properyField(region.Records[Left]).CompareTo(properyField(region.Records[Index])) < 0)
                {
                    largest = Left;
                }
                else
                {
                    largest = Index;
                }
                if (Right < HeapSize && properyField(region.Records[Right]).CompareTo(properyField(region.Records[largest])) < 0)
                {
                    largest = Right;
                }
            }

            if (largest != Index)
            {
                SeismicRecord temp = region.Records[Index];
                region.Records[Index]   = region.Records[largest];
                region.Records[largest] = temp;
                Max_Heapify(region, HeapSize, largest, properyField);
            }
        }
예제 #7
0
        /// <summary>
        /// BinarySearch looks for matching records in the sorted array and prints all matching records
        /// </summary>
        /// <typeparam name="T">Generic type for the TResult in targetProperty</typeparam>
        /// <typeparam name="F">Generic type for the key that will be searched (Type T == Type F in this program)</typeparam>
        /// <param name="key">The reference to generic key type</param>
        /// <param name="region">Which array the operation to be performed on</param>
        /// <param name="foundVals">Reference to array outside the method to store matched keys</param>
        /// <param name="targetProperty">Property that the search will be conducted on (month, day etc)</param>
        /// <param name="left">Lowest index boundry in the array</param>
        /// <param name="right">Highest index boundry in the array</param>
        private static void BinarySearch <T, F>(F key, int left, int right,
                                                ref RecordCollection region, ref RecordCollection foundVals, Func <SeismicRecord, T> targetProperty)
            where T : IComparable
            where F : IComparable
        {
            //during recursion, if left boundry exceeds right, return void
            if (left > right)
            {
                return;
            }
            int mid = (left + right) / 2;                                                         //calibrating current middle position in the array

            if (region.SortOrder == true)                                                         //checking the order in which the array is sorted in ascended way
            {
                if (key.CompareTo(targetProperty(region.Records[mid])) < 0)                       // when key is < mid record's key
                {
                    BinarySearch(key, left, mid - 1, ref region, ref foundVals, targetProperty);  //call with updated right boundry
                }
                else if (key.CompareTo(targetProperty(region.Records[mid])) > 0)                  // when key is > mid record's key
                {
                    BinarySearch(key, mid + 1, right, ref region, ref foundVals, targetProperty); //call with updated left boundry
                }
            }
            else//when the array is sorted in descending order
            {
                //same operation as above, but changed boundries to account for descending order
                if (key.CompareTo(targetProperty(region.Records[mid])) < 0)
                {
                    BinarySearch(key, mid + 1, right, ref region, ref foundVals, targetProperty);
                }
                else if (key.CompareTo(targetProperty(region.Records[mid])) > 0)
                {
                    BinarySearch(key, left, mid - 1, ref region, ref foundVals, targetProperty);
                }
            }
            //when the key is matched
            if (key.Equals(targetProperty(region.Records[mid])))
            {
                //add record to the array of matched keys
                foundVals.Records.AddRecord(region.Records[mid]);
                //branch out and search for other values in both halves of current mid record (in case they're between the current matched record)
                BinarySearch(key, left, mid - 1, ref region, ref foundVals, targetProperty);
                BinarySearch(key, mid + 1, right, ref region, ref foundVals, targetProperty);
            }
        }
예제 #8
0
        /// <summary>
        /// Heap algorithm transform the records into a heap and sorts it logarithmically
        /// </summary>
        /// <typeparam name="T">Generic type</typeparam>
        /// <param name="region">The data to be sorted</param>
        /// <param name="properyField">Property to sort</param>
        public static void HeapSort <T>(RecordCollection region, Func <SeismicRecord, T> properyField) where T : IComparable
        {
            int HeapSize = region.Records.currentCapacity;
            int i;

            //starting from the middle
            for (i = (HeapSize) / 2; i >= 0; i--)
            {
                //create a max heap (sorted)
                Max_Heapify(region, HeapSize, i, properyField);
            }
            for (i = region.Records.currentCapacity - 1; i > 0; i--)
            {
                SeismicRecord temp = region.Records[i];
                region.Records[i] = region.Records[0];
                region.Records[0] = temp;
                HeapSize--;
                Max_Heapify(region, HeapSize, 0, properyField);
            }
        }
예제 #9
0
        /// <summary>
        /// Helper method to print out all the found results in the BinarySearch
        /// </summary>
        /// <typeparam name="T">Generic type for the TResult in targetProperty</typeparam>
        /// <typeparam name="F">Generic type for the key that will be searched (Type T == Type F in this program)</typeparam>
        /// <param name="key">The reference to generic key type</param>
        /// <param name="region">Which array the operation to be performed on</param>
        /// <param name="targetProperty">Property that the search will be conducted on (month, day etc)</param>
        /// <param name="left">Lowest index boundry in the array</param>
        /// <param name="right">Highest index boundry in the array</param>
        public static void BinarySearchAll <T, F>(F key, int left, int right,
                                                  ref RecordCollection region, Func <SeismicRecord, T> targetProperty)
            where T : IComparable
            where F : IComparable
        {
            //array to capture the matched keys from the binary search
            RecordCollection foundVals = new RecordCollection();

            BinarySearch(key, left, right, ref region, ref foundVals, targetProperty);
            //if the array of found records is not empty
            if (foundVals.Records.currentCapacity != 0)
            {
                //if the record should be displayed with the corresponding fields
                if (region.CorrespondingFields == true)
                {
                    foundVals.Records.ListRecords();
                }
                else//if only the value for the record should be displaye
                {
                    //capturing the name of the lambda parameter in the delegate to determine which record field's format to return the key in
                    string paramName = targetProperty.Method.GetParameters()[0].Name;
                    //setting the string to the formatted key
                    string formatOutput = RecordCollection.formatPrinter(paramName, foundVals.Records[0], targetProperty);
                    //for each record present in foundVals
                    for (int i = 0; i < foundVals.Records.currentCapacity; i++)
                    {
                        Console.WriteLine(formatOutput);//output the record
                    }
                }
            }
            else //if the array is emptry, it means the BinarySearch yielded no results
            {
                Console.WriteLine($"'{key}' was not found among the records!");
            }

            //search yield information for the key
            Console.WriteLine($"Found records for '{key}' : {foundVals.Records.currentCapacity} records");
        }
예제 #10
0
        /// <summary>
        /// The operation menu contains all the operations that you can perform on a given field
        /// </summary>
        /// <typeparam name="T">To reduce redundancy, I've specified a generic type method to ensure properties of the SesmicRecord
        /// such as int, double, TimeSpan are inferred by the compiler</typeparam>
        /// <param name="region">region data to operate on</param>
        /// <param name="propertyField">A selected property (column) to perform the required operations on</param>
        static private void OperationMenu <T>(RecordCollection region, Func <SeismicRecord, T> propertyField) where T : IComparable
        {
            int userInput;

            do
            {
                Console.WriteLine("Which of the following you want to perform?" +
                                  "\n1)Heap Sort and display corresponding values" +
                                  "\n2)Binary Search by a field" +
                                  "\n3)Find Max and minimum value" +
                                  "\n4)Go back!");
                userInput = short.Parse(Console.ReadLine());
                //paramName; a name of currently passed propertField parameter i.e. month => month.Month is month
                string paramName = propertyField.Method.GetParameters()[0].Name;
                switch (userInput)
                {
                case 1:
                    //sort in the chosen order
                    Console.WriteLine("1)Ascending" +
                                      "\n2)Descending");
                    int sortInput = short.Parse(Console.ReadLine());
                    switch (sortInput)
                    {
                    //sets the region's desired sort order before sorting
                    case 1: region.SortOrder = true; break;

                    case 2: region.SortOrder = false; break;

                    default: Console.WriteLine("No such sorting option exists!"); break;
                    }
                    //when order is set, sort the region records by the property
                    SortAlgorithms.HeapSort(region, propertyField);
                    region.Records.ListRecords();    //list the records when it's sorted
                    Console.WriteLine("There are currently: {0} records\n", region.Records.currentCapacity);
                    break;

                case 2:
                    //how the found records to be displayed
                    Console.WriteLine("1)Display corresponding values" +
                                      "\n2)Display only selected field");
                    int searchInput = short.Parse(Console.ReadLine());
                    switch (searchInput)
                    {
                    //sets the decision on how to display the records
                    case 1: region.CorrespondingFields = true; break;

                    case 2: region.CorrespondingFields = false; break;

                    default: Console.WriteLine("No such sorting option exists!"); break;
                    }
                    Console.WriteLine($"Enter your search value for {paramName}:");
                    region.SortOrder = true;
                    SortAlgorithms.HeapSort(region, propertyField);
                    //calls a generic method for the users input
                    TypeSafeSearch(region, propertyField);
                    break;

                case 3:
                    //the static method for finding minimum maximum for current field
                    MinMax.FindMinMax(ref region, propertyField);
                    break;

                case 4: break;

                default:
                    Console.WriteLine("Such operation doesn't exist!");
                    break;
                }
            } while (userInput != 4); //loops until the input is a correct case or intention to quit
        }