diff --git a/PainTrackerPT/Controllers/Analytics/AnalyticsLogsController.cs b/PainTrackerPT/Controllers/Analytics/AnalyticsLogsController.cs index d032042..1acbe61 100644 --- a/PainTrackerPT/Controllers/Analytics/AnalyticsLogsController.cs +++ b/PainTrackerPT/Controllers/Analytics/AnalyticsLogsController.cs @@ -5,24 +5,67 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.EntityFrameworkCore; -using PainTrackerPT.Models; +using PainTrackerPT.Data.Analytics; using PainTrackerPT.Models.Analytics; +using analyticsModel = PainTrackerPT.Models.Analytics.GFPatient; +using PainTrackerPT.Trends; +using PainTrackerPT.Trends.Aggregate; namespace PainTrackerPT.Controllers { public class AnalyticsLogsController : Controller { - private readonly PainTrackerPTContext _context; - public AnalyticsLogsController(PainTrackerPTContext context) + private readonly IGinyuGateway _gateway; + private readonly IGFPatientGateway _patientGateway; + private readonly IGFPatientMedicineIntakeGateway _patientMedicineIntakeGateway; + + public AnalyticsLogsController(IGinyuGateway gateway, IGFPatientGateway _patient, IGFPatientMedicineIntakeGateway _medicineIntake) { - _context = context; + _gateway = gateway; + _patientGateway = _patient; + _patientMedicineIntakeGateway = _medicineIntake; + } + + public async Task<ActionResult> PatientTrend() + { + analyticsModel.PainDiary PainDiary = _patientGateway.SelectById(1); + List<analyticsModel.MedicineIntake> Mitl = _patientMedicineIntakeGateway.SelectAll(); + + //All trends related to PainDiary + IPatientTrend PainIntensityTrend = new PainIntensityTrend(PainDiary.PainIntensity); + IPatientTrend SleepTrend = new SleepTrend(PainDiary.Sleep); + IPatientTrend MoodTrend = new MoodTrend(PainDiary.Mood); + IPatientPatternTrend InterferenceTrend = new InterferenceTrend(PainDiary.Interference); + + //Trends related to MedicineIntake + IPatientTrend MedicineIntakeTrend = new MedicineIntakeTrend(Mitl); + + //Plot SuperImposed Graph in view + ViewBag.PainIntensityPlots = PainIntensityTrend.PlotGraph(); + ViewBag.InterferencePlots = InterferenceTrend.PlotGraph(); + ViewBag.MoodPlots = MoodTrend.PlotGraph(); + ViewBag.SleepPlots = SleepTrend.PlotGraph(); + ViewBag.MedicineIntakePlots = MedicineIntakeTrend.PlotGraph(); + + + //Send PieChart data to frontend + ViewBag.PainAreaPie = PainIntensityTrend.PlotPie(); + ViewBag.MoodDoughnut = MoodTrend.PlotPie(); + + //Send Pattern data to front end + ViewBag.InterferenceRows = InterferenceTrend.RetrievePattern(); + ViewBag.SleepRows = SleepTrend.PlotPie(); + + return View(); } // GET: AnalyticsLogs public async Task<IActionResult> Index() { - return View(await _context.AnalyticsLog.ToListAsync()); + //Currently Retrieving a specific user information for testing + return View(_gateway.SelectAll()); + //return View(_patientGateway.SelectById(1)); } // GET: AnalyticsLogs/Details/5 @@ -33,8 +76,8 @@ public async Task<IActionResult> Details(Guid? id) return NotFound(); } - var analyticsLog = await _context.AnalyticsLog - .FirstOrDefaultAsync(m => m.Id == id); + var analyticsLog = _gateway.Find(id); + if (analyticsLog == null) { return NotFound(); @@ -59,8 +102,9 @@ public async Task<IActionResult> Create([Bind("Id,Description,timeStamp")] Analy if (ModelState.IsValid) { analyticsLog.Id = Guid.NewGuid(); - _context.Add(analyticsLog); - await _context.SaveChangesAsync(); + + _gateway.Insert(analyticsLog); + _gateway.Save(); return RedirectToAction(nameof(Index)); } return View(analyticsLog); @@ -74,7 +118,7 @@ public async Task<IActionResult> Edit(Guid? id) return NotFound(); } - var analyticsLog = await _context.AnalyticsLog.FindAsync(id); + var analyticsLog = _gateway.Find(id); if (analyticsLog == null) { return NotFound(); @@ -98,8 +142,9 @@ public async Task<IActionResult> Edit(Guid id, [Bind("Id,Description,timeStamp") { try { - _context.Update(analyticsLog); - await _context.SaveChangesAsync(); + _gateway.Update(analyticsLog); + _gateway.Save(); + } catch (DbUpdateConcurrencyException) { @@ -125,8 +170,7 @@ public async Task<IActionResult> Delete(Guid? id) return NotFound(); } - var analyticsLog = await _context.AnalyticsLog - .FirstOrDefaultAsync(m => m.Id == id); + var analyticsLog = _gateway.Find(id); if (analyticsLog == null) { return NotFound(); @@ -140,15 +184,14 @@ public async Task<IActionResult> Delete(Guid? id) [ValidateAntiForgeryToken] public async Task<IActionResult> DeleteConfirmed(Guid id) { - var analyticsLog = await _context.AnalyticsLog.FindAsync(id); - _context.AnalyticsLog.Remove(analyticsLog); - await _context.SaveChangesAsync(); + _gateway.Delete(id); + _gateway.Save(); return RedirectToAction(nameof(Index)); } private bool AnalyticsLogExists(Guid id) { - return _context.AnalyticsLog.Any(e => e.Id == id); + return _gateway.Exist(id); } } } diff --git a/PainTrackerPT/Data/Analytics/GFPatientGateway.cs b/PainTrackerPT/Data/Analytics/GFPatientGateway.cs new file mode 100644 index 0000000..6103842 --- /dev/null +++ b/PainTrackerPT/Data/Analytics/GFPatientGateway.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using PainTrackerPT.Models; +using PainTrackerPT.Models.Analytics.GFPatient; + +namespace PainTrackerPT.Data.Analytics +{ + public class GFPatientGateway : IGFPatientGateway + { + private readonly PainTrackerPTContext _context; + public GFPatientGateway(PainTrackerPTContext context) + { + _context = context; + } + + public PainDiary SelectById(int? id) + { + List<Interference> interferenceList = new List<Interference>(); + List<Mood> moodList = new List<Mood>(); + List<Sleep> sleepList = new List<Sleep>(); + List<PainIntensity> painIntensityList = new List<PainIntensity>(); + + //retrieve painDiary based on patient id + PainDiary pain = _context.PainDiary.Find(id); + + //retrieve all records tied to patient pain diaries + pain.Interference = retrieveInterferenceById(pain.PainDiaryID); + pain.Mood = retrieveMoodById(pain.PainDiaryID); + pain.Sleep = retrieveSleepById(pain.PainDiaryID); + pain.PainIntensity = retrievePainIntensityById(pain.PainDiaryID); + + return pain; + } + + public List<Interference> retrieveInterferenceById(int? id) + { + List<Interference> list = new List<Interference>(); + foreach (Interference entry in _context.Interference) + { + if (entry.PainDiaryID == id) + { + list.Add(entry); + } + } + return list; + } + + public List<Mood> retrieveMoodById(int? id) + { + List<Mood> list = new List<Mood>(); + foreach (Mood entry in _context.Mood) + { + if (entry.PainDiaryID == id) + { + list.Add(entry); + } + } + return list; + } + + public List<PainIntensity> retrievePainIntensityById(int? id) + { + List<PainIntensity> list = new List<PainIntensity>(); + foreach (PainIntensity entry in _context.PainIntensity) + { + if (entry.PainDiaryID == id) + { + list.Add(entry); + } + } + return list; + } + + public List<Sleep> retrieveSleepById(int? id) + { + List<Sleep> list = new List<Sleep>(); + foreach (Sleep entry in _context.Sleep) + { + if (entry.PainDiaryID == id) + { + list.Add(entry); + } + } + return list; + } + } +} diff --git a/PainTrackerPT/Data/Analytics/GFPatientMedicineIntakeGateway.cs b/PainTrackerPT/Data/Analytics/GFPatientMedicineIntakeGateway.cs new file mode 100644 index 0000000..12112fe --- /dev/null +++ b/PainTrackerPT/Data/Analytics/GFPatientMedicineIntakeGateway.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using PainTrackerPT.Models; +using PainTrackerPT.Models.Analytics.GFPatient; + +namespace PainTrackerPT.Data.Analytics +{ + public class GFPatientMedicineIntakeGateway : IGFPatientMedicineIntakeGateway + { + private readonly PainTrackerPTContext _context; + public GFPatientMedicineIntakeGateway(PainTrackerPTContext context) + { + _context = context; + } + + public List<MedicineIntake> SelectAll() + { + List<MedicineIntake> MedicineIntakeList = new List<MedicineIntake>(); + //retrieve painDiary based on patient id + MedicineIntakeList = _context.MedicineIntake.ToList(); + return MedicineIntakeList; + + } + } +} diff --git a/PainTrackerPT/Data/Analytics/GinyuGateway.cs b/PainTrackerPT/Data/Analytics/GinyuGateway.cs new file mode 100644 index 0000000..5878347 --- /dev/null +++ b/PainTrackerPT/Data/Analytics/GinyuGateway.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using PainTrackerPT.Models; +using PainTrackerPT.Models.Analytics; + +namespace PainTrackerPT.Data.Analytics +{ + public class GinyuGateway : IGinyuGateway + { + private readonly PainTrackerPTContext _context; + + public GinyuGateway(PainTrackerPTContext context) + { + _context = context; + } + + public IEnumerable<AnalyticsLog> SelectAll() + { + return _context.AnalyticsLog.ToList(); + } + + public AnalyticsLog SelectById(int? id) + { + return _context.AnalyticsLog.Find(id); + } + + public AnalyticsLog Find(Guid? id) + { + return _context.AnalyticsLog.FirstOrDefault(m => m.Id == id); + } + + public void Insert(AnalyticsLog analyticsLog) + { + _context.Add(analyticsLog); + + } + + public void Delete(Guid id) + { + AnalyticsLog analyticsLog = _context.AnalyticsLog.Find(id); + _context.AnalyticsLog.Remove(analyticsLog); + } + + public void Update(AnalyticsLog analyticsLog) + { + _context.Update(analyticsLog); + } + + public void Save() + { + _context.SaveChangesAsync(); + } + + public bool Exist(Guid? id) + { + return _context.AnalyticsLog.Any(e => e.Id == id); + + } + } +} diff --git a/PainTrackerPT/Data/Analytics/IGFPatientGateway.cs b/PainTrackerPT/Data/Analytics/IGFPatientGateway.cs new file mode 100644 index 0000000..f47cc82 --- /dev/null +++ b/PainTrackerPT/Data/Analytics/IGFPatientGateway.cs @@ -0,0 +1,18 @@ +using PainTrackerPT.Models.Analytics.GFPatient; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PainTrackerPT.Data.Analytics +{ + public interface IGFPatientGateway + { + PainDiary SelectById(int? id); + List<Interference> retrieveInterferenceById(int? id); + List<Mood> retrieveMoodById(int? id); + List<Sleep> retrieveSleepById(int? id); + List<PainIntensity> retrievePainIntensityById(int? id); + + } +} diff --git a/PainTrackerPT/Data/Analytics/IGFPatientMedicineIntakeGateway.cs b/PainTrackerPT/Data/Analytics/IGFPatientMedicineIntakeGateway.cs new file mode 100644 index 0000000..eaddab7 --- /dev/null +++ b/PainTrackerPT/Data/Analytics/IGFPatientMedicineIntakeGateway.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using PainTrackerPT.Models.Analytics.GFPatient; + +namespace PainTrackerPT.Data.Analytics +{ + public interface IGFPatientMedicineIntakeGateway + { + List<MedicineIntake> SelectAll(); + } +} diff --git a/PainTrackerPT/Data/Analytics/IGinyuGateway.cs b/PainTrackerPT/Data/Analytics/IGinyuGateway.cs new file mode 100644 index 0000000..cef8c47 --- /dev/null +++ b/PainTrackerPT/Data/Analytics/IGinyuGateway.cs @@ -0,0 +1,23 @@ +using PainTrackerPT.Models.Analytics; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PainTrackerPT.Data.Analytics +{ + public interface IGinyuGateway + { + //implement CRUD for Logger + IEnumerable<AnalyticsLog> SelectAll(); + AnalyticsLog SelectById(int? id); + AnalyticsLog Find(Guid? id); + Boolean Exist(Guid? id); + + void Update(AnalyticsLog analyticsLog); + void Delete(Guid id); + void Insert(AnalyticsLog analyticsLog); + + void Save(); + } +} diff --git a/PainTrackerPT/Data/PainTrackerPTContext.cs b/PainTrackerPT/Data/PainTrackerPTContext.cs index aa11e3f..6a903fe 100644 --- a/PainTrackerPT/Data/PainTrackerPTContext.cs +++ b/PainTrackerPT/Data/PainTrackerPTContext.cs @@ -19,6 +19,14 @@ public PainTrackerPTContext (DbContextOptions<PainTrackerPTContext> options) { } + //Ginyu Force Analytics + public DbSet<PainTrackerPT.Models.Analytics.GFPatient.PainDiary> PainDiary { get; set; } + public DbSet<PainTrackerPT.Models.Analytics.GFPatient.Interference> Interference { get; set; } + public DbSet<PainTrackerPT.Models.Analytics.GFPatient.Mood> Mood { get; set; } + public DbSet<PainTrackerPT.Models.Analytics.GFPatient.PainIntensity> PainIntensity { get; set; } + public DbSet<PainTrackerPT.Models.Analytics.GFPatient.Sleep> Sleep { get; set; } + public DbSet<PainTrackerPT.Models.Analytics.GFPatient.MedicineIntake> MedicineIntake { get; set; } + public DbSet<PainTrackerPT.Models.Analytics.AnalyticsLog> AnalyticsLog { get; set; } public DbSet<PainTrackerPT.Models.Doctors.DoctorsLog> DoctorsLog { get; set; } diff --git a/PainTrackerPT/Migrations/20190402113130_Ginyu.Designer.cs b/PainTrackerPT/Migrations/20190402113130_Ginyu.Designer.cs new file mode 100644 index 0000000..a7e427d --- /dev/null +++ b/PainTrackerPT/Migrations/20190402113130_Ginyu.Designer.cs @@ -0,0 +1,277 @@ +// <auto-generated /> +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PainTrackerPT.Models; + +namespace PainTrackerPT.Migrations +{ + [DbContext(typeof(PainTrackerPTContext))] + [Migration("20190402113130_Ginyu")] + partial class Ginyu + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.1-servicing-10028") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.AnalyticsLog", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Description"); + + b.Property<DateTime>("timeStamp"); + + b.HasKey("Id"); + + b.ToTable("AnalyticsLog"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.Interference", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<DateTime>("Date") + .HasColumnName("Date"); + + b.Property<string>("Description") + .HasColumnName("Description"); + + b.Property<int>("Duration") + .HasColumnName("Duration"); + + b.Property<int>("PainDiaryID"); + + b.Property<int>("Severity") + .HasColumnName("Severity"); + + b.HasKey("Id"); + + b.HasIndex("PainDiaryID"); + + b.ToTable("Interference"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.MedicineIntake", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<DateTime>("Date") + .HasColumnName("Date"); + + b.Property<double>("Dosage") + .HasColumnName("Dosage"); + + b.HasKey("Id"); + + b.ToTable("MedicineIntake"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.Mood", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<DateTime>("Date") + .HasColumnName("Date"); + + b.Property<int>("Duration") + .HasColumnName("Duration"); + + b.Property<int>("MoodType") + .HasColumnName("MoodType"); + + b.Property<int>("PainDiaryID"); + + b.HasKey("Id"); + + b.HasIndex("PainDiaryID"); + + b.ToTable("Mood"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.PainDiary", b => + { + b.Property<int>("PainDiaryID") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<int>("PatientID"); + + b.HasKey("PainDiaryID"); + + b.ToTable("PainDiary"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.PainIntensity", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<DateTime>("Date") + .HasColumnName("Date"); + + b.Property<int>("Duration") + .HasColumnName("Duration"); + + b.Property<int>("PainArea") + .HasColumnName("PainArea"); + + b.Property<int>("PainDiaryID"); + + b.Property<int>("PainRating") + .HasColumnName("PainRating"); + + b.HasKey("Id"); + + b.HasIndex("PainDiaryID"); + + b.ToTable("PainIntensity"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.Sleep", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<int>("ComfortLevel") + .HasColumnName("ComfortLevel"); + + b.Property<DateTime>("Date") + .HasColumnName("Date"); + + b.Property<int>("PainDiaryID"); + + b.Property<int>("SleepHours") + .HasColumnName("SleepHours"); + + b.Property<int>("Tiredness") + .HasColumnName("Tiredness"); + + b.HasKey("Id"); + + b.HasIndex("PainDiaryID"); + + b.ToTable("Sleep"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Doctors.DoctorsLog", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Description"); + + b.Property<DateTime>("timeStamp"); + + b.HasKey("Id"); + + b.ToTable("DoctorsLog"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Events.EventsLog", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Description"); + + b.Property<DateTime>("timeStamp"); + + b.HasKey("Id"); + + b.ToTable("EventsLog"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Followups.FollowupsLog", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Description"); + + b.Property<DateTime>("timeStamp"); + + b.HasKey("Id"); + + b.ToTable("FollowupsLog"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Medicine.MedicineLog", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Description"); + + b.Property<DateTime>("timeStamp"); + + b.HasKey("Id"); + + b.ToTable("MedicineLog"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.PainDiary.PainDiaryLog", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Description"); + + b.Property<DateTime>("timeStamp"); + + b.HasKey("Id"); + + b.ToTable("PainDiaryLog"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.Interference", b => + { + b.HasOne("PainTrackerPT.Models.Analytics.GFPatient.PainDiary") + .WithMany("Interference") + .HasForeignKey("PainDiaryID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.Mood", b => + { + b.HasOne("PainTrackerPT.Models.Analytics.GFPatient.PainDiary") + .WithMany("Mood") + .HasForeignKey("PainDiaryID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.PainIntensity", b => + { + b.HasOne("PainTrackerPT.Models.Analytics.GFPatient.PainDiary") + .WithMany("PainIntensity") + .HasForeignKey("PainDiaryID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.Sleep", b => + { + b.HasOne("PainTrackerPT.Models.Analytics.GFPatient.PainDiary") + .WithMany("Sleep") + .HasForeignKey("PainDiaryID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/PainTrackerPT/Migrations/20190402113130_Ginyu.cs b/PainTrackerPT/Migrations/20190402113130_Ginyu.cs new file mode 100644 index 0000000..54d3a7c --- /dev/null +++ b/PainTrackerPT/Migrations/20190402113130_Ginyu.cs @@ -0,0 +1,267 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace PainTrackerPT.Migrations +{ + public partial class Ginyu : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AnalyticsLog", + columns: table => new + { + Id = table.Column<Guid>(nullable: false), + Description = table.Column<string>(nullable: true), + timeStamp = table.Column<DateTime>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AnalyticsLog", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "DoctorsLog", + columns: table => new + { + Id = table.Column<Guid>(nullable: false), + Description = table.Column<string>(nullable: true), + timeStamp = table.Column<DateTime>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DoctorsLog", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "EventsLog", + columns: table => new + { + Id = table.Column<Guid>(nullable: false), + Description = table.Column<string>(nullable: true), + timeStamp = table.Column<DateTime>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EventsLog", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "FollowupsLog", + columns: table => new + { + Id = table.Column<Guid>(nullable: false), + Description = table.Column<string>(nullable: true), + timeStamp = table.Column<DateTime>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_FollowupsLog", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "MedicineIntake", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + Date = table.Column<DateTime>(nullable: false), + Dosage = table.Column<double>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_MedicineIntake", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "MedicineLog", + columns: table => new + { + Id = table.Column<Guid>(nullable: false), + Description = table.Column<string>(nullable: true), + timeStamp = table.Column<DateTime>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_MedicineLog", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "PainDiary", + columns: table => new + { + PainDiaryID = table.Column<int>(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + PatientID = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PainDiary", x => x.PainDiaryID); + }); + + migrationBuilder.CreateTable( + name: "PainDiaryLog", + columns: table => new + { + Id = table.Column<Guid>(nullable: false), + Description = table.Column<string>(nullable: true), + timeStamp = table.Column<DateTime>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PainDiaryLog", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Interference", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + Date = table.Column<DateTime>(nullable: false), + Description = table.Column<string>(nullable: true), + Severity = table.Column<int>(nullable: false), + Duration = table.Column<int>(nullable: false), + PainDiaryID = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Interference", x => x.Id); + table.ForeignKey( + name: "FK_Interference_PainDiary_PainDiaryID", + column: x => x.PainDiaryID, + principalTable: "PainDiary", + principalColumn: "PainDiaryID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Mood", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + Date = table.Column<DateTime>(nullable: false), + MoodType = table.Column<int>(nullable: false), + Duration = table.Column<int>(nullable: false), + PainDiaryID = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Mood", x => x.Id); + table.ForeignKey( + name: "FK_Mood_PainDiary_PainDiaryID", + column: x => x.PainDiaryID, + principalTable: "PainDiary", + principalColumn: "PainDiaryID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PainIntensity", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + Date = table.Column<DateTime>(nullable: false), + PainRating = table.Column<int>(nullable: false), + PainArea = table.Column<int>(nullable: false), + Duration = table.Column<int>(nullable: false), + PainDiaryID = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PainIntensity", x => x.Id); + table.ForeignKey( + name: "FK_PainIntensity_PainDiary_PainDiaryID", + column: x => x.PainDiaryID, + principalTable: "PainDiary", + principalColumn: "PainDiaryID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Sleep", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + Date = table.Column<DateTime>(nullable: false), + SleepHours = table.Column<int>(nullable: false), + ComfortLevel = table.Column<int>(nullable: false), + Tiredness = table.Column<int>(nullable: false), + PainDiaryID = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Sleep", x => x.Id); + table.ForeignKey( + name: "FK_Sleep_PainDiary_PainDiaryID", + column: x => x.PainDiaryID, + principalTable: "PainDiary", + principalColumn: "PainDiaryID", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Interference_PainDiaryID", + table: "Interference", + column: "PainDiaryID"); + + migrationBuilder.CreateIndex( + name: "IX_Mood_PainDiaryID", + table: "Mood", + column: "PainDiaryID"); + + migrationBuilder.CreateIndex( + name: "IX_PainIntensity_PainDiaryID", + table: "PainIntensity", + column: "PainDiaryID"); + + migrationBuilder.CreateIndex( + name: "IX_Sleep_PainDiaryID", + table: "Sleep", + column: "PainDiaryID"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AnalyticsLog"); + + migrationBuilder.DropTable( + name: "DoctorsLog"); + + migrationBuilder.DropTable( + name: "EventsLog"); + + migrationBuilder.DropTable( + name: "FollowupsLog"); + + migrationBuilder.DropTable( + name: "Interference"); + + migrationBuilder.DropTable( + name: "MedicineIntake"); + + migrationBuilder.DropTable( + name: "MedicineLog"); + + migrationBuilder.DropTable( + name: "Mood"); + + migrationBuilder.DropTable( + name: "PainDiaryLog"); + + migrationBuilder.DropTable( + name: "PainIntensity"); + + migrationBuilder.DropTable( + name: "Sleep"); + + migrationBuilder.DropTable( + name: "PainDiary"); + } + } +} diff --git a/PainTrackerPT/Migrations/PainTrackerPTContextModelSnapshot.cs b/PainTrackerPT/Migrations/PainTrackerPTContextModelSnapshot.cs new file mode 100644 index 0000000..7c08260 --- /dev/null +++ b/PainTrackerPT/Migrations/PainTrackerPTContextModelSnapshot.cs @@ -0,0 +1,275 @@ +// <auto-generated /> +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PainTrackerPT.Models; + +namespace PainTrackerPT.Migrations +{ + [DbContext(typeof(PainTrackerPTContext))] + partial class PainTrackerPTContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.1-servicing-10028") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.AnalyticsLog", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Description"); + + b.Property<DateTime>("timeStamp"); + + b.HasKey("Id"); + + b.ToTable("AnalyticsLog"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.Interference", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<DateTime>("Date") + .HasColumnName("Date"); + + b.Property<string>("Description") + .HasColumnName("Description"); + + b.Property<int>("Duration") + .HasColumnName("Duration"); + + b.Property<int>("PainDiaryID"); + + b.Property<int>("Severity") + .HasColumnName("Severity"); + + b.HasKey("Id"); + + b.HasIndex("PainDiaryID"); + + b.ToTable("Interference"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.MedicineIntake", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<DateTime>("Date") + .HasColumnName("Date"); + + b.Property<double>("Dosage") + .HasColumnName("Dosage"); + + b.HasKey("Id"); + + b.ToTable("MedicineIntake"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.Mood", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<DateTime>("Date") + .HasColumnName("Date"); + + b.Property<int>("Duration") + .HasColumnName("Duration"); + + b.Property<int>("MoodType") + .HasColumnName("MoodType"); + + b.Property<int>("PainDiaryID"); + + b.HasKey("Id"); + + b.HasIndex("PainDiaryID"); + + b.ToTable("Mood"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.PainDiary", b => + { + b.Property<int>("PainDiaryID") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<int>("PatientID"); + + b.HasKey("PainDiaryID"); + + b.ToTable("PainDiary"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.PainIntensity", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<DateTime>("Date") + .HasColumnName("Date"); + + b.Property<int>("Duration") + .HasColumnName("Duration"); + + b.Property<int>("PainArea") + .HasColumnName("PainArea"); + + b.Property<int>("PainDiaryID"); + + b.Property<int>("PainRating") + .HasColumnName("PainRating"); + + b.HasKey("Id"); + + b.HasIndex("PainDiaryID"); + + b.ToTable("PainIntensity"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.Sleep", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property<int>("ComfortLevel") + .HasColumnName("ComfortLevel"); + + b.Property<DateTime>("Date") + .HasColumnName("Date"); + + b.Property<int>("PainDiaryID"); + + b.Property<int>("SleepHours") + .HasColumnName("SleepHours"); + + b.Property<int>("Tiredness") + .HasColumnName("Tiredness"); + + b.HasKey("Id"); + + b.HasIndex("PainDiaryID"); + + b.ToTable("Sleep"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Doctors.DoctorsLog", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Description"); + + b.Property<DateTime>("timeStamp"); + + b.HasKey("Id"); + + b.ToTable("DoctorsLog"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Events.EventsLog", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Description"); + + b.Property<DateTime>("timeStamp"); + + b.HasKey("Id"); + + b.ToTable("EventsLog"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Followups.FollowupsLog", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Description"); + + b.Property<DateTime>("timeStamp"); + + b.HasKey("Id"); + + b.ToTable("FollowupsLog"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Medicine.MedicineLog", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Description"); + + b.Property<DateTime>("timeStamp"); + + b.HasKey("Id"); + + b.ToTable("MedicineLog"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.PainDiary.PainDiaryLog", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Description"); + + b.Property<DateTime>("timeStamp"); + + b.HasKey("Id"); + + b.ToTable("PainDiaryLog"); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.Interference", b => + { + b.HasOne("PainTrackerPT.Models.Analytics.GFPatient.PainDiary") + .WithMany("Interference") + .HasForeignKey("PainDiaryID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.Mood", b => + { + b.HasOne("PainTrackerPT.Models.Analytics.GFPatient.PainDiary") + .WithMany("Mood") + .HasForeignKey("PainDiaryID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.PainIntensity", b => + { + b.HasOne("PainTrackerPT.Models.Analytics.GFPatient.PainDiary") + .WithMany("PainIntensity") + .HasForeignKey("PainDiaryID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("PainTrackerPT.Models.Analytics.GFPatient.Sleep", b => + { + b.HasOne("PainTrackerPT.Models.Analytics.GFPatient.PainDiary") + .WithMany("Sleep") + .HasForeignKey("PainDiaryID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/PainTrackerPT/Models/Analytics/GFPatient/Interference.cs b/PainTrackerPT/Models/Analytics/GFPatient/Interference.cs new file mode 100644 index 0000000..98d8f5b --- /dev/null +++ b/PainTrackerPT/Models/Analytics/GFPatient/Interference.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Threading.Tasks; + +namespace PainTrackerPT.Models.Analytics.GFPatient +{ + public class Interference + { + [Key] + public int Id { get; set; } + + [Column("Date")] + public DateTime Date { get; set; } + + [Column("Description")] + public string Description { get; set; } + + [Column("Severity")] + public int Severity { get; set; } + + [Column("Duration")] + public int Duration { get; set; } + + [ForeignKey("PainDiary")] + public int PainDiaryID { get; set; } + + + + + } +} diff --git a/PainTrackerPT/Models/Analytics/GFPatient/MedicineIntake.cs b/PainTrackerPT/Models/Analytics/GFPatient/MedicineIntake.cs new file mode 100644 index 0000000..49bc123 --- /dev/null +++ b/PainTrackerPT/Models/Analytics/GFPatient/MedicineIntake.cs @@ -0,0 +1,21 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PainTrackerPT.Models.Analytics.GFPatient +{ + public class MedicineIntake + { + [Key] + public int Id { get; set; } + + [Column("Date")] + public DateTime Date { get; set; } + + [Column("Dosage")] + public double Dosage { get; set; } + } +} diff --git a/PainTrackerPT/Models/Analytics/GFPatient/Mood.cs b/PainTrackerPT/Models/Analytics/GFPatient/Mood.cs new file mode 100644 index 0000000..65b214a --- /dev/null +++ b/PainTrackerPT/Models/Analytics/GFPatient/Mood.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Threading.Tasks; + +namespace PainTrackerPT.Models.Analytics.GFPatient +{ + public class Mood + { + [Key] + public int Id { get; set; } + + [Column("Date")] + public DateTime Date { get; set; } + + [Column("MoodType")] + public int MoodType { get; set; } + + [Column("Duration")] + public int Duration { get; set; } + + [ForeignKey("PainDiary")] + public int PainDiaryID { get; set; } + } +} diff --git a/PainTrackerPT/Models/Analytics/GFPatient/PainDiary.cs b/PainTrackerPT/Models/Analytics/GFPatient/PainDiary.cs new file mode 100644 index 0000000..f01a4f7 --- /dev/null +++ b/PainTrackerPT/Models/Analytics/GFPatient/PainDiary.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Threading.Tasks; + +namespace PainTrackerPT.Models.Analytics.GFPatient +{ + public class PainDiary + { + [Key] + public int PainDiaryID { get; set; } + + [ForeignKey("Patient")] + public int PatientID { get; set; } + + public virtual List<Interference> Interference { get; set; } + public virtual List<Mood> Mood { get; set; } + public virtual List<Sleep> Sleep { get; set; } + public virtual List<PainIntensity> PainIntensity { get; set; } + + } +} diff --git a/PainTrackerPT/Models/Analytics/GFPatient/PainIntensity.cs b/PainTrackerPT/Models/Analytics/GFPatient/PainIntensity.cs new file mode 100644 index 0000000..d0f8192 --- /dev/null +++ b/PainTrackerPT/Models/Analytics/GFPatient/PainIntensity.cs @@ -0,0 +1,27 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace PainTrackerPT.Models.Analytics.GFPatient +{ + public class PainIntensity + { + [Key] + public int Id { get; set; } + + [Column("Date")] + public DateTime Date { get; set; } + + [Column("PainRating")] + public int PainRating { get; set; } + + [Column("PainArea")] + public int PainArea { get; set; } + + [Column("Duration")] + public int Duration { get; set; } + + [ForeignKey("PainDiary")] + public int PainDiaryID { get; set; } + } +} diff --git a/PainTrackerPT/Models/Analytics/GFPatient/Sleep.cs b/PainTrackerPT/Models/Analytics/GFPatient/Sleep.cs new file mode 100644 index 0000000..57ae50d --- /dev/null +++ b/PainTrackerPT/Models/Analytics/GFPatient/Sleep.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Threading.Tasks; + +namespace PainTrackerPT.Models.Analytics.GFPatient +{ + public class Sleep + { + [Key] + public int Id { get; set; } + + [Column("Date")] + public DateTime Date { get; set; } + + [Column("SleepHours")] + public int SleepHours { get; set; } + + [Column("ComfortLevel")] + public int ComfortLevel { get; set; } + + [Column("Tiredness")] + public int Tiredness { get; set; } + + [ForeignKey("PainDiary")] + public int PainDiaryID { get; set; } + } +} diff --git a/PainTrackerPT/PainTrackerPT.csproj b/PainTrackerPT/PainTrackerPT.csproj index e22727b..c1e72b3 100644 --- a/PainTrackerPT/PainTrackerPT.csproj +++ b/PainTrackerPT/PainTrackerPT.csproj @@ -7,9 +7,11 @@ <ItemGroup> + <PackageReference Include="Chart.Mvc" Version="1.0.0.2" /> <PackageReference Include="Microsoft.AspNetCore.App" /> <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" /> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.0" /> + <PackageReference Include="Moment.js" Version="2.24.0" /> </ItemGroup> </Project> diff --git a/PainTrackerPT/Startup.cs b/PainTrackerPT/Startup.cs index f547274..21c172e 100644 --- a/PainTrackerPT/Startup.cs +++ b/PainTrackerPT/Startup.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.EntityFrameworkCore; using PainTrackerPT.Models; +using PainTrackerPT.Data.Analytics; namespace PainTrackerPT { @@ -38,9 +39,14 @@ public void ConfigureServices(IServiceCollection services) services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.AddDbContext<PainTrackerPTContext>(options => - //options.UseSqlServer(Configuration.GetConnectionString("PainTrackerPTContext"))); + options.UseSqlServer(Configuration.GetConnectionString("PainTrackerPTContext"))); // Just for testing use the in memory database but in real testing, create your own one. - options.UseInMemoryDatabase("PainTrackerPTContext")); + //options.UseInMemoryDatabase("PainTrackerPTContext")); + + //Add Analytics Services + services.AddScoped<IGinyuGateway, GinyuGateway>(); + services.AddScoped<IGFPatientGateway, GFPatientGateway>(); + services.AddScoped<IGFPatientMedicineIntakeGateway, GFPatientMedicineIntakeGateway>(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -65,7 +71,7 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) { routes.MapRoute( name: "default", - template: "{controller=Home}/{action=Index}/{id?}"); + template: "{controller=AnalyticsLogs}/{action=PatientTrend}/{id?}"); }); } } diff --git a/PainTrackerPT/Trends/Aggregate/InterferenceTrend.cs b/PainTrackerPT/Trends/Aggregate/InterferenceTrend.cs new file mode 100644 index 0000000..60e748b --- /dev/null +++ b/PainTrackerPT/Trends/Aggregate/InterferenceTrend.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using PainTrackerPT.Models.Analytics.GFPatient; +using PainTrackerPT.Trends.Iterator; +using System.Linq; +using System.Threading.Tasks; + +namespace PainTrackerPT.Trends.Aggregate +{ + public class InterferenceTrend : TrendAggregate, IPatientPatternTrend + { + List<Interference> InterferenceTrendList; + bool NewestFirst; + + public InterferenceTrend(List<Interference> InterferenceTrendList) + { + this.InterferenceTrendList = InterferenceTrendList; + } + + public List<KeyValuePair<DateTime, int>> PlotGraph() + { + var InterferencePlots = new List<KeyValuePair<DateTime, int>>(); + NewestFirst = false; + foreach (Interference item in this) + { + InterferencePlots.Add(new KeyValuePair<DateTime, int>(item.Date,item.Severity)); + } + return InterferencePlots; + } + + public List<KeyValuePair<int, int>> PlotPie() + { + throw new NotImplementedException(); + } + + public override IEnumerator GetEnumerator() + { + return new InterferenceTrendIterator(InterferenceTrendList, NewestFirst); + } + + public List<KeyValuePair<string, int>> RetrievePattern() + { + var InterferenceRows = new List<KeyValuePair<String, int>>(); + NewestFirst = true; + foreach (Interference item in this) + { + InterferenceRows.Add(new KeyValuePair<String, int>(item.Description, item.Duration)); + } + return InterferenceRows; + } + } +} diff --git a/PainTrackerPT/Trends/Aggregate/MedicineIntakeTrend.cs b/PainTrackerPT/Trends/Aggregate/MedicineIntakeTrend.cs new file mode 100644 index 0000000..d9c4e2f --- /dev/null +++ b/PainTrackerPT/Trends/Aggregate/MedicineIntakeTrend.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using PainTrackerPT.Models.Analytics.GFPatient; +using PainTrackerPT.Trends.Iterator; + +namespace PainTrackerPT.Trends.Aggregate +{ + public class MedicineIntakeTrend : TrendAggregate, IPatientTrend + { + List<MedicineIntake> MedicineIntakeList; + + public MedicineIntakeTrend(List<MedicineIntake> MedicineIntakeList) + { + this.MedicineIntakeList = MedicineIntakeList; + } + + public override IEnumerator GetEnumerator() + { + return new MedicineIntakeTrendIterator(MedicineIntakeList); + } + + public List<KeyValuePair<DateTime, int>> PlotGraph() + { + var MedicineIntakePlots = new List<KeyValuePair<DateTime, int>>(); + foreach (MedicineIntake item in this) + { + MedicineIntakePlots.Add(new KeyValuePair<DateTime, int>(item.Date, Convert.ToInt32(item.Dosage))); + } + return MedicineIntakePlots; + } + + public List<KeyValuePair<int, int>> PlotPie() + { + throw new NotImplementedException(); + } + } +} diff --git a/PainTrackerPT/Trends/Aggregate/MoodTrend.cs b/PainTrackerPT/Trends/Aggregate/MoodTrend.cs new file mode 100644 index 0000000..6111026 --- /dev/null +++ b/PainTrackerPT/Trends/Aggregate/MoodTrend.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using PainTrackerPT.Models.Analytics.GFPatient; +using PainTrackerPT.Trends.Iterator; + +namespace PainTrackerPT.Trends.Aggregate +{ + public class MoodTrend : TrendAggregate, IPatientTrend + { + List<Mood> MoodTrendList; + + public MoodTrend(List<Mood> MoodTrendList) + { + this.MoodTrendList = MoodTrendList; + } + public List<KeyValuePair<DateTime, int>> PlotGraph() + { + var MoodPlots = new List<KeyValuePair<DateTime, int>>(); + foreach (Mood item in this) + { + MoodPlots.Add(new KeyValuePair<DateTime, int>(item.Date, item.MoodType)); + } + return MoodPlots; + } + + public List<KeyValuePair<int, int>> PlotPie() + { + var MoodDoughnutList = new List<KeyValuePair<int, int>>(); + var MoodDoughnutGroup = from item in MoodTrendList + group item by item.MoodType into g + select new { g.Key, Count = g.Count() }; + + foreach (var md in MoodDoughnutGroup) + { + MoodDoughnutList.Add(new KeyValuePair<int, int>(md.Key, md.Count)); + } + + return MoodDoughnutList; + } + + public override IEnumerator GetEnumerator() + { + return new MoodTrendIterator(MoodTrendList); + } + } +} diff --git a/PainTrackerPT/Trends/Aggregate/PainIntensityTrend.cs b/PainTrackerPT/Trends/Aggregate/PainIntensityTrend.cs new file mode 100644 index 0000000..e5e698d --- /dev/null +++ b/PainTrackerPT/Trends/Aggregate/PainIntensityTrend.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using PainTrackerPT.Models.Analytics.GFPatient; +using PainTrackerPT.Trends.Iterator; + +namespace PainTrackerPT.Trends.Aggregate +{ + public class PainIntensityTrend : TrendAggregate, IPatientTrend + { + List<PainIntensity> PainIntensities; + + public PainIntensityTrend(List<PainIntensity> PainIntensityList) + { + PainIntensities = PainIntensityList; + } + + public List<KeyValuePair<DateTime, int>> PlotGraph() + { + var PainIntensityPlots = new List<KeyValuePair<DateTime, int>>(); + foreach (PainIntensity item in this) + { + PainIntensityPlots.Add(new KeyValuePair<DateTime, int>(item.Date, item.PainRating)); + } + return PainIntensityPlots; + } + + public List<KeyValuePair<int, int>> PlotPie() + { + var PainAreaPieList = new List<KeyValuePair<int, int>>(); + var PainAreaPieGroup = from item in PainIntensities + group item by item.PainArea into g + select new { g.Key, Count = g.Count() }; + + foreach (var pa in PainAreaPieGroup) + { + PainAreaPieList.Add(new KeyValuePair<int, int>(pa.Key, pa.Count)); + } + return PainAreaPieList; + + } + + public override IEnumerator GetEnumerator() + { + return new PainIntensityTrendIterator(this.PainIntensities); + } + } +} diff --git a/PainTrackerPT/Trends/Aggregate/SleepTrend.cs b/PainTrackerPT/Trends/Aggregate/SleepTrend.cs new file mode 100644 index 0000000..338272a --- /dev/null +++ b/PainTrackerPT/Trends/Aggregate/SleepTrend.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using PainTrackerPT.Models.Analytics.GFPatient; +using PainTrackerPT.Trends.Iterator; + +namespace PainTrackerPT.Trends.Aggregate +{ + public class SleepTrend : TrendAggregate, IPatientTrend + { + List<Sleep> SleepList; + bool NewestFirst; + + public SleepTrend(List<Sleep> SleepList) + { + this.SleepList = SleepList; + } + + + public List<KeyValuePair<DateTime, int>> PlotGraph() + { + var SleepPlots = new List<KeyValuePair<DateTime, int>>(); + NewestFirst = false; + foreach (Sleep item in this) + { + SleepPlots.Add(new KeyValuePair<DateTime, int>(item.Date, item.SleepHours)); + } + return SleepPlots; + } + + public List<KeyValuePair<int, int>> PlotPie() + { + var SleepRows = new List<KeyValuePair<int, int>>(); + NewestFirst = true; + foreach (Sleep item in this) + { + SleepRows.Add(new KeyValuePair<int, int>(item.ComfortLevel, item.Tiredness)); + } + return SleepRows; + } + + public override IEnumerator GetEnumerator() + { + return new SleepTrendIterator(SleepList,NewestFirst); + } + } +} diff --git a/PainTrackerPT/Trends/Aggregate/TrendAggregate.cs b/PainTrackerPT/Trends/Aggregate/TrendAggregate.cs new file mode 100644 index 0000000..4592e6b --- /dev/null +++ b/PainTrackerPT/Trends/Aggregate/TrendAggregate.cs @@ -0,0 +1,9 @@ +using System.Collections; + +namespace PainTrackerPT.Trends.Aggregate +{ + public abstract class TrendAggregate + { + public abstract IEnumerator GetEnumerator(); + } +} diff --git a/PainTrackerPT/Trends/IDoctorTrend.cs b/PainTrackerPT/Trends/IDoctorTrend.cs new file mode 100644 index 0000000..5d1d8ac --- /dev/null +++ b/PainTrackerPT/Trends/IDoctorTrend.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PainTrackerPT.Trends +{ + interface IDoctorTrend:ITrend + { + List<KeyValuePair<int, int>> PlotHeatMap(); + } +} diff --git a/PainTrackerPT/Trends/IPatientPatternTrend.cs b/PainTrackerPT/Trends/IPatientPatternTrend.cs new file mode 100644 index 0000000..d019314 --- /dev/null +++ b/PainTrackerPT/Trends/IPatientPatternTrend.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace PainTrackerPT.Trends +{ + public interface IPatientPatternTrend: IPatientTrend + { + List<KeyValuePair<string, int>> RetrievePattern(); + } +} diff --git a/PainTrackerPT/Trends/IPatientTrend.cs b/PainTrackerPT/Trends/IPatientTrend.cs new file mode 100644 index 0000000..330b2fe --- /dev/null +++ b/PainTrackerPT/Trends/IPatientTrend.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace PainTrackerPT.Trends +{ + public interface IPatientTrend:ITrend + { + List<KeyValuePair<int, int>> PlotPie(); + } +} diff --git a/PainTrackerPT/Trends/ITrend.cs b/PainTrackerPT/Trends/ITrend.cs new file mode 100644 index 0000000..8b1a3c3 --- /dev/null +++ b/PainTrackerPT/Trends/ITrend.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using PainTrackerPT.Models.Analytics.GFPatient; +using System.Linq; +using System.Threading.Tasks; + +namespace PainTrackerPT.Trends +{ + public interface ITrend + { + List<KeyValuePair<DateTime, int>> PlotGraph(); + } +} diff --git a/PainTrackerPT/Trends/Iterator/InterferenceTrendIterator.cs b/PainTrackerPT/Trends/Iterator/InterferenceTrendIterator.cs new file mode 100644 index 0000000..8c09a1c --- /dev/null +++ b/PainTrackerPT/Trends/Iterator/InterferenceTrendIterator.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using PainTrackerPT.Models.Analytics.GFPatient; + +namespace PainTrackerPT.Trends.Iterator +{ + public class InterferenceTrendIterator : Iterator + { + List<Interference> InterferenceTrendList; + int Position = 0; + int Flag = 0; + + + public InterferenceTrendIterator(List<Interference> InterferenceTrendList, bool NewestFirst) + { + if(NewestFirst) + this.InterferenceTrendList = InterferenceTrendList.OrderByDescending(i => i.Date).ToList(); + else + this.InterferenceTrendList = InterferenceTrendList.OrderBy(i => i.Date).ToList(); + } + + public override object Current() + { + return InterferenceTrendList[Position]; + } + + public override int Key() + { + return Position; + } + + public override bool MoveNext() + { + int updatedPosition = Position + 1; + if (Flag == 0) + { + Flag = 1; + return true; + + } + + else if (updatedPosition >= 0 && updatedPosition < InterferenceTrendList.Count) + { + Position = updatedPosition; + return true; + } + else + { + return false; + } + } + + public override void Reset() + { + Flag = 0; + Position = 0; + } + } +} diff --git a/PainTrackerPT/Trends/Iterator/Iterator.cs b/PainTrackerPT/Trends/Iterator/Iterator.cs new file mode 100644 index 0000000..0133094 --- /dev/null +++ b/PainTrackerPT/Trends/Iterator/Iterator.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections; + + +namespace PainTrackerPT.Trends.Iterator +{ + public abstract class Iterator : IEnumerator + { + object IEnumerator.Current => Current(); + + // Returns the key of the current element + public abstract int Key(); + + // Returns the current element + public abstract object Current(); + + // Move forward to next element + public abstract bool MoveNext(); + + // Rewinds the Iterator to the first element + public abstract void Reset(); + } +} diff --git a/PainTrackerPT/Trends/Iterator/MedicineIntakeTrendIterator.cs b/PainTrackerPT/Trends/Iterator/MedicineIntakeTrendIterator.cs new file mode 100644 index 0000000..bd705cd --- /dev/null +++ b/PainTrackerPT/Trends/Iterator/MedicineIntakeTrendIterator.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using PainTrackerPT.Models.Analytics.GFPatient; + +namespace PainTrackerPT.Trends.Iterator +{ + public class MedicineIntakeTrendIterator : Iterator + { + List<MedicineIntake> MedicineIntakeList; + int Position = 0; + int Flag = 0; + + public MedicineIntakeTrendIterator(List<MedicineIntake> MedicineIntakeList) + { + this.MedicineIntakeList = MedicineIntakeList.OrderBy(i => i.Date).ToList(); + } + public override object Current() + { + return MedicineIntakeList[Position]; + } + + public override int Key() + { + return Position; + } + + public override bool MoveNext() + { + int updatedPosition = Position + 1; + if (Flag == 0) + { + Flag = 1; + return true; + + } + + else if (updatedPosition >= 0 && updatedPosition < MedicineIntakeList.Count) + { + Position = updatedPosition; + return true; + } + else + { + return false; + } + } + + public override void Reset() + { + Flag = 0; + Position = 0; + } + } +} diff --git a/PainTrackerPT/Trends/Iterator/MoodTrendIterator.cs b/PainTrackerPT/Trends/Iterator/MoodTrendIterator.cs new file mode 100644 index 0000000..ea14ba9 --- /dev/null +++ b/PainTrackerPT/Trends/Iterator/MoodTrendIterator.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using PainTrackerPT.Models.Analytics.GFPatient; + +namespace PainTrackerPT.Trends.Iterator +{ + public class MoodTrendIterator : Iterator + { + List<Mood> MoodTrendList; + int Position = 0; + int Flag = 0; + + public MoodTrendIterator(List<Mood> MoodTrendList) + { + this.MoodTrendList = MoodTrendList.OrderBy(i => i.Date).ToList(); + } + + public override object Current() + { + return MoodTrendList[Position]; + } + + public override int Key() + { + return Position; + } + + public override bool MoveNext() + { + int updatedPosition = Position + 1; + if (Flag == 0) + { + Flag = 1; + return true; + + } + + else if (updatedPosition >= 0 && updatedPosition < MoodTrendList.Count) + { + Position = updatedPosition; + return true; + } + else + { + return false; + } + } + + public override void Reset() + { + Flag = 0; + Position = 0; + } + } +} diff --git a/PainTrackerPT/Trends/Iterator/PainIntensityTrendIterator.cs b/PainTrackerPT/Trends/Iterator/PainIntensityTrendIterator.cs new file mode 100644 index 0000000..f37bd00 --- /dev/null +++ b/PainTrackerPT/Trends/Iterator/PainIntensityTrendIterator.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using PainTrackerPT.Models.Analytics.GFPatient; + +namespace PainTrackerPT.Trends.Iterator +{ + public class PainIntensityTrendIterator : Iterator + { + List<PainIntensity> PainIntensities; + int Position = 0; + int Flag = 0; + + public PainIntensityTrendIterator(List<PainIntensity> PainIntensityList) + { + PainIntensities = PainIntensityList.OrderBy(i => i.Date).ToList(); + + } + + public override object Current() + { + return PainIntensities[Position]; + } + + public override int Key() + { + return Position; + } + + public override bool MoveNext() + { + int updatedPosition = Position + 1; + if (Flag == 0) + { + Flag = 1; + return true; + + } + + else if (updatedPosition >= 0 && updatedPosition < PainIntensities.Count) + { + Position = updatedPosition; + return true; + } + else + { + return false; + } + } + + public override void Reset() + { + Flag = 0; + Position = 0; + } + } +} diff --git a/PainTrackerPT/Trends/Iterator/SleepTrendIterator.cs b/PainTrackerPT/Trends/Iterator/SleepTrendIterator.cs new file mode 100644 index 0000000..1a4f672 --- /dev/null +++ b/PainTrackerPT/Trends/Iterator/SleepTrendIterator.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using PainTrackerPT.Models.Analytics.GFPatient; + +namespace PainTrackerPT.Trends.Iterator +{ + public class SleepTrendIterator : Iterator + { + List<Sleep> SleepList; + int Position = 0; + int Flag = 0; + + public SleepTrendIterator(List<Sleep> SleepList, bool NewestFirst) + { + if(NewestFirst) + this.SleepList = SleepList.OrderByDescending(i => i.Date).ToList(); + else + this.SleepList = SleepList.OrderBy(i => i.Date).ToList(); + } + + + public override object Current() + { + return SleepList[Position]; + } + + public override int Key() + { + return Position; + } + + public override bool MoveNext() + { + int updatedPosition = Position + 1; + if (Flag == 0) + { + Flag = 1; + return true; + + } + + else if (updatedPosition >= 0 && updatedPosition < SleepList.Count) + { + Position = updatedPosition; + return true; + } + else + { + return false; + } + } + + public override void Reset() + { + Flag = 0; + Position = 0; + } + } +} diff --git a/PainTrackerPT/Views/AnalyticsLogs/PatientTrend.cshtml b/PainTrackerPT/Views/AnalyticsLogs/PatientTrend.cshtml new file mode 100644 index 0000000..dbea16f --- /dev/null +++ b/PainTrackerPT/Views/AnalyticsLogs/PatientTrend.cshtml @@ -0,0 +1,489 @@ + +@{ + ViewData["Title"] = "PatientTrend"; + +} + +<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.2.2/Chart.bundle.min.js"></script> +<script src="https://www.chartjs.org/samples/latest/utils.js"></script> +<script type="text/javascript"> +</script> + +<br /><br /> +<h1 class="mx-4">Patient Trends</h1> + +<!--begin::Filter buttons--> +<div class="mx-5" style="float:right;"> + <div class="m-dropdown m-dropdown--inline m-dropdown--arrow m-dropdown--align-right m-dropdown--align-push" m-dropdown-toggle="hover" aria-expanded="true"> + <a href="#" class="m-portlet__nav-link btn btn-lg btn-secondary m-btn m-btn--outline-2x m-btn--air m-btn--icon m-btn--icon-only m-btn--pill m-dropdown__toggle"> + <i class="la la-plus m--hide"></i> + <i class="la la-ellipsis-h"></i> + </a> + <div class="m-dropdown__wrapper" style="z-index: 101;"> + <span class="m-dropdown__arrow m-dropdown__arrow--right m-dropdown__arrow--adjust" style="left: auto; right: 21.5px;"></span> + <div class="m-dropdown__inner"> + <div class="m-dropdown__body"> + <div class="m-dropdown__content"> + <ul class="m-nav"> + <li class="m-nav__section m-nav__section--first"> + <span class="m-nav__section-text">Filter view</span> + </li> + <li class="m-nav__section m-nav__section--first m--hide"> + <span class="m-nav__section-text">Quick Actions</span> + </li> + <li class="m-nav__item" onclick="showYear()"> + <a href="#" class="m-nav__link"> + <i class="m-nav__link-icon flaticon-calendar-1"></i> + <span class="m-nav__link-text">Year</span> + </a> + </li> + <li class="m-nav__item" onclick="showMonth()"> + <a href="#" class="m-nav__link"> + <i class="m-nav__link-icon flaticon-calendar-2"></i> + <span class="m-nav__link-text">Month</span> + </a> + </li> + <li class="m-nav__item" onclick="showWeek()"> + <a href="#" class="m-nav__link"> + <i class="m-nav__link-icon flaticon-calendar-1"></i> + <span class="m-nav__link-text">Week</span> + </a> + </li> + <li class="m-nav__item"> + <a href="#" class="m-nav__link" onclick="showDay()"> + <i class="m-nav__link-icon flaticon-calendar-3"></i> + <span class="m-nav__link-text">Day</span> + </a> + </li> + </ul> + </div> + </div> + </div> + </div> + </div> +</div> +<!--end::Filter buttons--> +<!--begin::Graph buttons--> +<div class="box-body px-4"> + + <div class="chart-container" style="height:500px"> + <canvas id="chart"></canvas> + </div> + + <br /> + <div style="width:100%; text-align:center; margin-top:50px;"> + <div class="btn-group btn-group" role="group"> + <button id="moodBtn" type="button" class="btn btn-secondary" onclick="togglePainIntensity()">Pain Intensity</button> + <button type="button" class="btn btn-secondary" onclick="toggleMood()">Mood</button> + <button type="button" class="btn btn-secondary" onclick="toggleSleep()">Sleep</button> + <button type="button" class="btn btn-secondary" onclick="toggleInterference()">Interference</button> + </div> + </div> +</div> +<!--end::Graph buttons--> +<div class="m-content"> + <!--begin::Rows1--> + <div class="row"> + <!--begin::Left column--> + <div class="col-xl-6"> + <div class="m-portlet"> + <div class="m-portlet__head"> + <div class="m-portlet__head-caption"> + <div class="m-portlet__head-title"> + <h3 class="m-portlet__head-text"> + Overall Pain Areas + </h3> + </div> + </div> + </div> + <div class="m-portlet__body"> + <!--begin::Pain Area Section--> + <div class="m-section__content"> + <span>Below is an analysis of your overall pain areas over your body</span><br /> + <div id="canvas-holder" style="width:100%"> + <canvas id="painAreaPie"></canvas> + </div> + </div> + <!--end::Pain Area Section--> + </div> + </div> + </div> + <!--end::Left column--> + <!--begin::Right column--> + <div class="col-xl-6"> + <div class="m-portlet"> + <div class="m-portlet__head"> + <div class="m-portlet__head-caption"> + <div class="m-portlet__head-title"> + <h3 class="m-portlet__head-text"> + Overall Interference Patterns + </h3> + </div> + </div> + </div> + <div class="m-portlet__body"> + + <!--begin::Section--> + <div class="m-section"> + <div class="m-section__content"> + + @foreach (var d in ViewBag.InterferenceRows) + { + <div class="m-alert m-alert--outline alert alert-success alert-dismissible fade show" role="alert"> + <strong>Description - </strong>@d.Key<br /> + <strong>Duration - </strong>@d.Value hour(s) + </div> + + } + + </div> + </div> + <!--end::Section--> + </div> + </div> + </div> + <!--end::Right column--> + </div> + <!--end::Rows1--> + <!--begin::Rows2--> + <div class="row"> + <!--begin::Left column--> + <div class="col-xl-6"> + <div class="m-portlet"> + <div class="m-portlet__head"> + <div class="m-portlet__head-caption"> + <div class="m-portlet__head-title"> + <h3 class="m-portlet__head-text"> + Overall Mood + </h3> + </div> + </div> + </div> + <div class="m-portlet__body"> + <!--begin::Pain Area Section--> + <div class="m-section__content"> + <span>Below is an analysis of your overall mood</span><br /> + <div id="canvas-holder" style="width:100%"> + <canvas id="moodDoughnut"></canvas> + </div> + </div> + <!--end::Pain Area Section--> + </div> + </div> + </div> + <!--end::Left column--> + <!--begin::Right column--> + <div class="col-xl-6"> + <div class="m-portlet"> + <div class="m-portlet__head"> + <div class="m-portlet__head-caption"> + <div class="m-portlet__head-title"> + <h3 class="m-portlet__head-text"> + Overall Sleep Pattern + </h3> + </div> + </div> + </div> + <div class="m-portlet__body"> + + <!--begin::Section--> + <div class="m-section"> + <div class="m-section__content"> + @foreach (var d in ViewBag.SleepRows) + { + <div class="m-alert m-alert--outline alert alert-success alert-dismissible fade show" role="alert"> + <strong>Comfort Level - </strong>@d.Key<br /> + <strong>Tiredness - </strong>@d.Value + </div> + + } + </div> + </div> + <!--end::Section--> + </div> + </div> + </div> + <!--end::Right column--> + </div> + <!--end::Rows2--> +</div> + +<script> + + /** + * List variables + * Razor function to call from controller to populate empty list + **/ + + var painIntensityData = []; + var moodData = []; + var sleepData = []; + var interferenceData = []; + + @foreach (var d in ViewBag.PainIntensityPlots) + { + @:var dicDate = '@d.Key'; + @:dicDate = dicDate.replace(/\//g, '-'); + @:painIntensityData.push({ x: new Date(toDate(dicDate)), y: '@d.Value' }); + } + + @foreach (var d in ViewBag.MoodPlots) + { + @:var dicDate = '@d.Key'; + @:dicDate = dicDate.replace(/\//g, '-'); + @:moodData.push({ x: new Date(toDate(dicDate)), y: '@d.Value' }); + } + + @foreach (var d in ViewBag.SleepPlots) + { + @:var dicDate = '@d.Key'; + @:dicDate = dicDate.replace(/\//g, '-'); + @:sleepData.push({ x: new Date(toDate(dicDate)), y: '@d.Value' }); + } + + @foreach (var d in ViewBag.InterferencePlots) + { + @:var dicDate = '@d.Key'; + @:dicDate = dicDate.replace(/\//g, '-'); + @:interferenceData.push({ x: new Date(toDate(dicDate)), y: '@d.Value' }); + } + + //Set canvas of graph + var ctx = document.getElementById("chart").getContext("2d"); + + //Date for range of graph + var startDate = new Date(); + var tempDate = new Date(); + var endDate = new Date(tempDate.setTime(tempDate.getTime() + 6 * 86400000)); + + //Define dataset + var data = { + datasets: [ + /** + * Dataset 1 - Pain Intensity + * X value = Date, Y = Intensity + **/ + { + label: "Pain Intensity", + backgroundColor: 'rgba(244, 86, 66, 0.2)', + borderColor:'rgba(244, 86, 66,1)', + borderWidth: 1, + hidden: false, + data: painIntensityData + }, + /** + * Dataset 2 - Mood + * X value = Date, Y = Moodtype + **/ + { + label: "Mood", + backgroundColor: 'rgba(66, 244, 125, 0.2)', + borderColor: 'rgba(66, 244, 125, 1)', + borderWidth: 1, + hidden: true, + data: moodData + }, + /** + * Dataset 3 - Sleep + * X value = Date, Y = Sleep hours + **/ + { + label: "Sleep", + backgroundColor: 'rgba(235, 86, 255, 0.2)', + borderColor: 'rgba(235, 86, 255, 1)', + borderWidth: 1, + hidden: true, + data: sleepData + }, + /** + * Dataset 4 - Interference + * X value = Date, Y = Interference Severity + **/ + { + label: "Interference", + backgroundColor: 'rgba(52, 249, 249, 0.2)', + borderColor: 'rgba(52, 249, 249, 1)', + borderWidth: 1, + hidden: true, + data: interferenceData + } + ] + }; + //Define graph options + var options = { + maintainAspectRatio: false, + scales: { + yAxes: [{ + ticks: { + min: 0, + beginAtZero: true + }, + gridLines: { + display: true, + color: "rgba(255,99,164,0.2)" + } + }], + xAxes: [{ + type: 'time', + distribution: 'linear', + time: + { + parse: 'DD/MM/YYYY HH:mm:ss', + unit: 'day', + min: startDate, + max: endDate + }, + ticks: { + min: 0, + beginAtZero: true + }, + gridLines: { + display: false + } + }] + } + }; + //Init chart on page + var myChart = new Chart(ctx, { + options: options, + data: data, + type: 'line' + }); + + + + /** + * All the pie charts configurations are placed here + * (1 - PAIN AREA) + * */ + + var painAreaDataLabel = []; + var painAreaData = []; + + @foreach (var d in ViewBag.PainAreaPie) + { + @:painAreaDataLabel.push('@d.Key'); + @:painAreaData.push(@d.Value); + } + + // Pie for overall pain areas + var painAreaPieConfig = { + type: 'pie', + data: { + datasets: [{ + data: painAreaData, + backgroundColor: [ + window.chartColors.red, + window.chartColors.orange, + window.chartColors.yellow, + window.chartColors.green, + window.chartColors.blue, + ], + label: 'Overall Pain Area' + }], + labels: painAreaDataLabel + }, + options: { + responsive: true + } + }; + + /** + * All the pie charts configurations are placed here + * (2 - MOOD) + * */ + + var moodDataLabel = []; + var moodData = []; + + @foreach (var d in ViewBag.MoodDoughnut) + { + @:moodDataLabel.push('@d.Key'); + @:moodData.push(@d.Value); + } + + // Pie for overall pain areas + var moodDoughnutConfig = { + type: 'doughnut', + data: { + datasets: [{ + data: moodData, + backgroundColor: [ + window.chartColors.red, + window.chartColors.orange, + window.chartColors.yellow, + window.chartColors.green, + window.chartColors.blue, + ], + label: 'Overall Mood' + }], + labels: moodDataLabel + }, + options: { + responsive: true + } + }; + + window.onload = function () { + var painAreaPie = document.getElementById('painAreaPie').getContext('2d'); + window.myPie = new Chart(painAreaPie, painAreaPieConfig); + + var moodDoughnut = document.getElementById('moodDoughnut').getContext('2d'); + window.myPie = new Chart(moodDoughnut, moodDoughnutConfig); + }; + + function toDate(dateStr) { + var empty = dateStr.split(" "); + var parts = empty[0].split("-"); + return (parts[1] + "-" + parts[0] + "-" + parts[2] + " " + empty[1] + " AM"); + } + + function showDay() { + myChart.options.scales.xAxes[0].time.unit = 'day'; + myChart.options.scales.xAxes[0].time.min = new Date("04-01-2019"); + myChart.options.scales.xAxes[0].time.max = new Date("04-31-2019"); + myChart.update(); + } + + function showMonth() { + myChart.options.scales.xAxes[0].time.unit = 'month'; + myChart.options.scales.xAxes[0].time.min = new Date("01-01-2019"); + myChart.options.scales.xAxes[0].time.max = new Date("12-31-2019"); + myChart.update(); + } + + function showWeek() { + myChart.options.scales.xAxes[0].time.unit = 'week'; + myChart.options.scales.xAxes[0].time.min = startDate; + myChart.options.scales.xAxes[0].time.max = endDate; + myChart.update(); + } + + function showYear() { + myChart.options.scales.xAxes[0].time.unit = 'year'; + myChart.options.scales.xAxes[0].time.min = new Date("01-01-2019"); + myChart.update(); + } + + function togglePainIntensity() { + myChart.data.datasets[0].hidden = !myChart.data.datasets[0].hidden; + myChart.update(); + } + + function toggleMood() { + myChart.data.datasets[1].hidden = !myChart.data.datasets[1].hidden; + myChart.update(); + } + + function toggleSleep() { + myChart.data.datasets[2].hidden = !myChart.data.datasets[2].hidden; + myChart.update(); + } + + function toggleInterference() { + myChart.data.datasets[3].hidden = !myChart.data.datasets[3].hidden; + myChart.update(); + } + +</script> diff --git a/PainTrackerPT/Views/AnalyticsLogs/Trends.cshtml b/PainTrackerPT/Views/AnalyticsLogs/Trends.cshtml new file mode 100644 index 0000000..3c8dbfc --- /dev/null +++ b/PainTrackerPT/Views/AnalyticsLogs/Trends.cshtml @@ -0,0 +1,28 @@ +@{ + ViewData["Title"] = "Trends"; +} + +<h1>Trends</h1> + +<p> + <a asp-action="Create">Create New</a> +</p> +<table class="table"> + <thead> + <tr> + <th> + </th> + <th></th> + </tr> + </thead> + <tbody> + @foreach (var kv in ViewBag.PainIntensityPlots) + { + <tr> + <td> + @kv. + </td> + </tr> + } + </tbody> + </table>