private async Task <StepikApiBlock> ConvertUlearnNonTextBlockIntoStepikStepBlock(SlideBlock block, StepikApiBlock lastTextBlock, string courseId, Slide slide, int lessonId, CourseExportOptions options, CourseExportResults results) { switch (block) { case AbstractExerciseBlock exerciseBlock: return(new StepikApiBlock { Name = "external-grader", Text = lastTextBlock.Text, Cost = ((ExerciseSlide)slide).Scoring.PassedTestsScore, Source = new StepikApiExternalGraderBlockSource(courseId, slide.Id, options.XQueueName, exerciseBlock.ExerciseInitialCode, stepikCSharpLanguageName) }); case ChoiceBlock choiceBlock: return(new StepikApiBlock { Name = "choice", Text = lastTextBlock.Text + $"<p><br/><b>{choiceBlock.Text.EscapeHtml()}</b></p>", Cost = choiceBlock.MaxScore, Source = new StepikApiChoiceBlockSource(choiceBlock.Items.Select(ConvertUlearnChoiceItemIntoStepikChoiceOption)) { IsMultipleChoice = choiceBlock.Multiple, PreserveOrder = !choiceBlock.Shuffle } }); case YoutubeBlock videoBlock: { var rawVideoUrl = await youtubeVideoUrlExtractor.GetVideoUrl(videoBlock.GetYoutubeUrl()).ConfigureAwait(false); var video = await client.UploadVideo(rawVideoUrl, lessonId).ConfigureAwait(false); await Task.Delay(options.PauseAfterVideoUploaded).ConfigureAwait(false); return(new StepikApiBlock { Name = "video", Video = video, }); } default: results.Error($"Unknown block type for converting into stepik step: {block.GetType().Name}, ignoring it"); return(null); } }
/* Convert ulearn's blocks and group some of them into on stepik's text block*/ private async Task <IEnumerable <StepikApiBlock> > ConvertUlearnBlocksIntoStepikBlocks(string courseId, Slide slide, IEnumerable <SlideBlock> blocks, CourseExportOptions options, int stepikLessonId, CourseExportResults results) { var stepikBlocks = new List <StepikApiBlock>(); var previousTextBlock = new StepikApiBlock { Name = "text", Text = "", }; var attachTextBlocksToInteractiveContent = slide is QuizSlide || slide is ExerciseSlide; foreach (var block in blocks) { if (block.Hide) { continue; } var isCurrentBlockText = IsCurrentBlockText(block, options); if (isCurrentBlockText) { previousTextBlock.Text += GetTextForStepikBlockFromUlearnBlock(courseId, slide, block); } else { if (!string.IsNullOrEmpty(previousTextBlock.Text) && !attachTextBlocksToInteractiveContent) { stepikBlocks.Add(previousTextBlock); previousTextBlock = new StepikApiBlock { Name = "text", Text = "", }; } var stepikBlock = await ConvertUlearnNonTextBlockIntoStepikStepBlock( block, previousTextBlock, courseId, slide, stepikLessonId, options, results ).ConfigureAwait(false); if (stepikBlock != null) { stepikBlocks.Add(stepikBlock); } } } if (!string.IsNullOrEmpty(previousTextBlock.Text) && !attachTextBlocksToInteractiveContent) { stepikBlocks.Add(previousTextBlock); } return(stepikBlocks); }
private static bool IsCurrentBlockText(SlideBlock block, CourseExportOptions options) { return(block is MarkdownBlock || block is CodeBlock || (options.VideoUploadOptions == UploadVideoToStepikOption.Iframe && block is YoutubeBlock)); }
private async Task <int> InsertSlideAsStepsInLesson(Course course, Slide slide, int stepikLessonId, int position, CourseExportOptions options, CourseExportResults results) { var stepikBlocks = (await ConvertUlearnBlocksIntoStepikBlocks(course.Id, slide, slide.Blocks, options, stepikLessonId, results).ConfigureAwait(false)).ToList(); var blocksCountToInsert = stepikBlocks.Count; await MoveStepsForSpaceEmpting(stepikLessonId, position, blocksCountToInsert).ConfigureAwait(false); foreach (var stepikBlock in stepikBlocks) { /* Stepik has no step's titles so insert slide title in each step as H1 */ stepikBlock.Text = $"<h1>{slide.Title.EscapeHtml()}</h1>" + (stepikBlock.Text ?? ""); var uploadedStep = await client.UploadStep(new StepikApiStepSource { Block = stepikBlock, Position = ++position, LessonId = stepikLessonId, Cost = stepikBlock.Cost, }).ConfigureAwait(false); if (!uploadedStep.Id.HasValue) { throw new StepikApiException("Didn't receive `step`'s ID from stepik"); } results.SlideIdToStepsIdsMap[slide.Id].Add(uploadedStep.Id.Value); } return(blocksCountToInsert); }