protected override void Initialize(HttpControllerContext controllerContext) { base.Initialize(controllerContext); feedtimeContext context = new feedtimeContext(); DomainManager = new EntityDomainManager <ChangeActivity>(context, Request, Services, enableSoftDelete: true); }
// POST tables/Baby public async Task <IHttpActionResult> PostBaby(Baby item) { // Ensure the baby is only inserted into the users family using (var context = new feedtimeContext()) { string userId = User.GetId(); var userProfile = context.Set <UserProfile>() .Single(up => up.UserId == userId); item.FamilyId = userProfile.FamilyId; } Baby current = await InsertAsync(item); return(CreatedAtRoute("Tables", new { id = current.Id }, current)); }
// DELETE tables/Baby/48D68C86-6EA6-4C25-AA33-223FC9A27959 public Task DeleteBaby(string id) { // Ensure that the baby being deleted belongs to the users family using (var context = new feedtimeContext()) { string userId = User.GetId(); var baby = context.Set <Baby>() .SingleOrDefault(b => b.Id == id && b.Family.UserProfiles.Any(up => up.UserId == userId)); if (baby == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } } return(DeleteAsync(id)); }
// DELETE tables/UserProfile/48D68C86-6EA6-4C25-AA33-223FC9A27959 public Task DeleteUserProfile(string id) { // Ensure that the user profile being deleted belongs to the current user using (var context = new feedtimeContext()) { string userId = User.GetId(); var userProfile = context.Set <UserProfile>() .SingleOrDefault(up => up.UserId == userId); if (userProfile == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } } return(DeleteAsync(id)); }
// GET api/DataTrends public DataTrends Get(string babyId) { using (var context = new feedtimeContext()) { // Use rolling windows for last 'day' & 'week' string userId = User.GetId(); var today = DateTimeOffset.UtcNow.AddHours(-24); var startOfWeek = DateTimeOffset.UtcNow.AddDays(-7); var dataTrends = new DataTrends { BabyId = babyId }; var currentBaby = context.Set <Baby>() .Where(baby => baby.Id == babyId && baby.Family.UserProfiles.Any(up => up.UserId == userId)) .SingleOrDefault(); if (currentBaby == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } dataTrends.StartOfDay = today; dataTrends.StartOfWeek = startOfWeek; dataTrends.BabysBirthDate = currentBaby.DateOfBirth; // Retrieve the averages for feeds & sleeps var feedsOverLastWeek = context.Set <FeedActivity>() .Where(activity => activity.BabyId == babyId && activity.StartTime >= startOfWeek && activity.EndTime.HasValue && !activity.Deleted) .AsEnumerable(); var feedsOverLastWeekWithVolume = feedsOverLastWeek.Where(activity => activity.MillilitresConsumed.HasValue); var feedsOverLastWeekByDay = feedsOverLastWeek.GroupBy(f => f.StartTime.Date); dataTrends.AverageFeedsPerDay = feedsOverLastWeekByDay.Aggregate(0, (a, b) => a + b.Count(), a => feedsOverLastWeekByDay.Any() ? Convert.ToInt32(Math.Round((double)a / feedsOverLastWeekByDay.Count())) : 0); dataTrends.AverageFeedDuration = feedsOverLastWeek.Aggregate(0d, (a, b) => a + (b.EndTime.Value - b.StartTime).Duration().Ticks, a => feedsOverLastWeek.Any() ? new TimeSpan(Convert.ToInt64(Math.Round((double)a / feedsOverLastWeek.Count()))) : TimeSpan.Zero); dataTrends.AverageFeedVolume = feedsOverLastWeekWithVolume.Aggregate(0, (a, b) => a + b.MillilitresConsumed.Value, a => feedsOverLastWeekWithVolume.Any() ? Convert.ToInt32(Math.Round((double)a / feedsOverLastWeekWithVolume.Count())) : 0); var sleepsOverLastWeek = context.Set <SleepActivity>() .Where(activity => activity.BabyId == babyId && activity.StartTime >= startOfWeek && activity.EndTime.HasValue && !activity.Deleted) .AsEnumerable(); var sleepsOverLastWeekByDay = sleepsOverLastWeek.GroupBy(f => f.StartTime.Date); dataTrends.AverageSleepsPerDay = sleepsOverLastWeekByDay.Aggregate(0, (a, b) => a + b.Count(), a => sleepsOverLastWeekByDay.Any() ? Convert.ToInt32(Math.Round((double)a / sleepsOverLastWeekByDay.Count())) : 0); dataTrends.AverageSleepDuration = sleepsOverLastWeek.Aggregate(0d, (a, b) => a + (b.EndTime.Value - b.StartTime).Duration().Ticks, a => sleepsOverLastWeek.Any() ? new TimeSpan(Convert.ToInt64(Math.Round((double)a / sleepsOverLastWeek.Count()))) : TimeSpan.Zero); var changesOverLastWeek = context.Set <ChangeActivity>() .Where(activity => activity.BabyId == babyId && activity.StartTime >= startOfWeek && activity.EndTime.HasValue && !activity.Deleted) .AsEnumerable(); var changesOverLastWeekByDay = changesOverLastWeek.GroupBy(f => f.StartTime.Date); dataTrends.AverageChangesPerDay = changesOverLastWeekByDay.Aggregate(0, (a, b) => a + b.Count(), a => changesOverLastWeekByDay.Any() ? Convert.ToInt32(Math.Round((double)a / changesOverLastWeekByDay.Count())) : 0); // Retrieve the data for activities over the last 24 hours dataTrends.FeedsOverLastDay = context.Set <FeedActivity>() .Where(activity => activity.BabyId == babyId && activity.StartTime >= today && !activity.Deleted) .Select(activity => new ActivityTrend { StartTime = activity.StartTime, EndTime = activity.EndTime }) .ToList(); dataTrends.SleepsOverLastDay = context.Set <SleepActivity>() .Where(activity => activity.BabyId == babyId && activity.StartTime >= today && !activity.Deleted) .Select(activity => new ActivityTrend { StartTime = activity.StartTime, EndTime = activity.EndTime }) .ToList(); dataTrends.ChangesOverLastDay = context.Set <ChangeActivity>() .Where(activity => activity.BabyId == babyId && activity.StartTime >= today && !activity.Deleted) .Select(activity => new ActivityTrend { StartTime = activity.StartTime, EndTime = activity.EndTime }) .ToList(); // Retrieve the data for mood over the last 7 days var sleepActivitiesWithFeeling = context.Set <SleepActivity>() .Where(activity => activity.BabyId == babyId && activity.StartTime >= startOfWeek && (activity.HowBabyFelt != null || activity.HowParentFelt != null) && !activity.Deleted) .Select(activity => new { StartTime = activity.StartTime, HowBabyFelt = activity.HowBabyFelt, HowParentFelt = activity.HowParentFelt }) .Union(context.Set <FeedActivity>() .Where(activity => activity.BabyId == babyId && activity.StartTime >= startOfWeek && (activity.HowBabyFelt != null || activity.HowParentFelt != null) && !activity.Deleted) .Select(activity => new { StartTime = activity.StartTime, HowBabyFelt = activity.HowBabyFelt, HowParentFelt = activity.HowParentFelt })) .Union(context.Set <ChangeActivity>() .Where(activity => activity.BabyId == babyId && activity.StartTime >= startOfWeek && (activity.HowBabyFelt != null || activity.HowParentFelt != null) && !activity.Deleted) .Select(activity => new { StartTime = activity.StartTime, HowBabyFelt = activity.HowBabyFelt, HowParentFelt = activity.HowParentFelt })) .AsEnumerable(); dataTrends.BabysMoodOverLastWeek = sleepActivitiesWithFeeling.Where(activity => activity.HowBabyFelt.HasValue) .GroupBy(activity => activity.StartTime.Date) .AsEnumerable() .Select(activityGroup => new MoodTrend { Date = activityGroup.Key, Feeling = AverageFeeling(activityGroup.Select(ag => ag.HowBabyFelt)) }) .ToList(); dataTrends.ParentsMoodOverLastWeek = sleepActivitiesWithFeeling.Where(activity => activity.HowParentFelt.HasValue) .GroupBy(activity => activity.StartTime.Date) .AsEnumerable() .Select(activityGroup => new MoodTrend { Date = activityGroup.Key, Feeling = AverageFeeling(activityGroup.Select(ag => ag.HowParentFelt)) }) .ToList(); // Retrieve the data for length and weight since birth dataTrends.MeasurementsSinceBirth = context.Set <Measurement>() .Where(m => m.Weight != null || m.Length != null && !m.Deleted) .AsEnumerable() .GroupBy(measurement => measurement.CreatedAt.Value.Date) .Select(measurementGroup => measurementGroup.OrderBy(measurement => measurement.CreatedAt.Value) .Last()) .AsEnumerable() .Select(measurement => new MeasurementTrend { Date = measurement.CreatedAt.Value, Length = measurement.Length, Weight = measurement.Weight }) .ToList(); dataTrends.TrendsGeneratedAt = DateTimeOffset.UtcNow; return(dataTrends); } }
// GET api/Schedule/abc123 public ActivitySchedule Get(string babyId) { using (var context = new feedtimeContext()) { string userId = User.GetId(); var currentBaby = context.Set <Baby>() .Where(baby => baby.Id == babyId && baby.Family.UserProfiles.Any(up => up.UserId == userId)) .SingleOrDefault(); if (currentBaby == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } // Use rolling windows for last 'week' var now = DateTimeOffset.UtcNow; var today = DateTimeOffset.UtcNow.Date; var startOfWeek = DateTimeOffset.UtcNow.AddDays(-7); // Calculate feed schedule for last 7 days long?averageTimeBetweenFeeds = null; //long? averageFeedTime = null; DateTimeOffset nextFeedDueAt = currentBaby.DateOfBirth.Add(TimeSpan.FromHours(2)); var feedActivities = context.FeedActivities .Where(ca => ca.BabyId == babyId && ca.StartTime >= startOfWeek && !ca.Deleted) .OrderByDescending(ca => ca.StartTime); var latestFeedActivity = feedActivities.FirstOrDefault(); if (latestFeedActivity != null) { var feedActivityStartTimes = feedActivities.Select(ca => ca.StartTime) .ToList(); // Calculate average time between feeds long totalTimeBetweenFeeds = 0; feedActivityStartTimes.Aggregate((a, b) => { totalTimeBetweenFeeds += (today.Add(a - b) - today).Ticks; return(b); }); averageTimeBetweenFeeds = Convert.ToInt64(Math.Round((double)totalTimeBetweenFeeds / feedActivityStartTimes.Count())); //// Calculate average feed time //var completedFeedActivities = feedActivities.Where(a => a.EndTime.HasValue); //var totalFeedTime = completedFeedActivities.Aggregate(0L, (a, b) => a + (b.EndTime.Value - b.StartTime).Ticks); //averageFeedTime = totalFeedTime / completedFeedActivities.Count(); // Calculate next feed time var minimumNextFeedTime = latestFeedActivity.StartTime.Add(new TimeSpan(averageTimeBetweenFeeds.Value)); var feedActivitiesByDate = feedActivities.ToList() .GroupBy(a => a.StartTime.Date) // For each date select the first feed after 'now' .Select(ag => { var ascendingStartTimes = ag.OrderBy(a => a.StartTime.TimeOfDay); var nextFeed = ascendingStartTimes .FirstOrDefault(a => a.StartTime.TimeOfDay > minimumNextFeedTime.TimeOfDay); if (nextFeed == null) { nextFeed = ascendingStartTimes.LastOrDefault(); } return(nextFeed == null ? null : Tuple.Create(nextFeed, nextFeed.StartTime.TimeOfDay - now.TimeOfDay)); }) .Where(a => a != null); if (feedActivitiesByDate.Any()) { var averageTimeToNextFeed = Convert.ToInt64(Math.Round((double)feedActivitiesByDate.Aggregate(0L, (a, b) => a + b.Item2.Ticks) / feedActivitiesByDate.Count())); nextFeedDueAt = now.Add(new TimeSpan(averageTimeToNextFeed)); } } // Calculate sleep schedule for last 7 days long? averageTimeBetweenSleeps = null; DateTimeOffset nextSleepDueAt = currentBaby.DateOfBirth.Add(TimeSpan.FromHours(2)); var sleepActivities = context.SleepActivities .Where(ca => ca.BabyId == babyId && ca.StartTime >= startOfWeek && !ca.Deleted) .OrderByDescending(ca => ca.StartTime); var latestSleepActivity = sleepActivities.FirstOrDefault(); if (latestSleepActivity != null) { var sleepActivityStartTimes = sleepActivities.Select(ca => ca.StartTime) .ToList(); long totalTimeBetweenSleeps = 0; sleepActivityStartTimes.Aggregate((a, b) => { totalTimeBetweenSleeps += (today.Add(a - b) - today).Ticks; return(b); }); averageTimeBetweenSleeps = Convert.ToInt64(Math.Round((double)totalTimeBetweenSleeps / sleepActivityStartTimes.Count())); // Calculate next sleep time var minimumNextSleepTime = latestSleepActivity.StartTime.Add(new TimeSpan(averageTimeBetweenSleeps.Value)); var sleepActivitiesByDate = sleepActivities.ToList() .GroupBy(a => a.StartTime.Date) // For each date select the first sleep after 'now' .Select(ag => { var ascendingStartTimes = ag.OrderBy(a => a.StartTime.TimeOfDay); var nextSleep = ascendingStartTimes .FirstOrDefault(a => a.StartTime.TimeOfDay > minimumNextSleepTime.TimeOfDay); if (nextSleep == null) { nextSleep = ascendingStartTimes.LastOrDefault(); } return(nextSleep == null ? null : Tuple.Create(nextSleep, nextSleep.StartTime.TimeOfDay - now.TimeOfDay)); }) .Where(a => a != null); if (sleepActivitiesByDate.Any()) { var averageTimeToNextSleep = Convert.ToInt64(Math.Round((double)sleepActivitiesByDate.Aggregate(0L, (a, b) => a + b.Item2.Ticks) / sleepActivitiesByDate.Count())); nextSleepDueAt = now.Add(new TimeSpan(averageTimeToNextSleep)); } } // Calculate change schedule for last 7 days long? averageTimeBetweenChanges = null; DateTimeOffset nextChangeDueAt = currentBaby.DateOfBirth.Add(TimeSpan.FromHours(3)); var changeActivities = context.ChangeActivities .Where(ca => ca.BabyId == babyId && ca.StartTime >= startOfWeek && !ca.Deleted) .OrderByDescending(ca => ca.StartTime); var latestChangeActivity = changeActivities.FirstOrDefault(); if (latestChangeActivity != null) { var changeActivityStartTimes = changeActivities.Select(ca => ca.StartTime) .ToList(); long totalTimeBetweenChanges = 0; changeActivityStartTimes.Aggregate((a, b) => { totalTimeBetweenChanges += (today.Add(a - b) - today).Ticks; return(b); }); averageTimeBetweenChanges = Convert.ToInt64(Math.Round((double)totalTimeBetweenChanges / changeActivityStartTimes.Count())); // Calculate next change time var minimumNextChangeTime = latestChangeActivity.StartTime.Add(new TimeSpan(averageTimeBetweenChanges.Value)); var changeActivitiesByDate = changeActivities.ToList() .GroupBy(a => a.StartTime.Date) // For each date select the first feed after 'now' .Select(ag => { var ascendingStartTimes = ag.OrderBy(a => a.StartTime.TimeOfDay); var nextChange = ascendingStartTimes .FirstOrDefault(a => a.StartTime.TimeOfDay > minimumNextChangeTime.TimeOfDay); if (nextChange == null) { nextChange = ascendingStartTimes.LastOrDefault(); } return(nextChange == null ? null : Tuple.Create(nextChange, nextChange.StartTime.TimeOfDay - now.TimeOfDay)); }) .Where(a => a != null); if (changeActivitiesByDate.Any()) { var averageTimeToNextChange = Convert.ToInt64(Math.Round((double)changeActivitiesByDate.Aggregate(0L, (a, b) => a + b.Item2.Ticks) / changeActivitiesByDate.Count())); nextChangeDueAt = now.Add(new TimeSpan(averageTimeToNextChange)); } } // Generate the complete schedule return(new ActivitySchedule { BabyId = babyId, ScheduleGeneratedAt = DateTimeOffset.UtcNow, CurrentlyFeeding = latestFeedActivity != null ? !latestFeedActivity.EndTime.HasValue : false, LastFeed = latestFeedActivity, AverageTimeBetweenFeeds = averageTimeBetweenFeeds.HasValue ? new TimeSpan(averageTimeBetweenFeeds.Value) : (TimeSpan?)null, NextFeedDueAt = nextFeedDueAt, CurrentlySleeping = latestSleepActivity != null ? !latestSleepActivity.EndTime.HasValue : false, LastSleep = latestSleepActivity, AverageTimeBetweenSleeps = averageTimeBetweenSleeps.HasValue ? new TimeSpan(averageTimeBetweenSleeps.Value) : (TimeSpan?)null, NextSleepDueAt = nextSleepDueAt, LastChange = latestChangeActivity, AverageTimeBetweenChanges = averageTimeBetweenChanges.HasValue ? new TimeSpan(averageTimeBetweenChanges.Value) : (TimeSpan?)null, NextChangeDueAt = nextChangeDueAt }); } }