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