mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
remote check (EDU-882)
This commit is contained in:
@@ -55,6 +55,7 @@
|
||||
<action id="Edu.NewScratchFile" class="com.intellij.ide.scratch.ScratchFileActions$NewFileAction" text="New Scratch File...">
|
||||
<add-to-group group-id="FileOpenGroup" relative-to-action="OpenFile" anchor="before"/>
|
||||
</action>
|
||||
<action id="Edu.Check" class="com.jetbrains.edu.learning.actions.StudyCheckAction"/>
|
||||
<action id="PrevWindowAction" class="com.jetbrains.edu.learning.actions.StudyPrevWindowAction" text="Previous Answer Placeholder"
|
||||
description="Navigate to the previous answer placeholder">
|
||||
</action>
|
||||
|
||||
+71
-5
@@ -1,5 +1,6 @@
|
||||
package com.jetbrains.edu.learning.actions;
|
||||
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.KeyboardShortcut;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
@@ -8,25 +9,37 @@ import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.progress.PerformInBackgroundOption;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.edu.learning.checker.StudyCheckListener;
|
||||
import com.jetbrains.edu.learning.StudySettings;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.checker.StudyCheckListener;
|
||||
import com.jetbrains.edu.learning.checker.StudyCheckResult;
|
||||
import com.jetbrains.edu.learning.checker.StudyCheckUtils;
|
||||
import com.jetbrains.edu.learning.checker.StudyTaskChecker;
|
||||
import com.jetbrains.edu.learning.courseFormat.RemoteCourse;
|
||||
import com.jetbrains.edu.learning.courseFormat.StudyStatus;
|
||||
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
|
||||
import com.jetbrains.edu.learning.courseFormat.tasks.TheoryTask;
|
||||
import com.jetbrains.edu.learning.editor.StudyEditor;
|
||||
import com.jetbrains.edu.learning.statistics.EduUsagesCollector;
|
||||
import com.jetbrains.edu.learning.stepic.StepicUser;
|
||||
import icons.EducationalCoreIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public abstract class StudyCheckAction extends StudyActionWithShortcut {
|
||||
public class StudyCheckAction extends StudyActionWithShortcut {
|
||||
public static final String SHORTCUT = "ctrl alt pressed ENTER";
|
||||
private static final String ACTION_ID = "Edu.Check";
|
||||
private static final String TEXT = "Check Task";
|
||||
public static final String FAILED_CHECK_LAUNCH = "Failed to launch checking";
|
||||
|
||||
protected final Ref<Boolean> myCheckInProgress = new Ref<>(false);
|
||||
|
||||
@@ -40,10 +53,9 @@ public abstract class StudyCheckAction extends StudyActionWithShortcut {
|
||||
return text + "(" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")";
|
||||
}
|
||||
|
||||
public abstract void check(@NotNull final Project project);
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
EduUsagesCollector.taskChecked();
|
||||
Project project = e.getProject();
|
||||
if (project == null) {
|
||||
return;
|
||||
@@ -69,7 +81,55 @@ public abstract class StudyCheckAction extends StudyActionWithShortcut {
|
||||
for (StudyCheckListener listener : Extensions.getExtensions(StudyCheckListener.EP_NAME)) {
|
||||
listener.beforeCheck(project, task);
|
||||
}
|
||||
check(project);
|
||||
StudyTaskChecker checker = task.getChecker(project);
|
||||
boolean isRemote = task.getLesson().getCourse() instanceof RemoteCourse;
|
||||
ProgressManager.getInstance()
|
||||
.run(new com.intellij.openapi.progress.Task.Backgroundable(project, "Checking Task", true, PerformInBackgroundOption.DEAF) {
|
||||
private StudyCheckResult myResult;
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
String message = myResult.getMessage();
|
||||
StudyStatus status = myResult.getStatus();
|
||||
task.setStatus(status);
|
||||
switch (status) {
|
||||
case Failed:
|
||||
checker.onTaskFailed(message);
|
||||
break;
|
||||
case Solved:
|
||||
checker.onTaskSolved(message);
|
||||
break;
|
||||
default:
|
||||
StudyCheckUtils.showTestResultPopUp(message, MessageType.WARNING.getPopupBackground(), project);
|
||||
}
|
||||
StudyUtils.updateToolWindows(myProject);
|
||||
ProjectView.getInstance(myProject).refresh();
|
||||
|
||||
for (StudyCheckListener listener : StudyCheckListener.EP_NAME.getExtensions()) {
|
||||
listener.afterCheck(project, task);
|
||||
}
|
||||
checker.clearState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
checker.clearState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
indicator.setIndeterminate(true);
|
||||
myResult = isRemote ? checkOnRemote() : checker.check();
|
||||
}
|
||||
|
||||
private StudyCheckResult checkOnRemote() {
|
||||
final StepicUser user = StudySettings.getInstance().getUser();
|
||||
if (user == null) {
|
||||
return new StudyCheckResult(StudyStatus.Unchecked, "Failed to launch checking: you're not authorized");
|
||||
}
|
||||
return checker.checkOnRemote(user);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,6 +159,12 @@ public abstract class StudyCheckAction extends StudyActionWithShortcut {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getActionId() {
|
||||
return ACTION_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getShortcuts() {
|
||||
return new String[]{SHORTCUT};
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.jetbrains.edu.learning.checker;
|
||||
|
||||
import com.jetbrains.edu.learning.courseFormat.StudyStatus;
|
||||
|
||||
public class StudyCheckResult {
|
||||
private StudyStatus myStatus;
|
||||
private String myMessage;
|
||||
|
||||
public StudyCheckResult(StudyStatus status, String message) {
|
||||
myStatus = status;
|
||||
myMessage = message;
|
||||
}
|
||||
|
||||
public StudyStatus getStatus() {
|
||||
return myStatus;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return myMessage;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,9 @@ package com.jetbrains.edu.learning.checker;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.jetbrains.edu.learning.courseFormat.StudyStatus;
|
||||
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
|
||||
import com.jetbrains.edu.learning.stepic.StepicUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class StudyTaskChecker<T extends Task> {
|
||||
@@ -24,4 +26,16 @@ public class StudyTaskChecker<T extends Task> {
|
||||
ApplicationManager.getApplication()
|
||||
.invokeLater(() -> StudyCheckUtils.showTestResultPopUp(message, MessageType.ERROR.getPopupBackground(), myProject));
|
||||
}
|
||||
|
||||
public StudyCheckResult check() {
|
||||
return new StudyCheckResult(StudyStatus.Unchecked, "Check for " + myTask.getTaskType() + " task isn't available");
|
||||
}
|
||||
|
||||
public StudyCheckResult checkOnRemote(@NotNull StepicUser user) {
|
||||
return new StudyCheckResult(StudyStatus.Unchecked, "Remote check for " + myTask.getTaskType() + " task isn't available");
|
||||
}
|
||||
|
||||
public void clearState() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -4,8 +4,11 @@ import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.checker.StudyCheckResult;
|
||||
import com.jetbrains.edu.learning.checker.StudyTaskChecker;
|
||||
import com.jetbrains.edu.learning.editor.StudyChoiceVariantsPanel;
|
||||
import com.jetbrains.edu.learning.stepic.EduAdaptiveStepicConnector;
|
||||
import com.jetbrains.edu.learning.stepic.StepicUser;
|
||||
import com.jetbrains.edu.learning.ui.StudyToolWindow;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -57,6 +60,11 @@ public class ChoiceTask extends Task {
|
||||
@Override
|
||||
public StudyTaskChecker getChecker(@NotNull Project project) {
|
||||
return new StudyTaskChecker<ChoiceTask>(this, project) {
|
||||
@Override
|
||||
public StudyCheckResult checkOnRemote(@NotNull StepicUser user) {
|
||||
return EduAdaptiveStepicConnector.checkChoiceTask(myProject, myTask, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskFailed(@NotNull String message) {
|
||||
super.onTaskFailed(message);
|
||||
|
||||
+8
@@ -1,8 +1,11 @@
|
||||
package com.jetbrains.edu.learning.courseFormat.tasks;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.jetbrains.edu.learning.checker.StudyCheckResult;
|
||||
import com.jetbrains.edu.learning.checker.StudyCheckUtils;
|
||||
import com.jetbrains.edu.learning.checker.StudyTaskChecker;
|
||||
import com.jetbrains.edu.learning.stepic.EduAdaptiveStepicConnector;
|
||||
import com.jetbrains.edu.learning.stepic.StepicUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CodeTask extends Task {
|
||||
@@ -26,6 +29,11 @@ public class CodeTask extends Task {
|
||||
super.onTaskFailed("Wrong solution");
|
||||
StudyCheckUtils.showTestResultsToolWindow(myProject, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StudyCheckResult checkOnRemote(@NotNull StepicUser user) {
|
||||
return EduAdaptiveStepicConnector.checkCodeTask(myProject, myTask, user);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+24
@@ -1,5 +1,10 @@
|
||||
package com.jetbrains.edu.learning.courseFormat.tasks;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.jetbrains.edu.learning.checker.StudyCheckResult;
|
||||
import com.jetbrains.edu.learning.checker.StudyTaskChecker;
|
||||
import com.jetbrains.edu.learning.courseFormat.StudyStatus;
|
||||
import com.jetbrains.edu.learning.stepic.StepicUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class TheoryTask extends Task {
|
||||
@@ -14,4 +19,23 @@ public class TheoryTask extends Task {
|
||||
public String getTaskType() {
|
||||
return "theory";
|
||||
}
|
||||
|
||||
@Override
|
||||
public StudyTaskChecker getChecker(@NotNull Project project) {
|
||||
return new StudyTaskChecker<TheoryTask>(this, project) {
|
||||
@Override
|
||||
public void onTaskSolved(@NotNull String message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public StudyCheckResult check() {
|
||||
return new StudyCheckResult(StudyStatus.Solved, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public StudyCheckResult checkOnRemote(@NotNull StepicUser user) {
|
||||
return new StudyCheckResult(StudyStatus.Solved, "");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+15
-16
@@ -13,13 +13,14 @@ import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.jetbrains.edu.learning.StudySettings;
|
||||
import com.jetbrains.edu.learning.StudyTaskManager;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.actions.StudyCheckAction;
|
||||
import com.jetbrains.edu.learning.checker.StudyCheckResult;
|
||||
import com.jetbrains.edu.learning.core.EduNames;
|
||||
import com.jetbrains.edu.learning.courseFormat.*;
|
||||
import com.jetbrains.edu.learning.courseFormat.tasks.ChoiceTask;
|
||||
@@ -475,8 +476,8 @@ public class EduAdaptiveStepicConnector {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Pair<Boolean, String> checkChoiceTask(@NotNull Project project, @NotNull ChoiceTask task, @NotNull StepicUser user) {
|
||||
if (task.getSelectedVariants().isEmpty()) return Pair.create(null, "No variants selected");
|
||||
public static StudyCheckResult checkChoiceTask(@NotNull Project project, @NotNull ChoiceTask task, @NotNull StepicUser user) {
|
||||
if (task.getSelectedVariants().isEmpty()) return new StudyCheckResult(StudyStatus.Failed, "No variants selected");
|
||||
final StepicWrappers.AdaptiveAttemptWrapper.Attempt attempt = getAttemptForStep(task.getStepId(), user.getId());
|
||||
|
||||
if (attempt != null) {
|
||||
@@ -484,12 +485,11 @@ public class EduAdaptiveStepicConnector {
|
||||
|
||||
final boolean isActiveAttempt = task.getSelectedVariants().stream()
|
||||
.allMatch(index -> attempt.dataset.options.get(index).equals(task.getChoiceVariants().get(index)));
|
||||
if (!isActiveAttempt) return Pair.create(false, "Your solution is out of date. Please try again");
|
||||
if (!isActiveAttempt) return new StudyCheckResult(StudyStatus.Failed, "Your solution is out of date. Please try again");
|
||||
final StepicWrappers.SubmissionToPostWrapper wrapper = new StepicWrappers.SubmissionToPostWrapper(String.valueOf(attemptId),
|
||||
createChoiceTaskAnswerArray(task));
|
||||
final Pair<Boolean, String> pair = doAdaptiveCheck(wrapper, attemptId, user.getId());
|
||||
Boolean result = pair.getFirst();
|
||||
if (result != null && !result) {
|
||||
final StudyCheckResult result = doAdaptiveCheck(wrapper, attemptId, user.getId());
|
||||
if (result.getStatus() == StudyStatus.Failed) {
|
||||
try {
|
||||
createNewAttempt(task.getStepId());
|
||||
final Task updatedTask = getTask(project, task.getName(), task.getStepId(), user.getId());
|
||||
@@ -503,10 +503,10 @@ public class EduAdaptiveStepicConnector {
|
||||
LOG.warn(e.getMessage());
|
||||
}
|
||||
}
|
||||
return pair;
|
||||
return result;
|
||||
}
|
||||
|
||||
return new Pair<>(null, "Failed to launch checking");
|
||||
return new StudyCheckResult(StudyStatus.Unchecked, StudyCheckAction.FAILED_CHECK_LAUNCH);
|
||||
}
|
||||
|
||||
private static boolean[] createChoiceTaskAnswerArray(@NotNull ChoiceTask task) {
|
||||
@@ -518,7 +518,7 @@ public class EduAdaptiveStepicConnector {
|
||||
return answer;
|
||||
}
|
||||
|
||||
public static Pair<Boolean, String> checkCodeTask(@NotNull Project project, @NotNull Task task, @NotNull StepicUser user) {
|
||||
public static StudyCheckResult checkCodeTask(@NotNull Project project, @NotNull Task task, @NotNull StepicUser user) {
|
||||
int attemptId = -1;
|
||||
try {
|
||||
attemptId = getAttemptId(task);
|
||||
@@ -539,10 +539,10 @@ public class EduAdaptiveStepicConnector {
|
||||
else {
|
||||
LOG.warn("Got an incorrect attempt id: " + attemptId);
|
||||
}
|
||||
return Pair.create(null, "Failed to launch checking");
|
||||
return new StudyCheckResult(StudyStatus.Unchecked, StudyCheckAction.FAILED_CHECK_LAUNCH);
|
||||
}
|
||||
|
||||
private static Pair<Boolean, String> doAdaptiveCheck(@NotNull StepicWrappers.SubmissionToPostWrapper submission,
|
||||
private static StudyCheckResult doAdaptiveCheck(@NotNull StepicWrappers.SubmissionToPostWrapper submission,
|
||||
int attemptId, int userId) {
|
||||
final CloseableHttpClient client = EduStepicAuthorizedClient.getHttpClient();
|
||||
if (client != null) {
|
||||
@@ -553,7 +553,7 @@ public class EduAdaptiveStepicConnector {
|
||||
final String status = wrapper.submissions[0].status;
|
||||
final String hint = wrapper.submissions[0].hint;
|
||||
final boolean isSolved = !status.equals("wrong");
|
||||
return Pair.create(isSolved, hint.isEmpty() ? StringUtil.capitalize(status) + " solution" : hint);
|
||||
return new StudyCheckResult(isSolved ? StudyStatus.Solved : StudyStatus.Failed, hint.isEmpty() ? StringUtil.capitalize(status) + " solution" : hint);
|
||||
}
|
||||
else {
|
||||
LOG.warn("Got a submission wrapper with incorrect submissions number: " + wrapper.submissions.length);
|
||||
@@ -561,11 +561,10 @@ public class EduAdaptiveStepicConnector {
|
||||
}
|
||||
else {
|
||||
LOG.warn("Can't do adaptive check: " + "wrapper is null");
|
||||
return Pair.create(null, "Can't get check results for Stepik");
|
||||
return new StudyCheckResult(StudyStatus.Unchecked, "Can't get check results for Stepik");
|
||||
}
|
||||
}
|
||||
|
||||
return Pair.create(null, "Failed to launch checking");
|
||||
return new StudyCheckResult(StudyStatus.Unchecked, StudyCheckAction.FAILED_CHECK_LAUNCH);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+4
-1
@@ -1,5 +1,6 @@
|
||||
package com.jetbrains.edu.learning.stepic;
|
||||
|
||||
import com.intellij.openapi.progress.PerformInBackgroundOption;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -32,9 +33,11 @@ public class EduNextRecommendationCheckListener implements StudyCheckListener {
|
||||
if (statusAfterCheck != StudyStatus.Solved) {
|
||||
return;
|
||||
}
|
||||
ProgressManager.getInstance().run(new com.intellij.openapi.progress.Task.Backgroundable(project, EduAdaptiveStepicConnector.LOADING_NEXT_RECOMMENDATION) {
|
||||
ProgressManager.getInstance().run(new com.intellij.openapi.progress.Task.Backgroundable(project, EduAdaptiveStepicConnector.LOADING_NEXT_RECOMMENDATION, false,
|
||||
PerformInBackgroundOption.DEAF) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
indicator.setIndeterminate(true);
|
||||
EduAdaptiveStepicConnector.addNextRecommendedTask(project, task.getLesson(), indicator, EduAdaptiveStepicConnector.NEXT_RECOMMENDATION_REACTION);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user