示例#1
0
 public Course(string id, List <Unit> units, CourseSettings settings, DirectoryInfo directory)
 {
     Id        = id;
     Units     = units;
     Settings  = settings;
     Directory = directory;
 }
示例#2
0
        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;
            }
        }
示例#3
0
 public CourseSettings(CourseSettings other) : this()
 {
     Title = other.Title;
     DefaultLanguageVersions = (Language[])other.DefaultLanguageVersions.Clone();
     Preludes       = (PreludeFile[])other.Preludes.Clone();
     DictionaryFile = other.DictionaryFile;
 }
示例#4
0
        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));
        }
示例#5
0
文件: Course.cs 项目: fakefeik/uLearn
		public Course(string id, string title, Slide[] slides, InstructorNote[] instructorNotes, CourseSettings settings)
		{
			Id = id;
			Title = title;
			Slides = slides;
			InstructorNotes = instructorNotes;
			Settings = settings;
		}
示例#6
0
		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));
		}
示例#7
0
		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));
		}
示例#8
0
		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;
		}
示例#9
0
 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;
 }
示例#10
0
        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)));
        }
示例#11
0
 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;
         }
     }
 }
示例#12
0
        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);
        }
示例#13
0
        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);
        }
示例#14
0
        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);
        }
示例#15
0
        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));
        }
示例#16
0
		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);
			}
		}
示例#17
0
        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);
        }
示例#18
0
        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);
        }
示例#19
0
 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);
     }
 }
示例#20
0
        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));
        }
示例#21
0
        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)));
        }
示例#22
0
 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);
     }
 }
示例#23
0
        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);
                }
            }
        }