Skip to content

Commit

Permalink
Merge pull request #27 from jav76/0.1.4
Browse files Browse the repository at this point in the history
V0.1.4
  • Loading branch information
jav76 authored Jul 4, 2024
2 parents cb87053 + 0eac8aa commit 25f5416
Show file tree
Hide file tree
Showing 7 changed files with 284 additions and 17 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,23 @@ Package for accessing Daylio data from exported CSV files.
The `DaylioData` class is the main class for accessing Daylio data. It has a single constructor that takes a string path to the CSV file.
Once initialized, deserialized CSV data can be accessed through `DaylioData.DataRepo`, and certain summary statistics can be accessed through `DaylioData.DataSummary`.

Example:

```csharp
DaylioData daylioData = new DaylioData("path_to_your_file.csv");
string summary = daylioData.DataSummary.GetSummary();
```

The `DaylioData.Methods` class has miscellanous helper methods for querying and aggregating data.

Example:

```csharp
IEnumerable<DaylioCSVDataModel> exampleEntries = GetEntriesWithActivity("Example Activity")
foreach (DaylioCSVDataModel entry in exampleEntries)
{
Console.WriteLine($"Activities: {entry.Activities}" + Environment.NewLine + $"Note: {entry.Note}");
}
```

Nuget: https://www.nuget.org/packages/DaylioData/
21 changes: 15 additions & 6 deletions src/DaylioData/DaylioData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,29 @@ namespace DaylioData
/// </summary>
public class DaylioData
{
private DaylioDataRepo _dataRepo;
private DaylioDataSummary _dataSummary;
private DaylioDataRepo? _dataRepo;
private DaylioDataSummary? _dataSummary;

public DaylioDataSummary DataSummary => _dataSummary;
public DaylioDataRepo DataRepo => _dataRepo;
public DaylioDataSummary? DataSummary => _dataSummary;
public DaylioDataRepo? DataRepo => _dataRepo;

/// <summary>
/// Initialize a new <see cref="DaylioData"/> class for a given <paramref name="filePath"/>.
/// Initializes a new instance of the <see cref="DaylioData"/> class.
/// </summary>
/// <param name="filePath"> Path of a Daylio CSV file.</param>
/// <param name="filePath"> Path of a Daylio CSV file to be used to initialize <see cref="DaylioDataRepo"/>.</param>
public DaylioData(string filePath)
{
_dataRepo = new DaylioDataRepo(new DaylioFileAccess(filePath));
_dataSummary = new DaylioDataSummary(_dataRepo);
Methods.InitData(this);
}

/// <summary>
/// Initializes a new instance of the <see cref="DaylioData"/> class.
/// </summary>
public DaylioData()
{

}
}
}
4 changes: 2 additions & 2 deletions src/DaylioData/DaylioData.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<BaseOutputPath>..\..\BuildResults</BaseOutputPath>
<UseCommonOutputDirectory>true</UseCommonOutputDirectory>
<AssemblyVersion>0.1.3.0</AssemblyVersion>
<Version>0.1.3</Version>
<AssemblyVersion>0.1.4.0</AssemblyVersion>
<Version>0.1.4</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
200 changes: 200 additions & 0 deletions src/DaylioData/Methods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
using DaylioData.Models;
using System.Runtime.InteropServices;

namespace DaylioData
{
public static class Methods
{
private static DaylioData? _daylioData;

public static void InitData(DaylioData daylioData)
{
_daylioData = daylioData;
}

/// <summary>
/// Gets the <see cref="DaylioCSVDataModel"/> with the earliest entry date.
/// Assumes that <see cref="DaylioData"/> has been initialized, otherwise returns null.
/// </summary>
/// <returns>The <see cref="DaylioCSVDataModel"/> with the earliest entry date</returns>
public static DaylioCSVDataModel? GetEarliestEntry()
{
return _daylioData?.DataSummary?.EarliestEntry;
}

/// <summary>
/// Gets the <see cref="DaylioCSVDataModel"/> with the earliest entry date.
/// </summary>
/// <param name="daylioData">The <see cref="DaylioData"/> instance to use.</param>
/// <returns>The <see cref="DaylioCSVDataModel"/> with the earliest entry date.</returns>
public static DaylioCSVDataModel? GetEarliestEntry(DaylioData daylioData)
{
InitData(daylioData);
return GetEarliestEntry();
}

/// <summary>
/// Gets the <see cref="DaylioCSVDataModel"/> with the latest entry date.
/// Assumes that <see cref="DaylioData"/> has been initialized, otherwise returns null.
/// </summary>
/// <returns>The <see cref="DaylioCSVDataModel"/> with the earliest entry date.</returns>
public static DaylioCSVDataModel? GetLatestEntry()
{
return _daylioData?.DataSummary?.LatestEntry;
}

/// <summary>
/// Gets the <see cref="DaylioCSVDataModel"/> with the latest entry date.
/// </summary>
/// <param name="daylioData">The <see cref="DaylioData"/> instance to use.</param>
/// <returns>The <see cref="DaylioCSVDataModel"/> with the latest entry date.</returns>
public static DaylioCSVDataModel? GetLatestEntry(DaylioData daylioData)
{
InitData(daylioData);
return GetLatestEntry();
}

/// <summary>
/// Gets <see cref="DaylioCSVDataModel"/> entries in a specified date range.
/// Assumes that <see cref="DaylioData"/> has been initialized, otherwise returns null.
/// </summary>
/// <param name="startDate">The earliest (inclusive) <see cref="DateTime"/> of entries.</param>
/// <param name="endDate">The latest (inclusive) <see cref="DateTime"/> of entries.</param>
/// <returns>An <see cref="IEnumerable{DaylioCSVDataModel}"/> of entries within the specified date range.</returns>
public static IEnumerable<DaylioCSVDataModel>? GetEntriesInRange(DateTime startDate, DateTime endDate)
{
TimeOnly startTime = TimeOnly.FromDateTime(startDate);
TimeOnly endTime = TimeOnly.FromDateTime(endDate);
return _daylioData?.DataRepo?.CSVData?.Where
(
entry =>
(entry.FullDate.ToDateTime(TimeOnly.MinValue) > startDate && // Date only comparison
entry.FullDate.ToDateTime(TimeOnly.MinValue) < endDate) ||
((entry.FullDate.ToDateTime(TimeOnly.MinValue) == startDate || entry.FullDate.ToDateTime(TimeOnly.MinValue) == endDate) && // Same date, Time comparison
entry.Time.IsBetween(startTime, endTime))
);
}

/// <summary>
/// Gets <see cref="DaylioCSVDataModel"/> entries in a specified date range.
/// </summary>
/// <param name="daylioData">The <see cref="DaylioData"/> instance to use.</param>
/// <param name="startDate">The earliest (inclusive) <see cref="DateTime"/> of entries.</param>
/// <param name="endDate">The latest (inclusive) <see cref="DateTime"/> of entries.</param>
/// <returns>An <see cref="IEnumerable{DaylioCSVDataModel}"/> of entries within the specified date range.</returns>
public static IEnumerable<DaylioCSVDataModel>? GetEntriesInRange(DaylioData daylioData, DateTime startDate, DateTime endDate)
{
InitData(daylioData);
return GetEntriesInRange(startDate, endDate);
}

/// <summary>
/// Gets <see cref="DaylioCSVDataModel"/> entries that include a specified activity
/// Assumes that <see cref="DaylioData"/> has been initialized, otherwise returns null.
/// </summary>
/// <param name="activity">An activity string</param>
/// <returns>An <see cref="IEnumerable{DaylioCSVDataModel}"/> of entries that contain the specified activity.</returns>
public static IEnumerable<DaylioCSVDataModel>? GetEntriesWithActivity(string activity)
{
if (string.IsNullOrWhiteSpace(activity) ||
_daylioData?.DataRepo?.Activities.Where(entry => entry.Equals(activity)).Any() == false)
{
return null;
}

return _daylioData?.DataRepo?.CSVData?.Where(entry => entry.ActivitiesCollection
.Any(entryActivity => entryActivity.Equals(activity, StringComparison.InvariantCultureIgnoreCase)));
}

/// <summary>
/// Gets <see cref="DaylioCSVDataModel"/> entries that include a specified activity
/// </summary>
/// <param name="daylioData">The <see cref="DaylioData"/> instance to use.</param>
/// <param name="activity">An activity string</param>
/// <returns>An <see cref="IEnumerable{DaylioCSVDataModel}"/> of entries that contain the specified activity.</returns>
public static IEnumerable<DaylioCSVDataModel>? GetEntriesWithActivity(DaylioData daylioData,string activity)
{
InitData(daylioData);
return GetEntriesWithActivity(activity);
}

/// <summary>
/// Gets <see cref="DaylioCSVDataModel"/> entries that have a specified mood.
/// Assumes that <see cref="DaylioData"/> has been initialized, otherwise returns null.
/// </summary>
/// <param name="mood">A mood string</param>
/// <returns>An <see cref="IEnumerable{DaylioCSVDataModel}"/> of entries that have the specified mood.</returns>
public static IEnumerable<DaylioCSVDataModel>? GetEntriesWithMood(string mood)
{
if (string.IsNullOrWhiteSpace(mood) ||
_daylioData?.DataRepo?.Moods.Where(entry => entry.Equals(mood)).Any() == false)
{
return null;
}

return _daylioData?.DataRepo?.CSVData?.Where(entry => entry.Mood?.Equals(mood, StringComparison.InvariantCultureIgnoreCase) == true);
}

/// <summary>
/// Gets <see cref="DaylioCSVDataModel"/> entries that have a specified mood.
/// </summary>
/// <param name="daylioData">The <see cref="DaylioData"/> instance to use.</param>
/// <param name="mood">A mood string</param>
/// <returns>An <see cref="IEnumerable{DaylioCSVDataModel}"/> of entries that have the specified mood.</returns>
public static IEnumerable<DaylioCSVDataModel>? GetEntriesWithMood(DaylioData daylioData, string mood)
{
InitData(daylioData);
return GetEntriesWithMood(mood);
}

/// <summary>
/// Gets the number of entries that include a specified activity.
/// Assumes that <see cref="DaylioData"/> has been initialized, otherwise returns null.
/// </summary>
/// <param name="activity">An activity string</param>
/// <returns>The <see cref="int"/> number of activities that include a specified activity.</returns>
public static int? GetActivityCount(string activity)
{
return _daylioData?.DataRepo?.CSVData?.Count(entry => entry.ActivitiesCollection
.Any(entryActivity => entryActivity.Equals(activity, StringComparison.InvariantCultureIgnoreCase)));
}

/// <summary>
/// Gets the number of entries that include a specified activity.
/// </summary>
/// <param name="activity">An activity string</param>
/// <returns>The <see cref="int"/> number of activities that include a specified activity.</returns>
public static int? GetActivityCount(DaylioData daylioData, string activity)
{
InitData(daylioData);
return GetActivityCount(activity);
}

/// <summary>
/// Gets <see cref="DaylioCSVDataModel"/> entries that contain a specified string in the note.
/// Assumes that <see cref="DaylioData"/> has been initialized, otherwise returns null.
/// </summary>
/// <param name="searchString">The <see cref="string"/> to search for within entries.</param>
/// <param name="comparisonMethod">The <see cref="StringComparison"/> method to use.</param>
/// <returns>An <see cref="IEnumerable{DaylioCSVDataModel}"/> of entries that contain the specified search string.</returns>
public static IEnumerable<DaylioCSVDataModel>? GetEntriesWithString(string searchString, StringComparison comparisonMethod = StringComparison.CurrentCulture)
{
return _daylioData?.DataRepo?.CSVData?.Where(entry => !string.IsNullOrWhiteSpace(entry.Note) &&
entry.Note.Contains(searchString, comparisonMethod));
}

/// <summary>
/// Gets <see cref="DaylioCSVDataModel"/> entries that contain a specified string in the note.
/// Assumes that <see cref="DaylioData"/> has been initialized, otherwise returns null.
/// </summary>
/// <param name="daylioData">The <see cref="DaylioData"/> instance to use.</param>
/// <param name="searchString">The <see cref="string"/> to search for within entries.</param>
/// <param name="comparisonMethod">The <see cref="StringComparison"/> method to use.</param>
/// <returns>An <see cref="IEnumerable{DaylioCSVDataModel}"/> of entries that contain the specified search string.</returns>
public static IEnumerable<DaylioCSVDataModel>? GetEntriesWithString(DaylioData daylioData, string searchString, StringComparison comparisonMethod = StringComparison.CurrentCulture)
{
InitData(daylioData);
return GetEntriesWithString(searchString, comparisonMethod);
}
}
}
3 changes: 3 additions & 0 deletions src/DaylioData/Models/DaylioCSVDataModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public class DaylioCSVDataModel

public override string ToString() => $"{FullDate.ToShortDateString()},{Date.DayNumber.ToString() + "-" + Date.Month.ToString()}," +
$"{Weekday},{Time},{Mood},{Activities},{NoteTitle},{Note}";

public IEnumerable<string> ActivitiesCollection => Activities?.Split(" | ")
?? Array.Empty<string>();

}
}
39 changes: 37 additions & 2 deletions src/DaylioData/Repo/DaylioDataRepo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,53 @@ public class DaylioDataRepo
{

private IEnumerable<DaylioCSVDataModel>? _CSVData;
private DaylioFileAccess? _fileAccess;

public IEnumerable<DaylioCSVDataModel>? CSVData => _CSVData;
public HashSet<string> Activities = new HashSet<string>();
public HashSet<string> Moods = new HashSet<string>();

internal DaylioDataRepo(DaylioFileAccess fileAccess)
{
_fileAccess = fileAccess;
_CSVData = _fileAccess.TryReadFile();
InitializeActivities();
InitializeMoods();
}

_CSVData = fileAccess.TryReadFile();
public void UpdateFile(string filePath)
{
_fileAccess?.SetFilePath(filePath);
_CSVData = _fileAccess?.TryReadFile();
Activities.Clear();
Moods.Clear();
InitializeActivities();
InitializeMoods();
}

/// <summary>
/// Moods can be customized and can be any string. This will keep track of all unique moods.
/// </summary>
/// <remarks>Unfortunately there is no way to assign a scale to the moods from the CSV data. This could potentially eventually be done through a manual assignment extension. </remarks>
private void InitializeMoods()
{
if (_CSVData == null)
{
return;
}

foreach (string? mood in _CSVData.Select(x => x.Mood).Distinct())
{
if (mood != null)
{
Moods.Add(mood);
}
}
}

/// <summary>
/// There can be any number of custom activities. This will keep track of all unique activities.
/// </summary>
private void InitializeActivities()
{
if (_CSVData == null)
Expand All @@ -32,6 +68,5 @@ private void InitializeActivities()
Activities.Add(activitiy);
}
}

}
}
20 changes: 13 additions & 7 deletions src/DaylioData/Repo/DaylioFileAccess.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using CsvHelper;
using DaylioData.Models;
using System.Diagnostics;
using System.Globalization;

namespace DaylioData.Repo
Expand All @@ -20,6 +21,16 @@ public class DaylioFileAccess

private string _filePath = string.Empty;

internal DaylioFileAccess(string filePath)
{
_filePath = filePath;
}

internal void SetFilePath(string filePath)
{
_filePath = filePath;
}

public static HashSet<string> CSVHeaders = new HashSet<string>()
{
FULL_DATE_HEADER,
Expand All @@ -32,11 +43,6 @@ public class DaylioFileAccess
NOTE_HEADER
};

internal DaylioFileAccess(string filePath)
{
_filePath = filePath;
}

internal IEnumerable<DaylioCSVDataModel>? TryReadFile()
{
List<DaylioCSVDataModel> CSVData = new List<DaylioCSVDataModel>();
Expand Down Expand Up @@ -68,12 +74,12 @@ internal DaylioFileAccess(string filePath)
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
Debug.WriteLine(ex.Message);
return null;
}
catch (InvalidDataException ex)
{
Console.WriteLine(ex.Message);
Debug.WriteLine(ex.Message);
return null;
}

Expand Down

0 comments on commit 25f5416

Please sign in to comment.