1 package com.jetbrains.edu.learning.stepic;
3 import com.google.gson.annotations.Expose;
4 import com.intellij.openapi.application.ApplicationManager;
5 import com.intellij.openapi.diagnostic.Logger;
6 import com.intellij.openapi.project.Project;
7 import com.intellij.openapi.util.Pair;
8 import com.intellij.openapi.util.io.FileUtil;
9 import com.intellij.openapi.vfs.VirtualFile;
10 import com.jetbrains.edu.learning.core.EduNames;
11 import com.jetbrains.edu.learning.core.EduUtils;
12 import com.jetbrains.edu.learning.courseFormat.Course;
13 import com.jetbrains.edu.learning.courseFormat.Lesson;
14 import com.jetbrains.edu.learning.courseFormat.Task;
15 import com.jetbrains.edu.learning.courseFormat.TaskFile;
16 import org.apache.commons.codec.binary.Base64;
17 import org.jetbrains.annotations.NotNull;
18 import org.jetbrains.annotations.Nullable;
20 import java.io.IOException;
21 import java.io.InputStream;
24 public class StepicWrappers {
25 private static final Logger LOG = Logger.getInstance(StepOptions.class);
27 static class StepContainer {
28 List<StepSource> steps;
31 public static class Step {
32 @Expose StepOptions options;
34 @Expose String name = "pycharm";
35 @Expose StepOptions source;
37 public static Step fromTask(Project project, @NotNull final Task task) {
38 final Step step = new Step();
39 step.text = task.getTaskText(project);
40 step.source = StepOptions.fromTask(project, task);
45 public static class StepOptions {
46 @Expose List<TestFileWrapper> test;
48 @Expose List<TaskFile> files;
50 @Expose List<List<String>> samples;
51 @Expose Integer executionMemoryLimit;
52 @Expose Integer executionTimeLimit;
53 @Expose CodeTemplatesWrapper codeTemplates;
55 public static StepOptions fromTask(final Project project, @NotNull final Task task) {
56 final StepOptions source = new StepOptions();
57 setTests(task, source, project);
58 source.files = new ArrayList<TaskFile>();
59 source.title = task.getName();
60 for (final Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
61 ApplicationManager.getApplication().runWriteAction(() -> {
62 final VirtualFile taskDir = task.getTaskDir(project);
63 assert taskDir != null;
64 VirtualFile ideaDir = project.getBaseDir().findChild(".idea");
65 assert ideaDir != null;
66 String stepic = "stepic";
67 VirtualFile stepicDir = ideaDir.findChild(stepic);
68 if (stepicDir == null) {
70 stepicDir = ideaDir.createChildDirectory(StepicWrappers.class, stepic);
72 catch (IOException e) {
73 LOG.info("Failed to create idea/stepic directory", e);
76 if (stepicDir == null) {
79 String name = entry.getKey();
80 VirtualFile answerFile = taskDir.findChild(name);
81 Pair<VirtualFile, TaskFile> pair = EduUtils.createStudentFile(StepicWrappers.class, project, answerFile, stepicDir, null);
85 VirtualFile virtualFile = pair.getFirst();
86 TaskFile taskFile = pair.getSecond();
88 InputStream stream = virtualFile.getInputStream();
90 EduUtils.isImage(name) ? Base64.encodeBase64URLSafeString(FileUtil.loadBytes(stream)) : FileUtil.loadTextAndClose(stream);
92 catch (IOException e) {
93 LOG.error("Can't find file " + virtualFile.getPath());
95 source.files.add(taskFile);
101 private static void setTests(@NotNull final Task task, @NotNull final StepOptions source, @NotNull final Project project) {
102 final Map<String, String> testsText = task.getTestsText();
103 if (testsText.isEmpty()) {
104 ApplicationManager.getApplication().runReadAction(() -> {
105 source.test = Collections.singletonList(new TestFileWrapper(EduNames.TESTS_FILE, task.getTestsText(project)));
109 source.test = new ArrayList<TestFileWrapper>();
110 for (Map.Entry<String, String> entry : testsText.entrySet()) {
111 source.test.add(new TestFileWrapper(entry.getKey(), entry.getValue()));
117 static class CodeTemplatesWrapper {
122 public String getTemplateForLanguage(@NotNull final String langauge) {
123 if (langauge.equals(EduAdaptiveStepicConnector.PYTHON27)) {
127 if (langauge.equals(EduAdaptiveStepicConnector.PYTHON3)) {
135 static class CoursesContainer {
136 public List<CourseInfo> courses;
140 static class StepSourceWrapper {
142 StepSource stepSource;
144 public StepSourceWrapper(Project project, Task task, int lessonId) {
145 stepSource = new StepSource(project, task, lessonId);
149 static class CourseWrapper {
152 public CourseWrapper(Course course) {
153 this.course = new CourseInfo();
154 this.course.setName(course.getName());
155 this.course.setDescription(course.getDescription());
156 this.course.setAuthors(course.getAuthors());
160 static class LessonWrapper {
163 public LessonWrapper(Lesson lesson) {
164 this.lesson = new Lesson();
165 this.lesson.setName(lesson.getName());
166 this.lesson.setId(lesson.getId());
167 this.lesson.steps = new ArrayList<Integer>();
171 static class LessonContainer {
172 List<Lesson> lessons;
175 static class StepSource {
177 @Expose int position = 0;
178 @Expose int lesson = 0;
181 public StepSource(Project project, Task task, int lesson) {
182 this.lesson = lesson;
183 position = task.getIndex();
184 block = Step.fromTask(project, task);
188 static class TestFileWrapper {
189 @Expose public final String name;
190 @Expose public final String text;
192 public TestFileWrapper(String name, String text) {
198 static class Section {
206 static class SectionWrapper {
210 static class SectionContainer {
211 List<Section> sections;
212 List<Lesson> lessons;
222 List<Integer> assignments;
225 static class UnitContainer {
230 static class UnitWrapper {
234 static class AttemptWrapper {
235 static class Attempt {
236 public Attempt(int step) {
244 public AttemptWrapper(int step) {
245 attempt = new Attempt(step);
251 static class AttemptToPostWrapper {
252 static class Attempt {
261 public Attempt(int step) {
266 public AttemptToPostWrapper(int step) {
267 attempt = new Attempt(step);
273 static class AttemptContainer {
274 List<AttemptWrapper.Attempt> attempts;
277 static class SolutionFile {
281 public SolutionFile(String name, String text) {
287 static class AuthorWrapper {
288 List<StepicUser> users;
291 static class SubmissionWrapper {
292 Submission submission;
295 public SubmissionWrapper(int attempt, String score, ArrayList<SolutionFile> files) {
296 submission = new Submission(score, attempt, files);
299 static class Submission {
301 private final Reply reply;
303 public Submission(String score, int attempt, ArrayList<SolutionFile> files) {
304 reply = new Reply(files, score);
305 this.attempt = attempt;
310 List<SolutionFile> solution;
312 public Reply(ArrayList<SolutionFile> files, String score) {
320 static class UserWrapper {
323 public UserWrapper(String user, String password) {
324 this.user = new StepicUser(user, password);
328 static class RecommendationReaction {
333 public RecommendationReaction(int reaction, String user, String lesson) {
334 this.reaction = reaction;
336 this.lesson = lesson;
340 static class RecommendationReactionWrapper {
341 RecommendationReaction recommendationReaction;
343 public RecommendationReactionWrapper(RecommendationReaction recommendationReaction) {
344 this.recommendationReaction = recommendationReaction;
348 static class RecommendationWrapper {
349 Recommendation[] recommendations;
352 static class Recommendation {
358 static class SubmissionToPostWrapper {
359 Submission submission;
361 public SubmissionToPostWrapper(@NotNull String attemptId, @NotNull String language, @NotNull String code) {
362 submission = new Submission(attemptId, new Submission.Reply(language, code));
365 static class Submission {
369 public Submission(String attempt, Reply reply) {
370 this.attempt = attempt;
378 public Reply(String language, String code) {
379 this.language = language;
386 static class ResultSubmissionWrapper {
387 ResultSubmission[] submissions;
389 static class ResultSubmission {
396 static class AssignmentsWrapper {
397 List<Assignment> assignments;
400 static class Assignment {
405 static class ViewsWrapper {
408 public ViewsWrapper(final int assignment, final int step) {
409 this.view = new View(assignment, step);
417 public View(int assignment, int step) {
418 this.assignment = assignment;
423 static class Enrollment {
426 public Enrollment(String courseId) {
431 static class EnrollmentWrapper {
432 Enrollment enrollment;
434 public EnrollmentWrapper(@NotNull final String courseId) {
435 enrollment = new Enrollment(courseId);