4b6d8cdc37b69427d9f005d68106fe254331f1e8
[idea/community.git] / python / educational / interactive-learning / src / com / jetbrains / edu / learning / StudyTaskManager.java
1 package com.jetbrains.edu.learning;
2
3 import com.intellij.openapi.components.*;
4 import com.intellij.openapi.project.DumbAware;
5 import com.intellij.openapi.project.Project;
6 import com.intellij.ui.JBColor;
7 import com.intellij.util.containers.hash.HashMap;
8 import com.intellij.util.xmlb.XmlSerializer;
9 import com.jetbrains.edu.EduUtils;
10 import com.jetbrains.edu.courseFormat.*;
11 import com.jetbrains.edu.learning.courseFormat.StudyStatus;
12 import com.jetbrains.edu.learning.courseFormat.UserTest;
13 import com.jetbrains.edu.oldCourseFormat.OldCourse;
14 import org.jdom.Element;
15 import org.jetbrains.annotations.NotNull;
16 import org.jetbrains.annotations.Nullable;
17
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.List;
21 import java.util.Map;
22
23 /**
24  * Implementation of class which contains all the information
25  * about study in context of current project
26  */
27
28 @State(
29   name = "StudySettings",
30   storages = {
31     @Storage(file = StoragePathMacros.PROJECT_FILE),
32     @Storage(
33       file = StoragePathMacros.PROJECT_CONFIG_DIR + "/study_project.xml",
34       scheme = StorageScheme.DIRECTORY_BASED
35     )}
36 )
37 public class StudyTaskManager implements PersistentStateComponent<Element>, DumbAware {
38   private Course myCourse;
39   private OldCourse myOldCourse;
40   public int VERSION = 2;
41   public Map<AnswerPlaceholder, StudyStatus> myStudyStatusMap = new HashMap<AnswerPlaceholder, StudyStatus>();
42   public Map<TaskFile, StudyStatus> myTaskStatusMap = new HashMap<TaskFile, StudyStatus>();
43   public Map<Task, List<UserTest>> myUserTests = new HashMap<Task, List<UserTest>>();
44   public List<String> myInvisibleFiles = new ArrayList<String>();
45
46   private StudyTaskManager() {
47   }
48
49   public void setCourse(final Course course) {
50     myCourse = course;
51   }
52
53   @Nullable
54   public Course getCourse() {
55     return myCourse;
56   }
57
58   public void setStatus(AnswerPlaceholder placeholder, StudyStatus status) {
59     if (myStudyStatusMap == null) {
60       myStudyStatusMap = new HashMap<AnswerPlaceholder, StudyStatus>();
61     }
62     myStudyStatusMap.put(placeholder, status);
63   }
64
65   public void addUserTest(@NotNull final Task task, UserTest userTest) {
66     List<UserTest> userTests = myUserTests.get(task);
67     if (userTests == null) {
68       userTests = new ArrayList<UserTest>();
69       myUserTests.put(task, userTests);
70     }
71     userTests.add(userTest);
72   }
73
74   public void setUserTests(@NotNull final Task task, @NotNull final List<UserTest> userTests) {
75     myUserTests.put(task, userTests);
76   }
77
78   @NotNull
79   public List<UserTest> getUserTests(@NotNull final Task task) {
80     final List<UserTest> userTests = myUserTests.get(task);
81     return userTests != null ? userTests : Collections.<UserTest>emptyList();
82   }
83
84   public void removeUserTest(@NotNull final Task task, @NotNull final UserTest userTest) {
85     final List<UserTest> userTests = myUserTests.get(task);
86     if (userTests != null) {
87       userTests.remove(userTest);
88     }
89   }
90
91
92   public void setStatus(Task task, StudyStatus status) {
93     for (TaskFile taskFile : task.getTaskFiles().values()) {
94       setStatus(taskFile, status);
95     }
96   }
97
98   public void setStatus(TaskFile file, StudyStatus status) {
99     if (file.getAnswerPlaceholders().isEmpty()) {
100       if (myTaskStatusMap == null) {
101         myTaskStatusMap = new HashMap<TaskFile, StudyStatus>();
102       }
103       myTaskStatusMap.put(file, status);
104     }
105     for (AnswerPlaceholder answerPlaceholder : file.getAnswerPlaceholders()) {
106       setStatus(answerPlaceholder, status);
107     }
108   }
109
110   public StudyStatus getStatus(AnswerPlaceholder placeholder) {
111     StudyStatus status = myStudyStatusMap.get(placeholder);
112     if (status == null) {
113       status = StudyStatus.Unchecked;
114       myStudyStatusMap.put(placeholder, status);
115     }
116     return status;
117   }
118
119
120   public StudyStatus getStatus(@NotNull final Lesson lesson) {
121     for (Task task : lesson.getTaskList()) {
122       StudyStatus taskStatus = getStatus(task);
123       if (taskStatus == StudyStatus.Unchecked || taskStatus == StudyStatus.Failed) {
124         return StudyStatus.Unchecked;
125       }
126     }
127     return StudyStatus.Solved;
128   }
129
130   public StudyStatus getStatus(@NotNull final Task task) {
131     for (TaskFile taskFile : task.getTaskFiles().values()) {
132       StudyStatus taskFileStatus = getStatus(taskFile);
133       if (taskFileStatus == StudyStatus.Unchecked) {
134         return StudyStatus.Unchecked;
135       }
136       if (taskFileStatus == StudyStatus.Failed) {
137         return StudyStatus.Failed;
138       }
139     }
140     return StudyStatus.Solved;
141   }
142
143   private StudyStatus getStatus(@NotNull final TaskFile file) {
144     if (file.getAnswerPlaceholders().isEmpty()) {
145       if (myTaskStatusMap == null) return StudyStatus.Solved;
146       return myTaskStatusMap.get(file);
147
148     }
149     for (AnswerPlaceholder answerPlaceholder : file.getAnswerPlaceholders()) {
150       StudyStatus placeholderStatus = getStatus(answerPlaceholder);
151       if (placeholderStatus == StudyStatus.Failed) {
152         return StudyStatus.Failed;
153       }
154       if (placeholderStatus == StudyStatus.Unchecked) {
155         return StudyStatus.Unchecked;
156       }
157     }
158     return StudyStatus.Solved;
159   }
160
161
162   public JBColor getColor(@NotNull final AnswerPlaceholder placeholder) {
163     final StudyStatus status = getStatus(placeholder);
164     if (status == StudyStatus.Solved) {
165       return JBColor.GREEN;
166     }
167     if (status == StudyStatus.Failed) {
168       return JBColor.RED;
169     }
170     return JBColor.BLUE;
171   }
172
173   public boolean hasFailedAnswerPlaceholders(@NotNull final TaskFile taskFile) {
174     return taskFile.getAnswerPlaceholders().size() > 0 && getStatus(taskFile) == StudyStatus.Failed;
175   }
176
177   @Nullable
178   @Override
179   public Element getState() {
180     Element el = new Element("taskManager");
181     if (myCourse != null) {
182       Element courseElement = new Element(MAIN_ELEMENT);
183       XmlSerializer.serializeInto(this, courseElement);
184       el.addContent(courseElement);
185     }
186     return el;
187   }
188
189   @Override
190   public void loadState(Element state) {
191     final Element mainElement = state.getChild(MAIN_ELEMENT);
192     if (mainElement != null) {
193       final StudyTaskManager taskManager = XmlSerializer.deserialize(mainElement, StudyTaskManager.class);
194       if (taskManager != null) {
195         myCourse = taskManager.myCourse;
196         myUserTests = taskManager.myUserTests;
197         myInvisibleFiles = taskManager.myInvisibleFiles;
198         myTaskStatusMap = taskManager.myTaskStatusMap;
199         myStudyStatusMap = taskManager.myStudyStatusMap;
200       }
201     }
202     final Element oldCourseElement = state.getChild(COURSE_ELEMENT);
203     if (oldCourseElement != null) {
204       myOldCourse = XmlSerializer.deserialize(oldCourseElement, OldCourse.class);
205       if (myOldCourse != null) {
206         myCourse = EduUtils.transformOldCourse(myOldCourse);
207         myOldCourse = null;
208       }
209     }
210     if (myCourse != null) {
211       myCourse.initCourse(true);
212     }
213   }
214
215   public static final String COURSE_ELEMENT = "courseElement";
216   public static final String MAIN_ELEMENT = "StudyTaskManager";
217
218   public OldCourse getOldCourse() {
219     return myOldCourse;
220   }
221
222   public void setOldCourse(OldCourse oldCourse) {
223     myOldCourse = oldCourse;
224   }
225
226   public static StudyTaskManager getInstance(@NotNull final Project project) {
227     return ServiceManager.getService(project, StudyTaskManager.class);
228   }
229
230   public void addInvisibleFiles(String filePath) {
231     myInvisibleFiles.add(filePath);
232   }
233
234   public boolean isInvisibleFile(String path) {
235     return myInvisibleFiles.contains(path);
236   }
237 }