コード例 #1
0
ファイル: Settings.xaml.cs プロジェクト: Blecki/LeaveWizard
 public static Settings Show(WeekData Week)
 {
     var dialog = new Settings();
     dialog.DaysPerSubInput.Text = Week.LeavePolicy.DaysPerSub.ToString();
     dialog.AmazonRoutesInput.Text = Week.LeavePolicy.AmazonRoutes.ToString();
     dialog.ShowDialog();
     return dialog;
 }
コード例 #2
0
 public static ModifyBaseData Show(WeekData Week)
 {
     var dialog = new ModifyBaseData();
     dialog.DateInput.Text = Week.SaturdayDate.ToShortDateString();
     dialog.YearInput.Text = Week.Year.ToString();
     dialog.PayPeriodInput.Text = Week.PayPeriod.ToString();
     dialog.WeekInput.Text = Week.Week.ToString();
     dialog.ShowDialog();
     return dialog;
 }
コード例 #3
0
        public static SubSchedule GenerateSubSchedule(WeekData Week)
        {
            var result = new SubSchedule();
            result.Subs = new List<SubRow>();
            result.OpenRoutes = new List<List<String>>();
            for (int i = 0; i < 7; ++i) result.OpenRoutes.Add(new List<String>());
            foreach (var sub in Week.Substitutes)
                result.Subs.Add(new SubRow { Name = sub.Name });

            for (var day = 0; day < 7; ++day)
                foreach (var leaveEntry in Week.DailySchedules[day].ReliefDays)
                {
                    var subName = "";
                    var data = "";
                    if (leaveEntry.LeaveType == "SUNDAY")
                    {
                        subName = leaveEntry.Substitute;
                        data = leaveEntry.Carrier;
                    }
                    else
                    {
                        var regular = Week.Regulars.Find(r => r.Name == leaveEntry.Carrier);
                        if (regular != null)
                        {
                            if (day == 1 || Week.DailySchedules[day].IsHoliday) continue;
                            if ("R35V".Contains(leaveEntry.LeaveType)) continue; //Don't put regulars on schedule for working relief day.
                            subName = leaveEntry.Substitute;
                            data = regular.Route.ToString();

                        }
                        else
                        {
                            subName = leaveEntry.Carrier;
                            data = leaveEntry.LeaveType;
                        }
                    }

                    if (subName == "DUMMY")
                        result.OpenRoutes[day].Add(data);
                    else
                    {
                        var sub = result.Subs.Find(r => r.Name == subName);
                        if (sub == null)
                        {
                            sub = new SubRow { Name = subName };
                            result.Subs.Add(sub);
                        }

                        sub.Schedule[day] = data;
                    }
                }

            //result.Subs = new List<SubRow>(result.Subs.OrderBy(r => r.Name));
            return result;
        }
コード例 #4
0
ファイル: WeekData.cs プロジェクト: Blecki/LeaveWizard
        public void Propogate(WeekData PreviousWeek)
        {
            this.PreviousWeek = PreviousWeek;

            if (PreviousWeek == null)
            {
                SaturdayDate = DateTime.FromOADate(0);
                PayPeriod = 0;
                Week = 1;
                Year = 2015;
                Substitutes = new List<Substitute>();
                Regulars = new List<RegularCarrier>();
                DailySchedules = new DailySchedule[7];
                for (int i = 0; i < 7; ++i) DailySchedules[i] = new DailySchedule();
                PendingJDays = new List<Tuple<DayOfWeek, LeaveEntry>>();
                LeavePolicy = new LeavePolicy { DaysPerSub = 5, AmazonRoutes = 0 };
            }
            else
            {
                LeavePolicy = PreviousWeek.LeavePolicy;
                Year = PreviousWeek.Year;
                Week = PreviousWeek.Week + 1;
                if (Week == 3)
                {
                    PayPeriod = PreviousWeek.PayPeriod + 1;
                    Week = 1;
                }
                else
                    PayPeriod = PreviousWeek.PayPeriod;

                SaturdayDate = PreviousWeek.SaturdayDate + TimeSpan.FromDays(7);

                Substitutes = new List<Substitute>(PreviousWeek.Substitutes);
                Regulars = new List<RegularCarrier>(PreviousWeek.Regulars);

                PendingJDays = new List<Tuple<DayOfWeek, LeaveEntry>>();
                DailySchedules = PreviousWeek.DailySchedules.Select(ds => ds.CloneForNewWeek()).ToArray();
                for ( var day = 0; day < 7; ++day)
                {
                    foreach (var rd in DailySchedules[day].ReliefDays)
                        if (rd.LeaveType == "J") PendingJDays.Add(Tuple.Create((DayOfWeek)day, rd));
                    DailySchedules[day].ReliefDays.RemoveAll(rd => rd.LeaveType == "J");
                }

                if (PreviousWeek.PendingJDays != null)
                    foreach (var pendingJ in PreviousWeek.PendingJDays)
                        DailySchedules[(int)pendingJ.Item1].ReliefDays.Add(pendingJ.Item2);
            }

            PrepareSundayRoutes();

            if (String.IsNullOrEmpty(EffectiveChanges)) EffectiveChanges = "";
            var iter = new StringIterator(EffectiveChanges);

            try
            {
                while (!iter.AtEnd)
                {
                    SkipWhitespace(iter);
                    if (iter.Next == 'S')
                    {
                        var sub = ParseSub(iter);
                        var existing = Substitutes.Find(s => s.Name == sub.Name);
                        if (existing != null) Substitutes.Remove(existing);
                        Substitutes.Add(sub);
                    }
                    else if (iter.Next == 'R')
                    {
                        var regular = ParseRegular(iter);
                        var existing = Regulars.Find(r => r.Name == regular.Name);
                        if (existing != null) Regulars.Remove(existing);
                        Regulars.Add(regular);
                    }
                    else if (iter.Next == 'L')
                    {
                        bool denied = false;
                        iter.Advance();
                        SkipWhitespace(iter);
                        if (iter.Next == 'D')
                        {
                            iter.Advance();
                            SkipWhitespace(iter);
                            denied = true;
                        }
                        var name = ParseName(iter);
                        SkipWhitespace(iter);
                        var day = ParseDay(iter);
                        SkipWhitespace(iter);
                        var type = ParseLeave(iter);
                        iter.Advance();
                        var leave = new LeaveEntry { Carrier = name, LeaveType = type, Substitute = "DUMMY" };
                        if (denied)
                            DailySchedules[(int)day].DeniedLeave.Add(leave);
                        else
                        {
                            DailySchedules[(int)day].ReliefDays.Add(leave);

                            //Leave supercedes a route assignment.
                            foreach (var reliefDay in DailySchedules[(int)day].ReliefDays.Where(rd => rd.Substitute == name))
                                reliefDay.Substitute = "DUMMY";
                        }
                    }
                    else if (iter.Next == 'B')
                    {
                        iter.Advance();
                        SkipWhitespace(iter);
                        var dateString = ParseName(iter);
                        SkipWhitespace(iter);
                        var year = ParseRoute(iter);
                        SkipWhitespace(iter);
                        var payPeriod = ParseRoute(iter);
                        SkipWhitespace(iter);
                        var week = ParseRoute(iter);

                        this.SaturdayDate = Convert.ToDateTime(dateString);
                        this.Year = year;
                        this.PayPeriod = payPeriod;
                        this.Week = week;
                    }
                    else if (iter.Next == 'P')
                    {
                        iter.Advance();
                        SkipWhitespace(iter);
                        var daysPerSub = ParseRoute(iter);
                        SkipWhitespace(iter);
                        var amazonRoutes = ParseRoute(iter);
                        LeavePolicy = new LeavePolicy { DaysPerSub = daysPerSub, AmazonRoutes = amazonRoutes };
                        PrepareSundayRoutes();
                    }
                    else if (iter.Next == 'A')
                    {
                        iter.Advance();
                        SkipWhitespace(iter);
                        var regular = ParseName(iter);
                        SkipWhitespace(iter);
                        var sub = ParseName(iter);
                        SkipWhitespace(iter);
                        var day = ParseDay(iter);
                        if (sub != "DUMMY")
                            foreach (var reliefDay in DailySchedules[(int)day].ReliefDays)
                                if (reliefDay.Substitute == sub) reliefDay.Substitute = "DUMMY";
                        foreach (var reliefDay in DailySchedules[(int)day].ReliefDays)
                            if (reliefDay.Carrier == regular) reliefDay.Substitute = sub;
                    }
                    else if (iter.Next == 'H')
                    {
                        iter.Advance();
                        SkipWhitespace(iter);
                        var day = ParseDay(iter);
                        Holiday(day);
                    }
                    else if (iter.Next == 'D')
                    {
                        iter.Advance();
                        if (iter.Next == 'S')
                        {
                            iter.Advance();
                            SkipWhitespace(iter);
                            var name = ParseName(iter);
                            Substitutes.RemoveAll(s => s.Name == name);
                        }
                        else if (iter.Next == 'R')
                        {
                            iter.Advance();
                            SkipWhitespace(iter);
                            var name = ParseName(iter);
                            Regulars.RemoveAll(r => r.Name == name);
                        }
                        else if (iter.Next == 'L')
                        {
                            iter.Advance();
                            SkipWhitespace(iter);
                            var name = ParseName(iter);
                            SkipWhitespace(iter);
                            var day = ParseDay(iter);
                            DailySchedules[(int)day].ReliefDays.RemoveAll(r => r.Carrier == name);
                        }
                        else if (iter.Next == 'D')
                        {
                            iter.Advance();
                            SkipWhitespace(iter);
                            var name = ParseName(iter);
                            SkipWhitespace(iter);
                            var day = ParseDay(iter);
                            DailySchedules[(int)day].DeniedLeave.RemoveAll(r => r.Carrier == name);
                        }
                        else if (iter.Next == 'H')
                        {
                            iter.Advance();
                            SkipWhitespace(iter);
                            var day = ParseDay(iter);
                            ClearHoliday(day);
                        }
                    }
                    else
                    {
                        iter.Advance();
                    }
                }
            }
            catch (Exception e)
            {

            }

            foreach (var ds in DailySchedules) ds.ReliefDays = new List<LeaveEntry>(ds.ReliefDays.OrderBy(rd => rd.Carrier));

            //Substitutes = new List<Substitute>(Substitutes.OrderBy(s => s.Name));
            Regulars = new List<RegularCarrier>(Regulars.OrderBy(r => r.Route));
        }
コード例 #5
0
ファイル: WeekData.cs プロジェクト: Blecki/LeaveWizard
 public void ApplyChange(WeekData PreviousWeek, String Command)
 {
     EffectiveChanges += Command;
     Propogate(PreviousWeek);
     EffectiveChanges = CodeGenerator.GenerateChangeCode(PreviousWeek, this);
 }
コード例 #6
0
ファイル: CodeGenerator.cs プロジェクト: Blecki/LeaveWizard
        public static String GenerateChangeCode(WeekData Start, WeekData End)
        {
            var result = new StringBuilder();

            if (Start == null)
            {
                Start = new WeekData();
                Start.Propogate(null);
            }

            var startDate = Start.SaturdayDate.ToShortDateString();
            var expectedEndDate = (Start.SaturdayDate + TimeSpan.FromDays(7)).ToShortDateString();
            var endDate = End.SaturdayDate.ToShortDateString();

            var expectedEndWeek = Start.Week + 1;
            var expectedEndPP = Start.PayPeriod;

            if (expectedEndWeek == 3)
            {
                expectedEndPP += 1;
                expectedEndWeek = 1;
            }

            if (endDate != expectedEndDate || expectedEndWeek != End.Week || expectedEndPP != End.PayPeriod || Start.Year != End.Year)
                result.Append(BaseData(End.SaturdayDate, End.Year, End.PayPeriod, End.Week));

            if (End.LeavePolicy.DaysPerSub != Start.LeavePolicy.DaysPerSub || End.LeavePolicy.AmazonRoutes != Start.LeavePolicy.AmazonRoutes)
                result.Append(Policy(End.LeavePolicy.DaysPerSub, End.LeavePolicy.AmazonRoutes));

            foreach (var sub in End.Substitutes)
            {
                var existing = Start.Substitutes.Find(s => s.Name == sub.Name && s.Matrix[0] == sub.Matrix[0] && s.Matrix[1] == sub.Matrix[1] && s.Matrix[2] == sub.Matrix[2]);
                if (existing == null)
                    result.Append(Substitute(sub));
            }

            foreach (var sub in Start.Substitutes)
            {
                var existing = End.Substitutes.Find(s => s.Name == sub.Name);
                if (existing == null)
                    result.Append(DeleteSubstitute(sub.Name));
            }

            foreach (var regular in End.Regulars.Where(r => Start.Regulars.Find(s => s.Name == r.Name && s.Route == r.Route) == null))
                result.Append(Regular(regular.Name, regular.Route));
            foreach (var regular in Start.Regulars.Where(r => End.Regulars.Find(s => s.Name == r.Name) == null))
                result.Append(DeleteRegular(regular.Name));

            for (int i = 6; i >= 0; --i)
            {
                string sundayRouteAssignments = "";

                foreach (var day in End.DailySchedules[i].ReliefDays)
                {
                    bool subAssigned = false;

                    if (day.LeaveType == "SUNDAY")
                    {

                    }
                    else if (day.LeaveType != "H") // H days should only exist as a result of a future holiday.
                    {
                        if (Constants.PropogatableLeaveTypes.Contains(day.LeaveType))
                        {
                            var existingPropogatableDay = Start.DailySchedules[i].ReliefDays.Find(l => l.Carrier == day.Carrier && l.LeaveType == day.LeaveType);

                            if (existingPropogatableDay == null && day.LeaveType == "J")
                            {
                                var tuple = Start.PendingJDays.Find(t => t.Item2.Carrier == day.Carrier && t.Item2.LeaveType == day.LeaveType);
                                if (tuple != null) existingPropogatableDay = tuple.Item2;
                            }

                            if (existingPropogatableDay == null)
                                result.Append(Leave(day.Carrier, i, day.LeaveType));
                            else
                            {
                                subAssigned = true;
                                if (day.Substitute != existingPropogatableDay.Substitute)
                                    result.Append(Assign(day.Carrier, day.Substitute, i));
                            }
                        }
                        else
                            result.Append(Leave(day.Carrier, i, day.LeaveType));
                    }

                    if (!subAssigned && day.Substitute != "DUMMY")
                    {
                        if (day.LeaveType == "SUNDAY")
                            sundayRouteAssignments += Assign(day.Carrier, day.Substitute, i);
                        else
                            result.Append(Assign(day.Carrier, day.Substitute, i));
                    }
                }

                foreach (var day in Start.DailySchedules[i].ReliefDays.Where(r => Constants.PropogatableLeaveTypes.Contains(r.LeaveType)))
                {
                    var existingDay = End.DailySchedules[i].ReliefDays.Find(l => l.Carrier == day.Carrier && l.LeaveType == day.LeaveType);
                    if (existingDay == null)
                        result.Append(DeleteLeave(day.Carrier, i));
                }

                if (End.DailySchedules[i].IsHoliday)
                    result.Append(Holiday(i));

                result.Append(sundayRouteAssignments);

                foreach (var day in End.DailySchedules[i].DeniedLeave)
                    result.Append(DeniedLeave(day.Carrier, i, day.LeaveType));
            }

            foreach (var jDay in Start.PendingJDays)
            {
                var existingJDay = End.DailySchedules[(int)jDay.Item1].ReliefDays.Find(l => l.Carrier == jDay.Item2.Carrier && l.LeaveType == jDay.Item2.LeaveType);
                if (existingJDay == null)
                    result.Append(DeleteLeave(jDay.Item2.Carrier, (int)jDay.Item1));
            }

            return result.ToString();
        }
コード例 #7
0
ファイル: DrawSubSchedule.cs プロジェクト: Blecki/LeaveWizard
        public static void DrawSubSchedule(PdfSharp.Drawing.XGraphics Graphics, WeekData Week)
        {
            var basicPen = XPens.Black;
            var boldPen = new XPen(XColors.Black, 2);
            var font = new XFont("Times New Roman", 14, XFontStyle.Bold);

            var schedule = GenerateSubSchedule(Week);
            var width = Graphics.PageSize.Width;
            var height = Graphics.PageSize.Height;
            var horizontalMargin = 20;
            var horizontalSpan = width - (horizontalMargin * 2);
            var columnWidth = horizontalSpan / 8;
            var verticalMargin = 20;
            var topMargin = 50;
            var mainVerticalSpan = height - topMargin - (verticalMargin * 2);
            var rowCount = schedule.Subs.Count + schedule.OpenRoutes.Max(l => l.Count);
            var rowHeight = mainVerticalSpan / rowCount;
            if (rowHeight > 20) rowHeight = 20;
            var realBottom = verticalMargin + topMargin + (rowHeight * rowCount);
            var fontMargin = 5;

            // Draw grid lines

            for (double x = horizontalMargin; x <= width; x += columnWidth)
                Graphics.DrawLine(boldPen, x, verticalMargin, x, realBottom);

            Graphics.DrawLine(basicPen, horizontalMargin, verticalMargin, width - horizontalMargin, verticalMargin);

            for (double y = verticalMargin + topMargin; y <= realBottom; y += rowHeight)
                Graphics.DrawLine(basicPen, horizontalMargin, y, width - horizontalMargin, y);

            // Draw info block at top-left
            Graphics.DrawString("Relief Carrier", font, XBrushes.Black, new XRect(horizontalMargin, verticalMargin, columnWidth, topMargin), XStringFormats.TopCenter);
            Graphics.DrawString("Schedule", font, XBrushes.Black, new XRect(horizontalMargin, verticalMargin + 16, columnWidth, topMargin), XStringFormats.TopCenter);
            Graphics.DrawString(String.Format("PP {0} WK {1}", Week.PayPeriod, Week.Week), font, XBrushes.Black, new XRect(horizontalMargin, verticalMargin, columnWidth, topMargin), XStringFormats.BottomCenter);

            // Draw Day Headers
            for (var day = 0; day < 7; ++day)
            {
                Graphics.DrawString(LongDayNames[day], font, XBrushes.Black, new XRect(horizontalMargin + (columnWidth * (day + 1)), verticalMargin, columnWidth, topMargin), XStringFormats.TopCenter);

                if (Week.DailySchedules[day].IsHoliday)
                    Graphics.DrawString("HOLIDAY", font, XBrushes.Black, new XRect(horizontalMargin + (columnWidth * (day + 1)), verticalMargin, columnWidth, topMargin), XStringFormats.Center);

                Graphics.DrawString((Week.SaturdayDate + TimeSpan.FromDays(day)).ToShortDateString(), font, XBrushes.Black, new XRect(horizontalMargin + (columnWidth * (day + 1)), verticalMargin, columnWidth, topMargin), XStringFormats.BottomCenter);
            }

            // Draw actual sub schedule.
            var row = 0;
            foreach (var sub in schedule.Subs)
            {
                Graphics.DrawString(sub.Name, font, XBrushes.Black, new XRect(fontMargin + horizontalMargin, verticalMargin + topMargin + (row * rowHeight), columnWidth, rowHeight), XStringFormats.Center);
                for (var c = 0; c < 7; ++c)
                    if (!String.IsNullOrEmpty(sub.Schedule[c]))
                        Graphics.DrawString(sub.Schedule[c], font, XBrushes.Black, new XRect(fontMargin + horizontalMargin + (columnWidth * (c + 1)), verticalMargin + topMargin + (row * rowHeight), columnWidth, rowHeight), XStringFormats.CenterLeft);
                row += 1;
            }

            // Draw open routes at bottom of schedule.
            for (var day = 0; day < 7; ++day)
            {
                var top = row;
                foreach (var entry in schedule.OpenRoutes[day])
                {
                    Graphics.DrawString(entry, font, XBrushes.Black, new XRect(fontMargin + horizontalMargin + (columnWidth * (day + 1)), verticalMargin + topMargin + (top * rowHeight), columnWidth, rowHeight), XStringFormats.CenterLeft);
                    top += 1;
                }
            }
        }
コード例 #8
0
 private int CountSubstituteScheduledDays(WeekData Week, string SubstituteName)
 {
     var r = 0;
     for (var day = 0; day < 7; ++day)
     {
         if (day == 1 || Week.DailySchedules[day].IsHoliday)
             r += Week.DailySchedules[day].ReliefDays.Count(entry => entry.Substitute == SubstituteName && entry.LeaveType == "SUNDAY");
         else
             r += Week.DailySchedules[day].ReliefDays.Count(entry => entry.Substitute == SubstituteName);
     }
     return r;
 }
コード例 #9
0
 public IEnumerable<int> EnumerateLeaveColumnHeights(WeekData Week)
 {
     for (var day = 0; day < 7; ++day)
         if (day == 1 || Week.DailySchedules[day].IsHoliday) yield return Week.LeavePolicy.AmazonRoutes;
         else yield return Week.DailySchedules[day].ReliefDays.Where(r => Week.Regulars.Find(c => c.Name == r.Carrier) == null).Count() + Week.Regulars.Count;
 }
コード例 #10
0
 public IEnumerable<int> EnumerateFullColumnHeights(WeekData Week)
 {
     yield return Week.Substitutes.Count + 1;
     yield return Week.Regulars.Count + 1;
     yield return EnumerateLeaveColumnHeights(Week).Max() + EnumerateDeniedLeaveCounts(Week).Max();
 }
コード例 #11
0
 public IEnumerable<int> EnumerateDeniedLeaveCounts(WeekData Week)
 {
     foreach (var day in Week.DailySchedules)
         yield return day.DeniedLeave.Count();
 }
コード例 #12
0
        public void DisplayWeek(WeekData Week)
        {
            CurrentWeek = Week;
            TopGrid.Children.Clear();
            MainGrid.Children.Clear();
            MainGrid.RowDefinitions.Clear();

            //MouseCoordBlock = AddToCell(TopGrid, 0, 1, new TextBlock { Text = "----" });

            if (CurrentWeek == null) return;

            var maxRows = EnumerateFullColumnHeights(Week).Max() + 4;
            var approvedLeaveRows = EnumerateLeaveColumnHeights(Week).Max() + 2;

            MainGrid.Height = 20 * maxRows;

            for (var i = 0; i < maxRows; ++i)
                MainGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(20) });

            AddCell(TopGrid, "Substitutes", 0, 0, "All available substitutes");
            AddCell(TopGrid, "", 0, 1, null);
            for (var i = 0; i < maxRows; ++i)
            {
                if (i > Week.Substitutes.Count)
                    AddCell(MainGrid, "", 0, i, "", null);
                else if (i == Week.Substitutes.Count)
                    AddCell(MainGrid, "+ new substitute", 0, i, "Click to add new substitute", () =>
                        {
                            var creator = CreateSub.Show();
                            if (creator.FinishedInput)
                                ApplyAction(String.Format("S\"{0}\" ", creator.Name));
                        });
                else if (i < Week.Substitutes.Count)
                {
                    var lambdaSub = Week.Substitutes[i];
                    AddCell(MainGrid, Week.Substitutes[i].ToString(), 0, i, "Click to modify matrix assignments", () =>
                        {
                            var matrixEditor = ModifyMatrix.Show(lambdaSub);
                            if (matrixEditor.FinishedInput)
                                ApplyAction(String.Format("S\"{0}\"M{1} {2} {3} ", lambdaSub.Name, matrixEditor.Choices[0], matrixEditor.Choices[1], matrixEditor.Choices[2]));
                        });

                    AddToCell(MainGrid, 0, i, new TextBlock
                    {
                        Text = "[del] ",
                        HorizontalAlignment = System.Windows.HorizontalAlignment.Right,
                        ToolTip = "Click to delete substitute"
                    }).MouseDown += (sender, args) => ApplyAction(String.Format("DS\"{0}\" ", lambdaSub.Name));
                }
            }

            AddCell(TopGrid, "D", 1, 0, "Days Scheduled", null);
            AddCell(TopGrid, "S", 1, 1, "Days Scheduled", null);

            for (var i = 0; i < Week.Substitutes.Count; ++i)
                AddCell(MainGrid, CountSubstituteScheduledDays(Week, Week.Substitutes[i].Name).ToString(), 1, i, "", null);

            for (var i = Week.Substitutes.Count; i < maxRows; ++i)
                AddCell(MainGrid, "", 1, i, "", null);

                AddCell(TopGrid, "Routes", 2, 0, "All routes");
            AddCell(TopGrid, "", 2, 1, null);
            for (var i = 0; i < maxRows; ++i)
            {
                if (i > Week.Regulars.Count)
                    AddCell(MainGrid, "", 2, i, "", null);
                else if (i >= Week.Regulars.Count)
                    AddCell(MainGrid, "+ new regular/route", 2, i, "Click to add regular", () =>
                    {
                        var creator = CreateRegular.Show();
                        if (creator.FinishedInput)
                            ApplyAction(String.Format("R\"{0}\"{1} ", creator.Name, creator.Route));
                    });
                else
                {
                    var lambdaR = Week.Regulars[i];
                    AddCell(MainGrid, lambdaR.ToString(), 2, i, null);

                    AddToCell(MainGrid, 2, i, new TextBlock
                    {
                        Text = "[del] ",
                        HorizontalAlignment = System.Windows.HorizontalAlignment.Right,
                        ToolTip = "Click to delete regular / route"
                    }).MouseDown += (sender, args) => ApplyAction(String.Format("DR\"{0}\" ", lambdaR.Name));
                }
            }

            for (var x = 3; x < 10; ++x)
            {
                var currentDay = Week.DailySchedules[x - 3];
                var dayIndex = x - 3;
                AddCell(TopGrid, ((DayOfWeek)dayIndex).ToString() + " - " + OffsetDateString(dayIndex) + (currentDay.IsHoliday ? " - HOLIDAY" : ""), x, 0, null);

                var localReliefDays = new List<LeaveEntry>(Week.DailySchedules[dayIndex].ReliefDays);

                if (localReliefDays.Count >= Week.Substitutes.Count)
                    AddCell(TopGrid, "FULL", x, 1, null);
                else
                    AddCell(TopGrid, String.Format("SUBS:{0}", Week.Substitutes.Count - localReliefDays.Count), x, 1, null);

                AddToCell(TopGrid, x, 1, new TextBlock
                {
                    HorizontalAlignment = System.Windows.HorizontalAlignment.Right,
                    Text = (currentDay.IsHoliday ? "[clear holiday]" : "[make holiday]"),
                }).MouseDown += (sender, args) =>
                    {
                        if (currentDay.IsHoliday) ApplyAction(String.Format("DH{0} ", Constants.DayNames[dayIndex]));
                        else ApplyAction(String.Format("H{0} ", Constants.DayNames[dayIndex]));
                    };

                var rowIndex = 0;

                if (dayIndex == 1 || currentDay.IsHoliday)
                {
                    var sundayRoutes = new List<LeaveEntry>(localReliefDays.Where(rd => rd.LeaveType == "SUNDAY"));
                    foreach (var sundayRoute in sundayRoutes)
                    {
                        localReliefDays.Remove(sundayRoute);
                        AddLeaveEntryCell(sundayRoute, LeaveCellType.Sunday, x, rowIndex);
                        rowIndex += 1;
                    }

                    while (rowIndex < CurrentWeek.Regulars.Count)
                    {
                        AddCell(MainGrid, "", x, rowIndex, null);
                        rowIndex += 1;
                    }

                    foreach (var regular in Week.Regulars)
                    {
                        var reliefDay = localReliefDays.Find(r => r.Carrier == regular.Name);
                        if (reliefDay != null)
                            localReliefDays.Remove(reliefDay);
                    }
                }
                else
                {
                    foreach (var regular in Week.Regulars)
                    {
                        var reliefDay = localReliefDays.Find(r => r.Carrier == regular.Name);
                        if (reliefDay == null)
                            AddCell(MainGrid, "", x, rowIndex, "Click to add leave", () =>
                                {
                                    var leaveSelector = SimpleSelector.Show("Select leave type", Constants.AllLeaveTypes.Select(c => (object)c));
                                    if (leaveSelector.SelectionMade)
                                        ApplyAction(String.Format("L\"{0}\"{1}{2} ",
                                            regular.Name, Constants.DayNames[dayIndex], leaveSelector.SelectedItem));
                                });
                        else
                        {
                            AddLeaveEntryCell(reliefDay, LeaveCellType.Regular, x, rowIndex);
                            localReliefDays.Remove(reliefDay);
                        }

                        rowIndex += 1;
                    }
                }

                foreach (var rDay in localReliefDays)
                {
                    AddLeaveEntryCell(rDay, LeaveCellType.Sub, x, rowIndex);
                    rowIndex += 1;
                }

                AddCell(MainGrid, "+ substitute leave", x, rowIndex, "Add leave for a substitute", () =>
                    {
                        var leaveSelector = SimpleSelector.Show("Select leave type", Constants.AllLeaveTypes.Select(c => (object)c));
                        if (leaveSelector.SelectionMade)
                        {
                            var carrierSelector = SimpleSelector.Show("Select carrier", EnumerateAllCarriers().Select(c => (object)c));
                            if (carrierSelector.SelectionMade)
                                ApplyAction(String.Format("L\"{0}\"{1}{2} ",
                                    carrierSelector.SelectedItem, Constants.DayNames[dayIndex], leaveSelector.SelectedItem));
                        }
                    });
                rowIndex += 1;

                while (rowIndex < approvedLeaveRows)
                {
                    AddCell(MainGrid, "", x, rowIndex, null);
                    rowIndex += 1;
                }

                AddCell(MainGrid, "DENIED LEAVE", x, rowIndex, null);
                rowIndex += 1;

                foreach (var rDay in CurrentWeek.DailySchedules[dayIndex].DeniedLeave)
                {
                    AddLeaveEntryCell(rDay, LeaveCellType.Denied, x, rowIndex);
                    rowIndex += 1;
                }

                AddCell(MainGrid, "+ denied leave", x, rowIndex, "Add denied leave", () =>
                    {
                        var leaveSelector = SimpleSelector.Show("Select leave type", Constants.AllLeaveTypes.Select(c => (object)c));
                        if (leaveSelector.SelectionMade)
                        {
                            var carrierSelector = SimpleSelector.Show("Select carrier", EnumerateAllCarriers().Select(c => (object)c));
                            if (carrierSelector.SelectionMade)
                                ApplyAction(String.Format("LD\"{0}\"{1}{2} ",
                                    carrierSelector.SelectedItem, Constants.DayNames[dayIndex], leaveSelector.SelectedItem));
                        }
                    });

                rowIndex += 1;

                while (rowIndex < maxRows)
                {
                    AddCell(MainGrid, "", x, rowIndex, null);
                    rowIndex += 1;
                }

            }

            UpdateMouseHilite();
            this.InvalidateVisual();
        }