33c626a05bcb5e191afc515167ef0d59d9378412
[idea/community.git] / python / educational-core / student / src / com / jetbrains / edu / learning / checker / StudyCheckUtils.java
1 package com.jetbrains.edu.learning.checker;
2
3 import com.intellij.openapi.application.ApplicationManager;
4 import com.intellij.openapi.diagnostic.Logger;
5 import com.intellij.openapi.editor.Document;
6 import com.intellij.openapi.editor.Editor;
7 import com.intellij.openapi.fileEditor.FileDocumentManager;
8 import com.intellij.openapi.fileEditor.FileEditor;
9 import com.intellij.openapi.fileEditor.FileEditorManager;
10 import com.intellij.openapi.progress.ProgressIndicator;
11 import com.intellij.openapi.progress.TaskInfo;
12 import com.intellij.openapi.project.Project;
13 import com.intellij.openapi.ui.popup.Balloon;
14 import com.intellij.openapi.ui.popup.BalloonBuilder;
15 import com.intellij.openapi.ui.popup.JBPopupFactory;
16 import com.intellij.openapi.util.Pair;
17 import com.intellij.openapi.vfs.VirtualFile;
18 import com.intellij.openapi.wm.IdeFocusManager;
19 import com.intellij.openapi.wm.IdeFrame;
20 import com.intellij.openapi.wm.WindowManager;
21 import com.intellij.openapi.wm.ex.StatusBarEx;
22 import com.intellij.openapi.wm.ex.WindowManagerEx;
23 import com.jetbrains.edu.learning.core.EduDocumentListener;
24 import com.jetbrains.edu.learning.core.EduNames;
25 import com.jetbrains.edu.learning.core.EduUtils;
26 import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
27 import com.jetbrains.edu.learning.courseFormat.Task;
28 import com.jetbrains.edu.learning.courseFormat.TaskFile;
29 import com.jetbrains.edu.learning.StudyState;
30 import com.jetbrains.edu.learning.StudyTaskManager;
31 import com.jetbrains.edu.learning.StudyUtils;
32 import com.jetbrains.edu.learning.editor.StudyEditor;
33 import com.jetbrains.edu.learning.navigation.StudyNavigator;
34 import org.jetbrains.annotations.NotNull;
35
36 import java.awt.*;
37 import java.io.IOException;
38 import java.util.List;
39 import java.util.Map;
40
41 public class StudyCheckUtils {
42   private static final Logger LOG = Logger.getInstance(StudyCheckUtils.class);
43
44   private StudyCheckUtils() {
45   }
46
47   public static void drawAllPlaceholders(@NotNull final Project project, @NotNull final Task task, @NotNull final VirtualFile taskDir) {
48     for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
49       String name = entry.getKey();
50       TaskFile taskFile = entry.getValue();
51       VirtualFile virtualFile = taskDir.findChild(name);
52       if (virtualFile == null) {
53         continue;
54       }
55       FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
56       if (fileEditor instanceof StudyEditor) {
57         StudyEditor studyEditor = (StudyEditor)fileEditor;
58         StudyUtils.drawAllWindows(studyEditor.getEditor(), taskFile);
59       }
60     }
61   }
62
63   public static void navigateToFailedPlaceholder(@NotNull final StudyState studyState,
64                                                   @NotNull final Task task,
65                                                   @NotNull final VirtualFile taskDir,
66                                                   @NotNull final Project project) {
67     TaskFile selectedTaskFile = studyState.getTaskFile();
68     Editor editor = studyState.getEditor();
69     TaskFile taskFileToNavigate = selectedTaskFile;
70     VirtualFile fileToNavigate = studyState.getVirtualFile();
71     final StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
72     if (!taskManager.hasFailedAnswerPlaceholders(selectedTaskFile)) {
73       for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
74         String name = entry.getKey();
75         TaskFile taskFile = entry.getValue();
76         if (taskManager.hasFailedAnswerPlaceholders(taskFile)) {
77           taskFileToNavigate = taskFile;
78           VirtualFile virtualFile = taskDir.findChild(name);
79           if (virtualFile == null) {
80             continue;
81           }
82           FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
83           if (fileEditor instanceof StudyEditor) {
84             StudyEditor studyEditor = (StudyEditor)fileEditor;
85             editor = studyEditor.getEditor();
86           }
87           fileToNavigate = virtualFile;
88           break;
89         }
90       }
91     }
92     if (fileToNavigate != null) {
93       FileEditorManager.getInstance(project).openFile(fileToNavigate, true);
94     }
95     final Editor editorToNavigate = editor;
96     ApplicationManager.getApplication().invokeLater(
97       () -> IdeFocusManager.getInstance(project).requestFocus(editorToNavigate.getContentComponent(), true));
98
99     StudyNavigator.navigateToFirstFailedAnswerPlaceholder(editor, taskFileToNavigate);
100   }
101
102
103   public static void showTestResultPopUp(final String text, Color color, @NotNull final Project project) {
104     BalloonBuilder balloonBuilder =
105       JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(text, null, color, null);
106     final Balloon balloon = balloonBuilder.createBalloon();
107     StudyUtils.showCheckPopUp(project, balloon);
108   }
109
110
111   public static void runSmartTestProcess(@NotNull final VirtualFile taskDir,
112                                      @NotNull final StudyTestRunner testRunner,
113                                      final String taskFileName,
114                                      @NotNull final TaskFile taskFile,
115                                      @NotNull final Project project) {
116     final TaskFile answerTaskFile = new TaskFile();
117     answerTaskFile.name = taskFileName;
118     final VirtualFile virtualFile = taskDir.findChild(taskFileName);
119     if (virtualFile == null) {
120       return;
121     }
122     final VirtualFile answerFile = getCopyWithAnswers(taskDir, virtualFile, taskFile, answerTaskFile);
123     for (final AnswerPlaceholder answerPlaceholder : answerTaskFile.getAnswerPlaceholders()) {
124       final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
125       if (document == null) {
126         continue;
127       }
128       if (!answerPlaceholder.isValid(document)) {
129         continue;
130       }
131       StudySmartChecker.smartCheck(answerPlaceholder, project, answerFile, answerTaskFile, taskFile, testRunner,
132                                    virtualFile, document);
133     }
134     StudyUtils.deleteFile(answerFile);
135   }
136
137
138
139   private static VirtualFile getCopyWithAnswers(@NotNull final VirtualFile taskDir,
140                                          @NotNull final VirtualFile file,
141                                          @NotNull final TaskFile source,
142                                          @NotNull final TaskFile target) {
143     VirtualFile copy = null;
144     try {
145
146       copy = file.copy(taskDir, taskDir, file.getNameWithoutExtension() + EduNames.ANSWERS_POSTFIX + "." + file.getExtension());
147       final FileDocumentManager documentManager = FileDocumentManager.getInstance();
148       final Document document = documentManager.getDocument(copy);
149       if (document != null) {
150         TaskFile.copy(source, target);
151         EduDocumentListener listener = new EduDocumentListener(target);
152         document.addDocumentListener(listener);
153         for (AnswerPlaceholder answerPlaceholder : target.getAnswerPlaceholders()) {
154           if (!answerPlaceholder.isValid(document)) {
155             continue;
156           }
157           final int start = answerPlaceholder.getRealStartOffset(document);
158           final int end = start + answerPlaceholder.getRealLength();
159           final String text = answerPlaceholder.getPossibleAnswer();
160           document.replaceString(start, end, text);
161         }
162         ApplicationManager.getApplication().runWriteAction(() -> {
163           documentManager.saveDocument(document);
164         });
165       }
166     }
167     catch (IOException e) {
168       LOG.error(e);
169     }
170     return copy;
171   }
172
173
174   public static boolean hasBackgroundProcesses(@NotNull Project project) {
175     final IdeFrame frame = ((WindowManagerEx)WindowManager.getInstance()).findFrameFor(project);
176     final StatusBarEx statusBar = frame == null ? null : (StatusBarEx)frame.getStatusBar();
177     if (statusBar != null) {
178       final List<Pair<TaskInfo, ProgressIndicator>> processes = statusBar.getBackgroundProcesses();
179       if (!processes.isEmpty()) return true;
180     }
181     return false;
182   }
183
184
185   public static void flushWindows(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
186     for (Map.Entry<String, TaskFile> entry : task.getTaskFiles().entrySet()) {
187       String name = entry.getKey();
188       TaskFile taskFile = entry.getValue();
189       VirtualFile virtualFile = taskDir.findChild(name);
190       if (virtualFile == null) {
191         continue;
192       }
193       EduUtils.flushWindows(taskFile, virtualFile, true);
194     }
195   }
196 }