コード例 #1
0
        /// <summary>
        /// Finds the next date that the class occurs on. If the class already started today, returns the
        /// NEXT instance of that class.
        /// </summary>
        /// <param name="account"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        public static DateTime?GetNextClassDate(AccountDataItem account, ViewItemClass c)
        {
            if (c.Schedules == null || c.Schedules.Count == 0)
            {
                return(null);
            }

            var      now  = DateTime.Now;
            DateTime date = now.Date;

            // Look up to 2 weeks (and one day) in advance
            // We include the extra one day since if the class is currently going on, we want the NEXT instance of that class,
            // which could possibly be 2 weeks out
            for (int i = 0; i < 15; i++, date = date.AddDays(1))
            {
                var currWeek = account.GetWeekOnDifferentDate(date);

                // If there's a schedule on that day
                // (If it's not today, then we're good... otherwise if it's today,
                // make sure that the class hasn't started yet - if it started, we want the NEXT instance of the class)
                if (c.Schedules.Any(s =>
                                    s.DayOfWeek == date.DayOfWeek &&
                                    (s.ScheduleWeek == Schedule.Week.BothWeeks || s.ScheduleWeek == currWeek) &&
                                    (date.Date != now.Date || s.StartTime.TimeOfDay > now.TimeOfDay)))
                {
                    return(date);
                }
            }

            return(null);
        }
コード例 #2
0
        private static DateTime GetDayBeforeReminderTime(DateTime date, AccountDataItem account, IEnumerable <ViewItemSchedule> allSchedules)
        {
            date = DateTime.SpecifyKind(date.Date, DateTimeKind.Local);

            //if they're using custom end times
            if (account.CustomEndTimes.ContainsKey(date.DayOfWeek))
            {
                return(date.Add(account.CustomEndTimes[date.DayOfWeek]).AddMinutes(10));
            }

            PowerPlannerSending.Schedule.Week week = account.GetWeekOnDifferentDate(date);

            //otherwise get all the schedules
            IEnumerable <ViewItemSchedule> schedules;

            schedules = allSchedules.Where(i => i.DayOfWeek == date.DayOfWeek && (i.ScheduleWeek == week || i.ScheduleWeek == PowerPlannerSending.Schedule.Week.BothWeeks));

            // If there aren't any schedules on that day
            if (!schedules.Any())
            {
                return(date.AddHours(15)); // 3:00 PM is default time for day before reminders
            }

            return(date.Add(schedules.Max(i => i.EndTime.TimeOfDay)).AddMinutes(10)); //day before reminders show up 10 mins after last class
        }
コード例 #3
0
        private DayScheduleItemsArranger(AccountDataItem account, SemesterItemsViewGroup semesterItems, ScheduleViewItemsGroup scheduleGroup, DateTime date, double heightOfHour, double spacingWhenNoAdditionalItems, double spacingWithAdditionalItems, double widthOfCollapsed, bool includeTasksAndEventsAndHolidays)
        {
            if (semesterItems.Semester == null)
            {
                throw new NullReferenceException("Semester was null");
            }

            _semesterItems = semesterItems;
            semesterItems.OnItemsChanged    += new WeakEventHandler <EventArgs>(SemesterGroup_OnItemsChanged).Handler;
            scheduleGroup.OnChangesOccurred += new WeakEventHandler <DataChangedEvent>(ScheduleViewItemsGroup_OnChangesOccurred).Handler;

            Date = date;
            _spacingWhenNoAdditionalItems = spacingWhenNoAdditionalItems;
            _spacingWithAdditionalItems   = spacingWithAdditionalItems;
            _widthOfCollapsed             = widthOfCollapsed;
            Account         = account;
            _schoolTimeZone = account.SchoolTimeZone;
            HeightOfHour    = heightOfHour;
            MinDuration     = TimeSpan.FromHours(widthOfCollapsed / HeightOfHour);

            IsDifferentSemester = !semesterItems.Semester.IsDateDuringThisSemester(date);

            SchedulesOnDay schedules = null;

            if (!IsDifferentSemester)
            {
                schedules = SchedulesOnDay.Get(account, semesterItems.Classes, date, account.GetWeekOnDifferentDate(date), trackChanges: true);
                schedules.CollectionChanged += new WeakEventHandler <NotifyCollectionChangedEventArgs>(Schedules_CollectionChanged).Handler;
            }

            _schedules = schedules;

            if (includeTasksAndEventsAndHolidays)
            {
                // For schedules, if tasks have a specific due time, we don't adjust the dates regardless of time zones causing them to switch to a different day, since they're displayed on the visual schedule. Therefore we set useEffectiveDatesEvenWhenItemsHaveTimes to false.
                _events = TasksOrEventsOnDay.Get(account, semesterItems.Items, date, today: null, activeOnly: false, useEffectiveDateEvenWhenItemsHaveTimes: false);
                _events.CollectionChanged += new WeakEventHandler <NotifyCollectionChangedEventArgs>(Events_CollectionChanged).Handler;
            }
            else
            {
                _events = new MyObservableList <BaseViewItemMegaItem>();
            }

            if (includeTasksAndEventsAndHolidays)
            {
                _holidays = HolidaysOnDay.Create(semesterItems.Items, date);
                _holidays.CollectionChanged += new WeakEventHandler <NotifyCollectionChangedEventArgs>(_holidays_CollectionChanged).Handler;
            }
            else
            {
                _holidays = new MyObservableList <ViewItemHoliday>();
            }

            Initialize(schedules, _events, _holidays);
        }
コード例 #4
0
        private DayScheduleItemsArranger(AccountDataItem account, SemesterItemsViewGroup semesterItems, ScheduleViewItemsGroup scheduleGroup, DateTime date, double heightOfHour, double spacingWhenNoAdditionalItems, double spacingWithAdditionalItems, double widthOfCollapsed, bool includeHomeworkAndHolidays)
        {
            if (semesterItems.Semester == null)
            {
                throw new NullReferenceException("Semester was null");
            }

            _semesterItems = semesterItems;
            semesterItems.OnItemsChanged    += new WeakEventHandler <EventArgs>(SemesterGroup_OnItemsChanged).Handler;
            scheduleGroup.OnChangesOccurred += new WeakEventHandler <DataChangedEvent>(ScheduleViewItemsGroup_OnChangesOccurred).Handler;

            Date = date;
            _spacingWhenNoAdditionalItems = spacingWhenNoAdditionalItems;
            _spacingWithAdditionalItems   = spacingWithAdditionalItems;
            _widthOfCollapsed             = widthOfCollapsed;
            Account         = account;
            _schoolTimeZone = account.SchoolTimeZone;
            HeightOfHour    = heightOfHour;
            MinDuration     = TimeSpan.FromHours(widthOfCollapsed / HeightOfHour);

            IsDifferentSemester = !semesterItems.Semester.IsDateDuringThisSemester(date);

            SchedulesOnDay schedules = null;

            if (!IsDifferentSemester)
            {
                schedules = SchedulesOnDay.Get(semesterItems.Classes, date, account.GetWeekOnDifferentDate(date), trackChanges: true);
                schedules.CollectionChanged += new WeakEventHandler <NotifyCollectionChangedEventArgs>(Schedules_CollectionChanged).Handler;
            }

            _schedules = schedules;

            if (includeHomeworkAndHolidays)
            {
                _events = HomeworksOnDay.Get(semesterItems.Items, date);
                _events.CollectionChanged += new WeakEventHandler <NotifyCollectionChangedEventArgs>(Events_CollectionChanged).Handler;
            }
            else
            {
                _events = new MyObservableList <BaseViewItemHomeworkExamGrade>();
            }

            if (includeHomeworkAndHolidays)
            {
                _holidays = HolidaysOnDay.Create(semesterItems.Items, date);
                _holidays.CollectionChanged += new WeakEventHandler <NotifyCollectionChangedEventArgs>(_holidays_CollectionChanged).Handler;
            }
            else
            {
                _holidays = new MyObservableList <ViewItemHoliday>();
            }

            Initialize(schedules, _events, _holidays);
        }
コード例 #5
0
        public static ViewItemClass GetFirstClassOnDay(DateTime date, AccountDataItem account, IEnumerable <ViewItemClass> classes)
        {
            if (classes == null)
            {
                return(null);
            }

            var currWeek = account.GetWeekOnDifferentDate(date);

            var schedules = SchedulesOnDay.Get(classes, date, currWeek, trackChanges: false);

            return(schedules.FirstOrDefault()?.Class);
        }
コード例 #6
0
        /// <summary>
        /// Returns true if the class takes place on the specified date.
        /// </summary>
        /// <param name="date"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool DoesClassOccurOnDate(AccountDataItem account, DateTime date, ViewItemClass c)
        {
            if (c.Schedules == null || c.Schedules.Count == 0 || account == null)
            {
                return(false);
            }

            var currWeek = account.GetWeekOnDifferentDate(date);

            return(c.Schedules.Any(s =>
                                   s.DayOfWeek == date.DayOfWeek &&
                                   (s.ScheduleWeek == Schedule.Week.BothWeeks || s.ScheduleWeek == currWeek)));
        }
コード例 #7
0
        public DateTime GetLocalStartDateAndTime(AccountDataItem account, DataItemSemester semester, DataItemClass c)
        {
            DateTime startDate;

            if (!DateValues.IsUnassigned(semester.Start))
            {
                startDate = DateHelpers.ToViewItemTime(account, semester.Start);
            }
            else
            {
                startDate = DateTime.Today.AddYears(-1);
            }

            // If the class has a start date, we use that rather than the semester start date
            if (!DateValues.IsUnassigned(c.StartDate))
            {
                startDate = DateHelpers.ToViewItemTime(account, c.StartDate);
            }

            var currentWeek = account.GetWeekOnDifferentDate(startDate);

            // If the schedule doesn't occur each week
            if (this.ScheduleWeek != Schedule.Week.BothWeeks)
            {
                // If it's on the wrong week, we'll move it forward 7 days
                if (currentWeek != this.ScheduleWeek)
                {
                    startDate = startDate.AddDays(7);
                }
            }

            // Get the date the schedule actually starts on
            startDate = DateTools.Next(this.DayOfWeek, startDate);

            return(startDate.Add(this.StartTime.TimeOfDay));
        }
コード例 #8
0
        public static ViewItemClass GetClosestClassBasedOnSchedule(DateTime now, AccountDataItem account, IEnumerable <ViewItemClass> classes)
        {
            if (classes == null)
            {
                return(null);
            }

            var currWeek = account.GetWeekOnDifferentDate(now);

            var schedules = SchedulesOnDay.Get(classes, now, currWeek, trackChanges: false);

            ViewItemSchedule closestBefore = null;
            ViewItemSchedule closestAfter  = null;

            //look through all schedules
            foreach (var s in schedules)
            {
                //if the class is currently going on
                if (now.TimeOfDay >= s.StartTime.TimeOfDay && now.TimeOfDay <= s.EndTime.TimeOfDay)
                {
                    return(s.Class);
                }

                //else if the class is in the future, we instantly select it for the after class since it's sorted from earliest to latest
                else if (s.StartTime.TimeOfDay >= now.TimeOfDay)
                {
                    // Make sure it's only 10 mins after
                    if ((s.StartTime.TimeOfDay - now.TimeOfDay) < TimeSpan.FromMinutes(10))
                    {
                        closestAfter = s;
                    }

                    // Regardless we break
                    break;
                }

                else
                {
                    // Make sure it's only 10 mins before
                    if ((now.TimeOfDay - s.EndTime.TimeOfDay) < TimeSpan.FromMinutes(10))
                    {
                        closestBefore = s;
                    }
                }
            }

            if (closestAfter == null && closestBefore == null)
            {
                return(null);
            }

            else if (closestAfter == null)
            {
                return(closestBefore.Class);
            }

            else if (closestBefore == null)
            {
                return(closestAfter.Class);
            }

            else if ((now.TimeOfDay - closestBefore.EndTime.TimeOfDay) < (closestAfter.StartTime.TimeOfDay - now.TimeOfDay))
            {
                return(closestBefore.Class);
            }

            else
            {
                return(closestAfter.Class);
            }
        }
コード例 #9
0
        /// <summary>
        /// Returns a list of items that should have active notifications (ignoring whether user already dismissed them)
        /// </summary>
        /// <param name="account"></param>
        /// <param name="agendaItems"></param>
        /// <param name="now"></param>
        /// <param name="nextReminderTime"></param>
        /// <returns></returns>
        private static List <Tuple <BaseViewItemHomeworkExam, DateTime> > GetItemsThatCouldHaveDayOfNotifications(AccountDataItem account, AgendaViewItemsGroup agendaItems, DateTime now, out DateTime nextReminderTime)
        {
            List <Tuple <BaseViewItemHomeworkExam, DateTime> > shouldBeActive = new List <Tuple <BaseViewItemHomeworkExam, DateTime> >();

            nextReminderTime = DateTime.MinValue;
            PowerPlannerSending.Schedule.Week currentWeek = account.GetWeekOnDifferentDate(now);

            // Add past-due incomplete tasks (we don't add exams since they're "complete" when they're past-due)
            foreach (var task in agendaItems.Items.OfType <ViewItemHomework>().Where(i => i.Date.Date < now.Date).OrderBy(i => i))
            {
                shouldBeActive.Add(new Tuple <BaseViewItemHomeworkExam, DateTime>(task, task.Date.Date));
            }

            // Look at items due today
            // NOTE: Assuming that end time is always on the same day. If we allow events that span multiple days,
            // we might need to update this so it correctly expires the event on the future date.
            // To make sure we include items due 00:30 on the next day, we have to factor in tomorrow
            DateTime tomorrow        = now.Date.AddDays(1);
            var      weekForTomorrow = account.GetWeekOnDifferentDate(tomorrow);

            foreach (var item in agendaItems.Items.Where(i => i.Date.Date == now.Date || i.Date.Date == tomorrow).OrderBy(i => i))
            {
                // Get the reminder time
                DateTime reminderTime = GetDayOfReminderTime(item.Date.Date == tomorrow ? weekForTomorrow : currentWeek, item);

                // If it's past the reminder time
                if (now >= reminderTime)
                {
                    // If it has an end time
                    DateTime endTime;
                    if (item.TryGetEndDateWithTime(out endTime))
                    {
                        // We have to consider the end time for updating reminders, since events
                        // expire once they're over (so need to update again right when an event completes)
                        if (endTime > now && (nextReminderTime == DateTime.MinValue || endTime < nextReminderTime))
                        {
                            shouldBeActive.Add(new Tuple <BaseViewItemHomeworkExam, DateTime>(item, reminderTime));
                            nextReminderTime = endTime;
                        }
                    }

                    else
                    {
                        // Otherwise add it
                        shouldBeActive.Add(new Tuple <BaseViewItemHomeworkExam, DateTime>(item, reminderTime));
                    }
                }
                else if (nextReminderTime == DateTime.MinValue || reminderTime < nextReminderTime)
                {
                    nextReminderTime = reminderTime;
                }
            }

            // If no time found, we pick an item that's due in the future
            if (nextReminderTime == DateTime.MinValue)
            {
                DateTime?nextDateWithItems = agendaItems.Items.Where(i => i.Date.Date > now.Date).OrderBy(i => i.Date.Date).FirstOrDefault()?.Date.Date;
                if (nextDateWithItems != null)
                {
                    // Get the week for that date
                    var week = account.GetWeekOnDifferentDate(nextDateWithItems.Value);

                    // Look through all items on that date
                    foreach (var item in agendaItems.Items.Where(i => i.Date.Date == nextDateWithItems.Value))
                    {
                        // Pick the smallest reminder time
                        DateTime reminderTime = GetDayOfReminderTime(currentWeek, item);
                        if (nextReminderTime == DateTime.MinValue || reminderTime < nextReminderTime)
                        {
                            nextReminderTime = reminderTime;
                        }
                    }
                }
            }

            return(shouldBeActive);
        }
コード例 #10
0
        protected override void ResetAllReminders(AccountDataItem account, ScheduleViewItemsGroup scheduleViewItemsGroup)
        {
            var notifier = ToastNotificationManager.CreateToastNotifier();
            var group    = ClassRemindersGroupPrefix + "." + UWPRemindersExtension.GetId(account);

            // Clear current scheduled notifications
            try
            {
                var scheduled = notifier.GetScheduledToastNotifications();
                foreach (var s in scheduled)
                {
                    try
                    {
                        if (s.Group == group)
                        {
                            notifier.RemoveFromSchedule(s);
                        }
                    }
                    catch { }
                }
            }
            catch { }

            if (scheduleViewItemsGroup == null)
            {
                return;
            }

            // This will be initialized
            var beforeTime = account.ClassRemindersTimeSpan.GetValueOrDefault();

            // Added in 17134
            bool isExpirationTimeSupported = ApiInformation.IsPropertyPresent(typeof(ScheduledToastNotification).FullName, "ExpirationTime");

            var today = DateTime.Today;
            var end   = today.AddDays(8); // Schedule out for 8 days

            Dictionary <ViewItemSchedule, XmlDocument> generatedPayloads = new Dictionary <ViewItemSchedule, XmlDocument>();

            for (; today.Date < end.Date; today = today.AddDays(1).Date)
            {
                // No need to lock changes, if changes occur an exception might occur, but that's fine, reminders would be reset once again anyways
                var schedulesOnDay = SchedulesOnDay.Get(account, scheduleViewItemsGroup.Classes, today, account.GetWeekOnDifferentDate(today), trackChanges: false);

                foreach (var s in schedulesOnDay)
                {
                    var reminderTime = today.Add(s.StartTime.TimeOfDay).Subtract(beforeTime);
                    if (reminderTime >= DateTime.Now.AddSeconds(5))
                    {
                        XmlDocument payload;

                        if (!generatedPayloads.TryGetValue(s, out payload))
                        {
                            payload = GeneratePayload(account, s);
                            generatedPayloads[s] = payload;
                        }

                        var notif = new ScheduledToastNotification(payload, reminderTime)
                        {
                            Group = group,
                            Tag   = s.Identifier.ToString() + "." + today.ToString("yy-dd-MM")
                        };

                        if (isExpirationTimeSupported)
                        {
                            notif.ExpirationTime = today.Add(s.EndTime.TimeOfDay);
                        }

                        try
                        {
                            notifier.AddToSchedule(notif);
                        }
                        catch (Exception ex)
                        {
                            // If OS is in a bad state, we'll just stop
                            TelemetryExtension.Current?.TrackException(new Exception("Adding toast to schedule failed: " + ex.Message, ex));
                            return;
                        }
                    }
                }
            }
        }