private int numClashes(ScheduledClass scheduledClass, byte[] slots)
        {
            var classes = new List <ScheduledClass> {
                scheduledClass
            }.Concat(scheduledClass.ChildClasses);

            //Don't care about classes we have no choice about clashing
            if (scheduledClass.OnlyChoice)
            {
                return(0);
            }

            int clashes = 0;

            foreach (var childClass in classes)
            {
                for (int i = childClass.SlotStart; i < childClass.SlotEnd; i++)
                {
                    if (slots[i] > 0)
                    {
                        clashes++;
                        break;
                    }
                }
            }
            return(clashes);
        }
        private byte[] updateSlots(ScheduledClass scheduledClass, byte[] slots)
        {
            var newSlots = new byte[24 * 4 * 5];

            Array.Copy(slots, newSlots, slots.Length);

            //Don't care about classes we have no choice about clashing
            if (scheduledClass.OnlyChoice)
            {
                return(newSlots);
            }

            var classes = new List <ScheduledClass> {
                scheduledClass
            }.Concat(scheduledClass.ChildClasses);

            foreach (var childClass in classes)
            {
                for (int i = childClass.SlotStart; i < childClass.SlotEnd; i++)
                {
                    newSlots[i]++;
                }
            }
            return(newSlots);
        }
Beispiel #3
0
        private bool classEquivalent(ScheduledClass a, ScheduledClass b)
        {
            //optimising this way not worth it if there are child classes
            if (a.ChildClasses.Any() || b.ChildClasses.Any())
            {
                return(false);
            }

            return(a.SlotStart == b.SlotStart && a.SlotEnd == b.SlotEnd);
        }
        public Timetable(List <ScheduledClass> permutation)
        {
            int size = permutation.Count + permutation.Sum(c => c.ChildClasses.Count);

            Classes = new ScheduledClass[size];

            int i = 0;

            foreach (var scheduledClass in permutation)
            {
                Classes[i] = scheduledClass;
                i++;
                foreach (var childClass in scheduledClass.ChildClasses)
                {
                    Classes[i] = childClass;
                    i++;
                }
            }
        }
        public Timetable(List <ScheduledClass> permutation)
        {
            int size = permutation.Count + permutation.Sum(c => c.ChildClasses.Count);

            Classes = new ScheduledClass[size];

            //Fill the classes array, including all child classes
            int j = 0;

            foreach (var scheduledClass in permutation)
            {
                Classes[j] = scheduledClass;
                j++;
                foreach (var childClass in scheduledClass.ChildClasses)
                {
                    Classes[j] = childClass;
                    j++;
                }
            }

            //Calculate average start time and total number of days
            long startTimes = 0;

            for (int i = 1; i <= 5; i++)
            {
                var classes = Classes.Where(c => (int)c.TimeStart.DayOfWeek == i).OrderBy(c => c.TimeStart);

                if (classes.Any())
                {
                    NumberDaysClasses++;
                    startTimes += classes.First().TimeStart.TimeOfDay.Ticks;
                }
            }

            AverageStartTime = startTimes / NumberDaysClasses;
        }
Beispiel #6
0
        private async Task downloadTimetable()
        {
            ClassInfos = new List <ClassInfo>();

            string resultStr = await getTimetableHTML(Code);

            HtmlDocument doc = new HtmlDocument();

            doc.LoadHtml(resultStr);

            List <HtmlNode> tables = doc.DocumentNode.Descendants("table").ToList();

            List <HtmlNode> rows = new List <HtmlNode>();

            //We look for the first non-empty table
            //This is okay as everything is filtered elsewhere (so we can ignore summer/winter/whatever)
            int i = 0;

            while (!rows.Any())
            {
                HtmlNode timesTable = tables.Skip(i++).FirstOrDefault();

                if (timesTable == null)
                {
                    return;
                }

                rows = timesTable.Descendants("tbody").First().Descendants("tr").ToList();
            }

            foreach (var row in rows)
            {
                try
                {
                    var elements = row.Descendants("td").ToArray();

                    string date      = elements[9].InnerText;
                    string startTime = date + " " + elements[3].InnerText;
                    string endTime   = date + " " + elements[4].InnerText;

                    string[] info = elements[0].InnerText.Split('/');

                    var timeStart = DateTime.ParseExact(startTime, "dd MMM yyyy HH:mm", CultureInfo.InvariantCulture);
                    var timeEnd   = DateTime.ParseExact(endTime, "dd MMM yyyy HH:mm", CultureInfo.InvariantCulture);

                    ScheduledClass scheduledClass = new ScheduledClass(timeStart, timeEnd)
                    {
                        Location    = elements[7].InnerText,
                        ClassNumber = short.Parse(info[5])
                    };

                    //Don't include Breakout classses, they're useless
                    if (info[4].Contains("Breakout"))
                    {
                        continue;
                    }

                    var classInfo = ClassInfos.FirstOrDefault(c => c.ClassType == info[4]);

                    if (classInfo != null)
                    {
                        scheduledClass.ClassInfo = classInfo;
                        classInfo.ScheduledClasses.Add(scheduledClass);
                    }
                    else
                    {
                        classInfo = new ClassInfo
                        {
                            ClassName        = elements[1].InnerText,
                            ScheduledClasses = new List <ScheduledClass> {
                                scheduledClass
                            },
                            ParentSubject = this,
                            ClassType     = info[4]
                        };
                        scheduledClass.ClassInfo = classInfo;
                        ClassInfos.Add(classInfo);
                    }
                }
                catch (Exception)//Sadly can't trust timetable to be in correct format
                { }
            }
        }
        public async Task UpdateTimetable()
        {
            ClassInfos = new List <ClassInfo>();

            string resultStr = await getTimetableHTML(Code);

            HtmlDocument doc = new HtmlDocument();

            doc.LoadHtml(resultStr);

            var tables = doc.DocumentNode.Descendants("table");

            IEnumerable <HtmlNode> rows = new List <HtmlNode>();

            //We look for the first non-empty table
            //This is okay as everything is filtered elsewhere (so we can ignore summer/winter/whatever)
            int i = 0;

            while (!rows.Any())
            {
                HtmlNode timesTable = tables.Skip(i).FirstOrDefault();

                if (timesTable == null)
                {
                    return;
                }

                rows = timesTable.Descendants("tbody").First().Descendants("tr");

                i++;
            }

            foreach (var row in rows)
            {
                try
                {
                    var elements = row.Descendants("td").ToArray();

                    string date  = elements[9].InnerText;
                    string start = date + " " + elements[3].InnerText;
                    string end   = date + " " + elements[4].InnerText;

                    string[] info = elements[0].InnerText.Split('/');

                    var timeStart = DateTime.ParseExact(start, "dd MMM yyyy HH:mm", CultureInfo.InvariantCulture);
                    var timeEnd   = DateTime.ParseExact(end, "dd MMM yyyy HH:mm", CultureInfo.InvariantCulture);

                    ScheduledClass scheduledClass = new ScheduledClass(timeStart, timeEnd)
                    {
                        Location    = elements[7].InnerText,
                        ClassNumber = short.Parse(info[5])
                    };

                    //Don't include Breakout classses, they're useless
                    if (info[4].Contains("Breakout"))
                    {
                        continue;
                    }

                    var classInfo = ClassInfos.FirstOrDefault(c => c.ClassType == info[4]);

                    if (classInfo != null)
                    {
                        scheduledClass.ClassInfo = classInfo;
                        classInfo.ScheduledClasses.Add(scheduledClass);
                    }
                    else
                    {
                        classInfo = new ClassInfo
                        {
                            ClassName        = elements[1].InnerText,
                            ScheduledClasses = new List <ScheduledClass> {
                                scheduledClass
                            },
                            ParentSubject = this,
                            ClassType     = info[4]
                        };
                        scheduledClass.ClassInfo = classInfo;
                        ClassInfos.Add(classInfo);
                    }
                }
                catch (Exception)//Sadly can't trust timetable to be in correct format
                {   }
            }

            //Make a copy of the originals to be used in rendering
            OriginalClassInfos = new List <ClassInfo>(ClassInfos);

            consolidateClasses();

            //Removing equivalent classes:

            foreach (var classInfo in ClassInfos)
            {
                var removals = new List <ScheduledClass>();//Can't remove them during enumeration, must collect to remove later
                foreach (var scheduledClass in classInfo.ScheduledClasses)
                {
                    if (removals.Contains(scheduledClass))
                    {
                        continue;
                    }

                    var equivalents = classInfo.ScheduledClasses.Where(b => classEquivalent(scheduledClass, b) && b != scheduledClass);
                    removals.AddRange(equivalents);
                }

                foreach (var removal in removals)
                {
                    classInfo.ScheduledClasses.Remove(removal);
                }
            }

            DateTime earliestClass = DateTime.MaxValue;

            foreach (var scheduledClass in AllClasses)
            {
                if (scheduledClass.TimeStart < earliestClass)
                {
                    earliestClass = scheduledClass.TimeStart;
                }
            }
            int earliestWeek = getWeekOfYear(earliestClass);


            foreach (var scheduledClass in AllClasses)
            {
                while (getWeekOfYear(scheduledClass.TimeStart) > earliestWeek)
                {
                    scheduledClass.TimeStart = scheduledClass.TimeStart - TimeSpan.FromDays(7);
                    scheduledClass.TimeEnd   = scheduledClass.TimeEnd - TimeSpan.FromDays(7);
                }
            }
        }