Визуализация календаря с временными интервалами и перекрывающимися встречами - PullRequest
0 голосов
/ 10 октября 2018

Я изо всех сил пытаюсь обдумать это.

У меня есть List<Appointment>, который содержит DateTime Start и DateTime End вместе с несколькими другими битами.

Iхочу нарисовать ежедневник, который перечисляет все встречи в порядке с заполнителями / пробелами, где это уместно.

Я справился с этим, но теперь мне нужно разобраться со сценарием, когда встречи перекрываются.Кажется, это может быть;

  • встреча a начинается до и заканчивается после встречи b
  • встреча a начинается до и заканчивается во время встречи b
  • встреча a начинается во время и заканчивается после встречи b
  • встреча начинается во время и заканчивается во время встречи b

Это похоже на проблему, которая должна была быть решена ранее.Есть указатели?

Вот пример какого-то ужасного кода, над которым я сейчас работаю;

        List<TechActivityModel> techActivity = new TechService().GetTechActivity(7, new DateTime(2018, 4, 11), new DateTime(2018, 4, 11).AddDays(1))
            .OrderBy(t => t.Start).ToList();

        for (int i = techActivity.Count - 1; i >= 0; i--)
        {
            //something starts before and ends after
            TechActivityModel clash = techActivity.Where(t => t.Id != techActivity[i].Id && t.Start < techActivity[i].Start && t.End > techActivity[i].End).FirstOrDefault();
            while (clash != null)
            {
                //split the clashing activity into a task before and another task after the existing on
                //first create the 2nd part of the task (after the existing one)
                TechActivityModel activityContinued = new TechActivityModel()
                {
                    Start = techActivity[i].End,
                    End = clash.End,
                    Subject = "++" + clash.Subject
                };
                activityContinued.Length = (int)(activityContinued.End - activityContinued.Start).TotalMinutes;
                techActivity.Add(activityContinued);

                //update the clashing task to finish when the existing task starts
                clash.Subject = "+" + clash.Subject;
                clash.End = techActivity[i].Start;
                clash.Length = (int)(clash.End - clash.Start).TotalMinutes;

                clash = techActivity.Where(t => t.Id != techActivity[i].Id && t.Start < techActivity[i].Start && t.End > techActivity[i].End).FirstOrDefault();
            }
        }

        for (int i = techActivity.Count - 1; i >= 0; i--)
        {
            //something starts before and ends during
            TechActivityModel clash = techActivity.Where(t => t.Id != techActivity[i].Id && t.Start <= techActivity[i].Start && t.End > techActivity[i].Start).FirstOrDefault();
            while (clash != null)
            {
                //update the clashing task to finish when the existing task starts
                clash.Subject = "/" + clash.Subject;
                clash.End = techActivity[i].Start;
                clash.Length = (int)(clash.End - clash.Start).TotalMinutes;

                clash = techActivity.Where(t => t.Id != techActivity[i].Id && t.Start < techActivity[i].Start && t.End > techActivity[i].Start).FirstOrDefault();
            }
        }

        techActivity = techActivity.OrderBy(t => t.Start).ToList();

        //now we're going to pad all the gaps
        List<TechActivityModel> newList = new List<TechActivityModel>();

        DateTime LastEnd = techActivity[0].End;

        //start with the gap from midnight till the first task
        newList.Add(new TechActivityModel()
        {
            Start = new DateTime(2018, 4, 10),
            End = techActivity[0].Start,
            TicketNumber = 0,
            Note = "",
            TicketSubject = "",
            TimeLogged = 0,
            Id = 0
        }
        );

        //pad all the gaps
        for (int i = 1; i < techActivity.Count; i++)
        {
            if (LastEnd < techActivity[i].Start.AddMinutes(-2))
            {
                TechActivityModel gap = new TechActivityModel()
                {
                    Start = LastEnd.AddMinutes(1),
                    End = techActivity[i].Start,
                    Subject = "",
                    Id = 0
                };
                gap.Length = (int)(gap.End - gap.Start).TotalMinutes;
                newList.Add(gap);
            }
            LastEnd = techActivity[i].End;
        }

        //and finally fill the gap from the last task till midnight
        newList.Add(new TechActivityModel()
        {
            Start = LastEnd,
            End = new DateTime(2018, 4, 11),
            Subject = "",
            Length = 0
        }
        );

        newList.AddRange(techActivity);

        string content = "";
        foreach (TechActivityModel techActivityModel in newList.OrderBy(t => t.Start))
        {
            content += 
                techActivityModel.Start.ToShortTimeString() 
                + " - " + techActivityModel.End.ToShortTimeString() 
                + " (" + techActivityModel.Length + "mins)"
                + " : " + techActivityModel.Subject 
                + Environment.NewLine;
        }

1 Ответ

0 голосов
/ 11 октября 2018

Вот как бы я подошел к вашей проблеме, если я вас правильно понял.Я бы начал с поиска всех отдельных значений Start и End, все вместе в одном списке.Мы хотим, чтобы они были четкими и в порядке.Затем мы сшиваем этот список с собой для генерации пар:

var l = new List<Appointment>();
var ex = l.SelectMany(a => new[] { a.Start, a.End }).Distinct().OrderBy(dt => dt);
var pairs = ex.Zip(ex.Skip(1), (First, Second) => new { First, Second });

Теперь, используя правило, которое я упомянул в комментариях:

Два периода времени перекрываются, если период a начинаетсядо окончания периода b и периода b до окончания периода a.

Мы работаем с каждой парой дат-тайм и повторно запрашиваем наш список встреч для все встречи, которые перекрывают период, описанный парой.Если вы не получили результатов, этот период времени в настоящее время свободен.Если вы получите один результат, у вас есть (на этот период) встреча, которая не перекрывается ничем другим.Если вы получаете несколько результатов, у вас есть конфликт и вы можете решить, как это отобразить.Но учтите, что вам не нужно постоянно пересматривать этот период времени и расширять / сокращать его, обновлять его текст и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...