public Course(string id, List <Unit> units, CourseSettings settings, DirectoryInfo directory) { Id = id; Units = units; Settings = settings; Directory = directory; }
private static IEnumerable <Unit> LoadUnits(DirectoryInfo dir, CourseSettings settings, string courseId) { var unitsDirectories = dir.GetDirectories().OrderBy(d => d.Name); var unitIds = new HashSet <Guid>(); var unitUrls = new HashSet <string>(); var slideIndex = 0; foreach (var unitDirectory in unitsDirectories) { var unit = UnitLoader.LoadUnit(unitDirectory, settings, courseId, slideIndex); if (unitIds.Contains(unit.Id)) { throw new CourseLoadingException($"Ошибка в курсе \"{settings.Title}\" при загрузке модуля \"{unit.Title}\" из {unitDirectory.FullName}. " + $"Повторяющийся идентификатор модуля: {unit.Id}. Идентификаторы модулей должны быть уникальными. " + $"К этому времени загружены модули {string.Join(", ", unitIds)}"); } unitIds.Add(unit.Id); if (unitUrls.Contains(unit.Url)) { throw new CourseLoadingException($"Ошибка в курсе \"{settings.Title}\" при загрузке модуля \"{unit.Title}\" из {unitDirectory.FullName}. Повторяющийся url-адрес модуля: {unit.Url}. Url-адреса модулей должны быть уникальными"); } unitUrls.Add(unit.Url); yield return(unit); slideIndex += unit.Slides.Count; } }
public CourseSettings(CourseSettings other) : this() { Title = other.Title; DefaultLanguageVersions = (Language[])other.DefaultLanguageVersions.Clone(); Preludes = (PreludeFile[])other.Preludes.Clone(); DictionaryFile = other.DictionaryFile; }
public Course LoadCourse(DirectoryInfo dir) { var courseId = dir.Name; var courseXmls = dir.GetFiles("course.xml", SearchOption.AllDirectories).ToList(); if (courseXmls.Count == 1) { dir = courseXmls[0].Directory; } else { dir = dir.HasSubdirectory("Slides") ? dir.Subdirectory("Slides") : dir; } var settings = CourseSettings.Load(dir); if (string.IsNullOrEmpty(settings.Title)) { settings.Title = GetCourseTitleFromFile(dir); } var units = LoadUnits(dir, settings).ToList(); var slides = units.SelectMany(u => u.Slides).ToList(); CheckDuplicateSlideIds(slides); AddDefaultScoringGroupIfNeeded(units, slides, settings); CalculateScoringGroupScores(units, settings); return(new Course(courseId, units, settings, dir)); }
public Course(string id, string title, Slide[] slides, InstructorNote[] instructorNotes, CourseSettings settings) { Id = id; Title = title; Slides = slides; InstructorNotes = instructorNotes; Settings = settings; }
private static IEnumerable<Func<int, Slide>> LoadUnit(DirectoryInfo unitDir, CourseSettings settings) { var unitTitle = GetTitle(unitDir); return unitDir.GetFiles() .Where(f => IsSlideFile(f.Name)) .OrderBy(f => f.Name) .Select<FileInfo, Func<int, Slide>>(f => i => LoadSlide(f, unitTitle, i, settings)); }
private static IEnumerable<Slide> LoadSlides(DirectoryInfo dir, CourseSettings settings) { var unitDirs = dir .GetDirectories() .OrderBy(d => d.Name); return unitDirs .SelectMany(info => LoadUnit(info, settings)) .Select((makeSlide, index) => makeSlide(index)); }
public Course(string id, string title, Slide[] slides, InstructorNote[] instructorNotes, CourseSettings settings, DirectoryInfo directory) { Id = id; Title = title; Slides = slides; InstructorNotes = instructorNotes; Settings = settings; Directory = directory; }
private static IEnumerable <Slide> LoadSlides(DirectoryInfo dir, CourseSettings settings) { var unitDirs = dir .GetDirectories() .OrderBy(d => d.Name); return(unitDirs .SelectMany(info => LoadUnit(info, settings)) .Select((makeSlide, index) => makeSlide(index))); }
private static void CalculateScoringGroupScores(IEnumerable <Unit> units, CourseSettings settings) { foreach (var unit in units) { foreach (var slide in unit.Slides.Where(s => s.ShouldBeSolved)) { unit.Scoring.Groups[slide.ScoringGroup].MaxNotAdditionalScore += slide.MaxScore; settings.Scoring.Groups[slide.ScoringGroup].MaxNotAdditionalScore += slide.MaxScore; } } }
public static UnitSettings Load(FileInfo file, CourseSettings courseSettings) { var unitSettings = file.DeserializeXml <UnitSettings>(); if (string.IsNullOrEmpty(unitSettings.Title)) { throw new CourseLoadingException($"Заголовок модуля не может быть пустым. Файл {file.FullName}"); } if (string.IsNullOrEmpty(unitSettings.Url)) { unitSettings.Url = unitSettings.Title.ToLatin(); } var courseScoringGroupsIds = new HashSet <string>(courseSettings.Scoring.Groups.Keys); foreach (var scoringGroup in unitSettings.Scoring.Groups.Values.ToList()) { if (!courseScoringGroupsIds.Contains(scoringGroup.Id)) { throw new CourseLoadingException( $"Неизвестная группа баллов описана в модуле: {scoringGroup.Id}. Файл {file.FullName}. " + $"Для курса определены только следующие группы баллов: {string.Join(", ", courseScoringGroupsIds)}" ); } /* By default set unit's scoring settings from course's scoring settings */ var unitScoringGroup = unitSettings.Scoring.Groups[scoringGroup.Id]; var courseScoringGroup = courseSettings.Scoring.Groups[scoringGroup.Id]; unitScoringGroup.CopySettingsFrom(courseScoringGroup); if (scoringGroup.IsMaxAdditionalScoreSpecified && (!scoringGroup.IsCanBeSetByInstructorSpecified || !scoringGroup.CanBeSetByInstructor)) { throw new CourseLoadingException( $"Модуль «{unitSettings.Title}»: чтобы выставлять дополнительные баллы в группу {scoringGroup.Id}, установите у неё атрибут set_by_instructor=\"true\" " + $"в настройках модуля (файл {file.Directory?.Name}/Unit.xml) или курса (файл Course.xml). " + $"В противном случае атрибут max_additional_score=\"{scoringGroup.MaxAdditionalScore}\" не действует" ); } if (scoringGroup.IsEnabledForEveryoneSpecified) { throw new CourseLoadingException( $"В настройках модуля «{unitSettings.Title}» для группы баллов {scoringGroup.Id} указана опция enable_for_everyone=\"{scoringGroup._enabledForEveryone}\" (файл {file.Directory?.Name}/Unit.xml). " + "Эту опцию можно указывать только в настройках всего курса (файл Course.xml)"); } } /* Copy other scoring groups and scoring settings from course settings */ unitSettings.Scoring.CopySettingsFrom(courseSettings.Scoring); return(unitSettings); }
public static UnitSettings CreateByTitle(string title, CourseSettings courseSettings) { var unitSettings = new UnitSettings { Id = title.ToDeterministicGuid(), Url = title.ToLatin(), Title = title, }; unitSettings.Scoring.CopySettingsFrom(courseSettings.Scoring); return(unitSettings); }
public static UnitSettings CreateByTitle(string title, CourseSettings courseSettings) { var unitSettings = new UnitSettings { /* We use Win1251 only for back compatibility. * In future all units will have Unit.xml with Id specified, so we will be able to switch to Encoding.UTF8 here or remove this function. */ Id = title.ToDeterministicGuid(Encoding.GetEncoding(1251)), Url = title.ToLatin(), Title = title, }; unitSettings.Scoring.CopySettingsFrom(courseSettings.Scoring); return(unitSettings); }
public Course LoadCourse(DirectoryInfo dir) { var courseId = dir.Name; dir = dir.HasSubdirectory("Slides") ? dir.Subdirectory("Slides") : dir; var settings = CourseSettings.Load(dir); var slides = LoadSlides(dir, settings).ToArray(); CheckDuplicateSlideIds(slides); var notes = LoadInstructorNotes(dir, courseId); var title = settings.Title ?? GetTitle(dir); return(new Course(courseId, title, slides, notes, settings, dir)); }
private static Slide LoadSlide(FileInfo file, string unitTitle, int slideIndex, CourseSettings settings) { try { var slideLoader = SlideLoaders .FirstOrDefault(loader => file.FullName.EndsWith(loader.Extension, StringComparison.InvariantCultureIgnoreCase)); if (slideLoader == null) throw new Exception("Unknown slide format " + file); return slideLoader.Load(file, unitTitle, slideIndex, settings); } catch (Exception e) { throw new Exception("Error loading slide " + file.FullName, e); } }
public static UnitSettings Load(FileInfo file, CourseSettings courseSettings) { var unitSettings = file.DeserializeXml <UnitSettings>(); if (string.IsNullOrEmpty(unitSettings.Title)) { throw new CourseLoadingException($"Заголовок модуля не может быть пустым. Файл {file.FullName}"); } if (string.IsNullOrEmpty(unitSettings.Url)) { unitSettings.Url = unitSettings.Title.ToLatin(); } var courseScoringGroupsIds = new HashSet <string>(courseSettings.Scoring.Groups.Keys); foreach (var scoringGroup in unitSettings.Scoring.Groups.Values.ToList()) { if (!courseScoringGroupsIds.Contains(scoringGroup.Id)) { throw new CourseLoadingException( $"Неизвестная группа баллов описана в модуле: {scoringGroup.Id}. Файл {file.FullName}. " + $"Для курса определены только следующие группы баллов: {string.Join(", ", courseScoringGroupsIds)}" ); } /* By default set unit's scoring settings from course's scoring settings */ var unitScoringGroup = unitSettings.Scoring.Groups[scoringGroup.Id]; var courseScoringGroup = courseSettings.Scoring.Groups[scoringGroup.Id]; unitScoringGroup.CopySettingsFrom(courseScoringGroup); if (scoringGroup.IsEnabledForEveryoneSpecified) { throw new CourseLoadingException( $"В настройках модуля «{unitSettings.Title}» для группы баллов {scoringGroup.Id} указана опция enable_for_everyone=\"{scoringGroup._enabledForEveryone}\" (файл {file.Directory?.Name}/Unit.xml). " + "Эту опцию можно указывать только в настройках всего курса (файл Course.xml)"); } } /* Copy other scoring groups and scoring settings from course settings */ unitSettings.Scoring.CopySettingsFrom(courseSettings.Scoring); return(unitSettings); }
public static Unit LoadUnit(DirectoryInfo unitDir, CourseSettings courseSettings, int firstSlideIndex) { var unitFile = unitDir.GetFile("Unit.xml"); var unitSettings = unitFile.Exists ? UnitSettings.Load(unitFile, courseSettings) : UnitSettings.CreateByTitle(GetUnitTitleFromFile(unitDir), courseSettings); var unit = new Unit(unitSettings, unitDir); unit.Slides = unitDir.GetFiles() .Where(f => IsSlideFile(f.Name)) .OrderBy(f => f.Name) .Select((f, internalIndex) => LoadSlide(f, unit, firstSlideIndex + internalIndex, courseSettings)) .ToList(); unit.LoadInstructorNote(); return(unit); }
private static Slide LoadSlide(FileInfo file, Unit unit, int slideIndex, CourseSettings courseSettings) { try { var slideLoader = slideLoaders .FirstOrDefault(loader => file.FullName.EndsWith(loader.Extension, StringComparison.InvariantCultureIgnoreCase)); if (slideLoader == null) { throw new CourseLoadingException($"Неизвестный формат слайда в файле {file.FullName}"); } return(slideLoader.Load(file, unit, slideIndex, courseSettings)); } catch (Exception e) { if (e.GetType().IsSubclassOf(typeof(CourseLoadingException))) { throw; } throw new CourseLoadingException($"Не могу загрузить слайд из файла {file.FullName}", e); } }
public Course LoadCourse(DirectoryInfo dir) { var courseId = dir.Name; var courseXmls = dir.GetFiles("course.xml", SearchOption.AllDirectories).ToList(); if (courseXmls.Count == 1) { dir = courseXmls[0].Directory; } else { dir = dir.HasSubdirectory("Slides") ? dir.GetSubdirectory("Slides") : dir; } var settings = CourseSettings.Load(dir); if (string.IsNullOrEmpty(settings.Title)) { try { settings.Title = GetCourseTitleFromFile(dir); } catch (Exception e) { throw new CourseLoadingException( "Не удалось прочитать настройки курса. Скорее всего, отсутствует или неправильно заполнен файл course.xml." ); } } var units = LoadUnits(dir, settings, courseId).ToList(); var slides = units.SelectMany(u => u.Slides).ToList(); CheckDuplicateSlideIds(slides); AddDefaultScoringGroupIfNeeded(units, slides, settings); CalculateScoringGroupScores(units, settings); return(new Course(courseId, units, settings, dir)); }
private static IEnumerable <Func <int, Slide> > LoadUnit(DirectoryInfo unitDir, CourseSettings settings) { var unitTitle = GetTitle(unitDir); return(unitDir.GetFiles() .Where(f => IsSlideFile(f.Name)) .OrderBy(f => f.Name) .Select <FileInfo, Func <int, Slide> >(f => i => LoadSlide(f, unitTitle, i, settings))); }
private static Slide LoadSlide(FileInfo file, string unitTitle, int slideIndex, CourseSettings settings) { try { var slideLoader = SlideLoaders .FirstOrDefault(loader => file.FullName.EndsWith(loader.Extension, StringComparison.InvariantCultureIgnoreCase)); if (slideLoader == null) { throw new Exception("Unknown slide format " + file); } return(slideLoader.Load(file, unitTitle, slideIndex, settings)); } catch (Exception e) { throw new Exception("Error loading slide " + file.FullName, e); } }
private static void AddDefaultScoringGroupIfNeeded(IEnumerable <Unit> units, IEnumerable <Slide> slides, CourseSettings settings) { if (slides.Any(s => s.ShouldBeSolved && string.IsNullOrEmpty(s.ScoringGroup))) { var defaultScoringGroup = new ScoringGroup { Id = "", Abbreviation = "Баллы", Name = "Упражнения и тесты", }; settings.Scoring.Groups.Add(defaultScoringGroup.Id, defaultScoringGroup); /* Add default scoring group to each unit */ foreach (var unit in units) { unit.Scoring.Groups.Add(defaultScoringGroup.Id, defaultScoringGroup); } } }