Exemple #1
0
 public HeartDataPoint(HeartDataType heartType, int amount, DateTime timestamp, string accuracy)
 {
     this.heartType = heartType;
     this.amount    = amount;
     this.timestamp = timestamp;
     this.accuracy  = accuracy;
 }
        /// <summary>
        /// The main task for writing the data to file; it get's the full set of data going in to the file,
        /// it then deletes the current file(if it exists) and creates a new file containing the incoming data, it then updates the status(TextView) of the app
        /// </summary>
        /// <param name="dataPoints"></param>
        /// <param name="fileName"></param>
        /// <param name="dataStatusHandler"></param>
        /// <returns></returns>
        private static async Task storeDataPointsTask(List <HeartDataPoint> dataPoints, string fileName, StatusHandler dataStatusHandler)
        {
            if (dataPoints != null && dataPoints.Count > 0)
            {
                HeartDebugHandler.debugLog("There is data to be written: " + dataPoints.Count.ToString());
                //needed values
                HeartDataType dataType    = dataPoints[0].heartType;
                DateTime      currentTime = DateTime.Now;


                string filePath = System.Environment.GetFolderPath(Environment.SpecialFolder.Personal);

                string backingFile = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), fileName);
                // TODO: "FILESTORAGE" [0] this needs a better solution, writing to temp and replacing it solves most file loss, but not ram usage, so should probably use appending so you don't need to read the whole file to memory every time
                // TODO: "FILESTORAGE" cont [1]: this should probably use a version of https://stackoverflow.com/a/39562216 but instead of dropping the last few lines, you store them and add them back into the file after adding the new objects

                Java.IO.File file = new Java.IO.File(backingFile);
                if (file.Exists())//if the file exists, delete it.// TODO: "FILESTORAGE" cont [2]: this is probably where it should be split into two different methods, one for storing and creating a new file, and one for 'appending'
                {
                    HeartDebugHandler.debugLog("File already exists, will be overwritten");
                    file.Delete();
                }

                //string debugString = "";

                using (var writer = System.IO.File.CreateText(backingFile))
                {
                    //made these to make the print statements a bit more readable(although they could probably be made better).
                    var indentOne   = "\t";
                    var indentTwo   = "\t\t";
                    var indentThree = "\t\t\t";
                    await writer.WriteLineAsync("{");                                                               //debugString += "{";

                    await writer.WriteLineAsync(indentOne + "\"updated\": \"" + currentTime.ToString("O") + "\","); //debugString += indentOne + "\"updated\": \"" + currentTime.ToString("O") + "\",";

                    await writer.WriteLineAsync(indentOne + "\"dataType\": \"" + dataType.ToString("G") + "\",");   //debugString += indentOne + "\"dataType\": \"" + dataType.ToString("G") + "\",";

                    await writer.WriteLineAsync(indentOne + "\"data\": [");                                         //debugString += indentOne + "\"data\": [";

                    for (int i = 0; i < dataPoints.Count; i++)
                    {
                        HeartDataPoint point = dataPoints[i];
                        await writer.WriteLineAsync(indentTwo + "{");                                                               //debugString += indentTwo + "{";

                        await writer.WriteLineAsync(indentThree + "\"DateTime\": " + "\"" + point.timestamp.ToString("O") + "\","); //debugString += indentThree + "\"DateTime\": " + "\"" + point.timestamp.ToString("O") + "\",";

                        await writer.WriteLineAsync(indentThree + "\"Value\": " + "\"" + point.amount + "\",");                     //debugString += indentThree + "\"Value\": " + point.amount;

                        await writer.WriteLineAsync(indentThree + "\"accuracy\": " + "\"" + point.accuracy + "\"");

                        string lastLine = "}";
                        if (i < dataPoints.Count - 1)
                        {
                            lastLine += ",";
                        }
                        await writer.WriteLineAsync(indentTwo + lastLine); //debugString += indentTwo + lastLine;
                    }
                    await writer.WriteLineAsync(indentOne + "]");          //debugString += indentOne + "]";

                    await writer.WriteLineAsync("}");                      //debugString += "}";
                }
                dataStatusHandler.updateStatus("File saved");
                //if (debugString != "")
                //{
                //    HeartDebugHandler.debugLog("File that was saved: ");
                //    HeartDebugHandler.debugLog(debugString);
                //}
                //else
                //{
                //    HeartDebugHandler.debugLog("debug string contained nothing");
                //}
            }
            else
            {
                HeartDebugHandler.debugLog("No data to write, operation cancelled");
                dataStatusHandler.updateStatus("No data to store");
            }
        }
        /// <summary>
        /// Reads data from a file, and converts it into instances of the HeartData class, then returns an awaitable task with that data at the end of it.
        /// </summary>
        /// <param name="fileName">The filename of the file that is to be read.</param>
        /// <returns></returns>
        private static async Task <List <HeartDataPoint> > ReadDataPointsTask(string fileName)
        {
            string backingFile = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), fileName);

            HeartDebugHandler.debugLog("File to read: " + backingFile);

            if (backingFile == null || !System.IO.File.Exists(backingFile))
            {
                HeartDebugHandler.debugLog("File does not exist");
                //REMARK: this is checked against, so make sure you know what you do if you do any change to return value
                return(null); //cancel operation
            }
            HeartDebugHandler.debugLog("file exists");
            List <HeartDataPoint> dataPoints = new List <HeartDataPoint>();

            using (var reader = new StreamReader(backingFile, true))
            {
                string        line;
                HeartDataType dataType    = HeartDataType.None;
                DateTime?     date        = null;
                string        accuracy    = null;
                int           value       = -1;
                bool          dataReached = false;
                bool          param1Found = false;
                bool          param2Found = false;
                bool          param3Found = false;

                //TODO: move this into the class definition of the dataclass, probably as a builder/factory or some fitting pattern, probably a better place to handle it.
                while ((line = await reader.ReadLineAsync()) != null)
                {
                    if (!dataReached && line.Contains("dataType"))
                    {
                        string[] types = line.Split(":");
                        if (types.Length < 2)
                        {
                            HeartDebugHandler.debugLog("file error, nothing after datatype");
                            break;
                        }
                        string type = line.Split(":")[1];
                        //HeartDebugHandler.debugLog("type: " + type);
                        int first = type.IndexOf("\"") + 1;
                        //HeartDebugHandler.debugLog("first: " + first);
                        int last = type.LastIndexOf("\"");
                        //HeartDebugHandler.debugLog("last: " + last);
                        int length = last - first;
                        //HeartDebugHandler.debugLog("length: " + length);
                        string typeVal = type.Substring(first, length);

                        //HeartDebugHandler.debugLog("typeVal: " + typeVal);
                        dataType = (HeartDataType)Enum.Parse(typeof(HeartDataType), typeVal); //will crash if no match exists
                        //HeartDebugHandler.debugLog("dataType: " + dataType.ToString("G"));
                    }
                    else if (!dataReached && line.Contains("["))
                    {
                        dataReached = true;
                    }

                    if (dataReached)
                    {
                        if (line.Contains("DateTime"))
                        {
                            param1Found = true;
                            //HeartDebugHandler.debugLog("line: " + line);
                            string dateString = line.Split(new[] { ':' }, 2)[1];
                            int    first      = dateString.IndexOf("\"") + 1;
                            int    last       = dateString.LastIndexOf("\"");
                            int    length     = last - first;
                            //HeartDebugHandler.debugLog("Breakpoint");
                            dateString = dateString.Substring(first, length);
                            //HeartDebugHandler.debugLog("Breakpoint");
                            date = DateTime.Parse(dateString, null, DateTimeStyles.RoundtripKind);
                            //HeartDebugHandler.debugLog("Breakpoint");
                        }

                        if (param1Found && line.Contains("Value"))
                        {
                            param2Found = true;
                            //HeartDebugHandler.debugLog("line: " + line);
                            string valueString = line.Split(":")[1];
                            //HeartDebugHandler.debugLog("Breakpoint");
                            valueString = valueString.Replace("\"", "");
                            valueString = valueString.Replace(" ", "");
                            valueString = valueString.Replace(",", "");
                            //HeartDebugHandler.debugLog("Breakpoint");
                            value = int.Parse(valueString);
                        }

                        if (param1Found && param2Found && line.Contains("accuracy"))
                        {
                            param3Found = true;
                            string accuracyString = line.Split(new[] { ':' }, 2)[1];
                            int    first          = accuracyString.IndexOf("\"") + 1;
                            int    last           = accuracyString.LastIndexOf("\"");
                            int    length         = last - first;
                            accuracy = accuracyString.Substring(first, length);
                        }

                        if (param1Found && param2Found && param3Found)
                        {
                            if (dataType != HeartDataType.None && value != -1 && date.HasValue)
                            {
                                HeartDataPoint dataPoint = new HeartDataPoint(dataType, value, (DateTime)date, accuracy);
                                //HeartDebugHandler.debugLog("Breakpoinmarker");
                                dataPoints.Add(dataPoint);

                                //dataType = HeartDataType.None;
                                value       = -1;
                                date        = null;
                                param1Found = false;
                                param2Found = false;
                            }
                        }

                        if (line.Contains("]"))//implicit "&& dataReached"
                        {
                            dataReached = false;
                        }
                    }
                }
            }

            return(dataPoints); //return actual value
        }