Пример #1
0
 protected bool Equals(ConnectedCourse other)
 {
     return(string.Equals(CourseId, other.CourseId) && string.Equals(CourseId2, other.CourseId2));
 }
Пример #2
0
        /// <summary>
        /// This method updates the (more detailed) properties of a given course such as dates, connected courses, description etc.
        /// </summary>
        /// <param name="course">Course for which the information should be updated</param>
        /// <param name="db">Database context</param>
        /// <param name="list">List of existing courses</param>
        /// <param name="catalog">Course catalog</param>
        /// <param name="isConnectedCourse">Determines if the current parsing happens for a connected course (is used to prevent cirular parsing)</param>
        /// <returns></returns>
        public async Task GetCourseDetailAsync(Course course, DatabaseContext db, List <Course> list, CourseCatalog catalog, bool isConnectedCourse = false)
        {
            HtmlDocument doc = await GetHtmlDocumentForCourse(course, db);

            if (doc == null)
            {
                return;
            }


            var changed = false;

            //case of isConnectedCourse is set to false (on PAUL website) is not handled
            if (isConnectedCourse)
            {
                if (course.ParsedConnectedCourses.All(c => c.Name.Length > course.Name.Length))
                {
                    var valueBefore = course.IsConnectedCourse;
                    course.IsConnectedCourse = false;
                    if (course.IsConnectedCourse != valueBefore)
                    {
                        changed = true;
                    }
                }
                else if (course.IsConnectedCourse != isConnectedCourse)
                {
                    course.IsConnectedCourse = isConnectedCourse;
                    changed = true;
                }
            }

            //Update InternalID if not set before (migration code)
            if (course.InternalCourseID == null)
            {
                course.InternalCourseID = course.Id.Split(',')[1];
                changed = true;
            }

            //Get Shortname
            var descr = doc.DocumentNode.GetDescendantsByName("shortdescription").FirstOrDefault();

            if (descr != null && course.ShortName != descr.Attributes["value"].Value)
            {
                course.ShortName = descr.Attributes["value"].Value;
                changed          = true;
            }

            try
            {
                //Termine parsen
                var dates = GetDates(doc, db).ToList();
                await UpdateDatesInDatabase(course, dates, db);
                await UpdateExamDates(doc, db, course);
            }
            catch
            {
                //if the updating of dates fails, not the whole update should crash
                PaulRepository.AddLog($"Date parsing failed for course {course.CourseId}", FatalityLevel.Error, "Date parsing");
            }

            //Verbundene Veranstaltungen parsen
            var divs    = doc.DocumentNode.GetDescendantsByClass("dl-ul-listview");
            var courses = divs.FirstOrDefault(l => l.InnerHtml.Contains("Veranstaltung anzeigen"))?.ChildNodes.Where(l => l.Name == "li" && l.InnerHtml.Contains("Veranstaltung anzeigen"));

            if (courses != null)
            {
                foreach (var c in courses)
                {
                    var text   = c.Descendants().First(n => n.Name == "strong")?.InnerText;
                    var name   = text.Split(new[] { ' ' }, 2)[1];
                    var id     = text.Split(new[] { ' ' }, 2)[0];
                    var url    = c.Descendants().First(n => n.Name == "a")?.Attributes["href"].Value;
                    var docent = c.Descendants().Where(n => n.Name == "p").Skip(2).First().InnerText;

                    await _writeLock.WaitAsync();

                    Course c2 = list.FirstOrDefault(co => co.Id == $"{course.Catalogue.InternalID},{id}");
                    if (c2 == null)
                    {
                        c2 = new Course {
                            Name = name, TrimmedUrl = url, Catalogue = course.Catalogue, Id = $"{course.Catalogue.InternalID},{id}"
                        };
                        //db.Courses.Add(c2);
                        db.Entry(c2).State = EntityState.Added;
                        list.Add(c2);
                    }

                    //prevent that two separate threads add the connected courses

                    if (course.Id != c2.Id &&
                        !course.ParsedConnectedCourses.Any(co => co.Id == c2.Id) &&
                        !c2.ParsedConnectedCourses.Any(co => co.Id == course.Id))
                    {
                        var con1 = new ConnectedCourse {
                            CourseId = course.Id, CourseId2 = c2.Id
                        };
                        course.ParsedConnectedCourses.Add(c2);
                        db.ConnectedCourses.Add(con1);

                        var con2 = new ConnectedCourse {
                            CourseId = c2.Id, CourseId2 = course.Id
                        };
                        c2.ParsedConnectedCourses.Add(course);
                        db.ConnectedCourses.Add(con2);
                    }

                    _writeLock.Release();
                }
            }

            //Gruppen parsen
            var groups = divs.FirstOrDefault(l => l.InnerHtml.Contains("Kleingruppe anzeigen"))?.ChildNodes.Where(l => l.Name == "li");

            if (groups != null)
            {
                var parsedTutorials = groups.Select(group =>
                {
                    var name = group.Descendants().First(n => n.Name == "strong")?.InnerText;
                    var url  = group.Descendants().First(n => n.Name == "a")?.Attributes["href"].Value;
                    return(new Course {
                        Id = course.Id + $",{name}", Name = name, TrimmedUrl = url, CourseId = course.Id, IsTutorial = true, Catalogue = catalog
                    });
                });

                foreach (var parsedTutorial in parsedTutorials)
                {
                    var tutorial = course.ParsedTutorials.FirstOrDefault(t => t == parsedTutorial);
                    if (tutorial != null)
                    {
                        tutorial.NewUrl = parsedTutorial.TrimmedUrl;
                    }
                }

                var newTutorials = parsedTutorials.Except(course.ParsedTutorials).ToList();
                if (newTutorials.Any())
                {
                    await _writeLock.WaitAsync();

                    //db.Courses.AddRange(newTutorials);
                    foreach (var t in newTutorials)
                    {
                        var entry = db.Entry(t);
                        if (entry.State != EntityState.Added)
                        {
                            entry.State = EntityState.Added;
                        }
                    }

                    course.ParsedTutorials.AddRange(newTutorials);
                    _writeLock.Release();
                }

                var oldTutorials = course.ParsedTutorials.Except(parsedTutorials).ToList();

                if (oldTutorials.Any() && parsedTutorials.Any())
                {
                    await _writeLock.WaitAsync();

                    await db.Database.ExecuteSqlCommandAsync($"DELETE FROM Date Where CourseId IN ({string.Join(",", oldTutorials.Select(o => "'" + o.Id + "'"))})");

                    var selectedCourses = db.SelectedCourses.Where(p => oldTutorials.Any(o => o.Id == p.CourseId)).Include(s => s.Users).ThenInclude(u => u.User).ToList();
                    foreach (var selectedCourseUser in selectedCourses.SelectMany(s => s.Users))
                    {
                        await db.Database.ExecuteSqlCommandAsync($"DELETE FROM SelectedCourseUser Where UserId IN ({selectedCourseUser.User.Id}) And SelectedCourseId IN ({string.Join(",", selectedCourses.Select(s => "'" + s.Id + "'"))}) ");
                    }
                    await db.Database.ExecuteSqlCommandAsync($"DELETE FROM SelectedCourse Where CourseId IN ({string.Join(",", oldTutorials.Select(o => "'" + o.Id + "'"))})");

                    await db.Database.ExecuteSqlCommandAsync($"DELETE FROM Course Where Id IN ({string.Join(",", oldTutorials.Select(o => "'" + o.Id + "'"))})");

                    foreach (var old in oldTutorials)
                    {
                        course.ParsedTutorials.Remove(old);
                    }
                    _writeLock.Release();
                }
            }


            //mark course as modified
            if (changed)
            {
                await _writeLock.WaitAsync();

                db.ChangeTracker.TrackObject(course);
                _writeLock.Release();
            }
        }