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