mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
removed obsolete duplicated course formats
This commit is contained in:
-173
@@ -1,173 +0,0 @@
|
||||
package com.jetbrains.edu.coursecreator.format;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.editor.markup.HighlighterLayer;
|
||||
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.jetbrains.edu.coursecreator.CCProjectService;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
public class AnswerPlaceholder implements Comparable<AnswerPlaceholder> {
|
||||
|
||||
@Expose private int line;
|
||||
@Expose private int start;
|
||||
@Expose private String hint;
|
||||
@Expose private String possible_answer;
|
||||
@Expose private int length;
|
||||
private int myIndex;
|
||||
|
||||
private String myTaskText;
|
||||
private int myReplacementLength;
|
||||
|
||||
public String getHint() {
|
||||
return hint;
|
||||
}
|
||||
|
||||
public String getPossible_answer() {
|
||||
return possible_answer;
|
||||
}
|
||||
|
||||
public void setPossible_answer(String possible_answer) {
|
||||
this.possible_answer = possible_answer;
|
||||
}
|
||||
|
||||
public AnswerPlaceholder() {}
|
||||
|
||||
public AnswerPlaceholder(int line, int start, int length, String selectedText) {
|
||||
this.line = line;
|
||||
this.start = start;
|
||||
myReplacementLength = length;
|
||||
this.possible_answer = selectedText;
|
||||
}
|
||||
|
||||
public void setTaskText(@NotNull final String taskText) {
|
||||
myTaskText = taskText;
|
||||
length = myTaskText.length();
|
||||
}
|
||||
|
||||
public String getTaskText() {
|
||||
return myTaskText;
|
||||
}
|
||||
|
||||
public int getReplacementLength() {
|
||||
return myReplacementLength;
|
||||
}
|
||||
|
||||
public void setHint(String hint) {
|
||||
this.hint = hint;
|
||||
}
|
||||
|
||||
public String getHintName() {
|
||||
return hint;
|
||||
}
|
||||
|
||||
public void removeResources(@NotNull final Project project) {
|
||||
if (hint != null) {
|
||||
VirtualFile hints = project.getBaseDir().findChild("hints");
|
||||
if (hints == null) {
|
||||
return;
|
||||
}
|
||||
File hintFile = new File(hints.getPath(), hint);
|
||||
CCProjectService.deleteProjectFile(hintFile, project);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawHighlighter(@NotNull final Editor editor, boolean useLength) {
|
||||
int startOffset = editor.getDocument().getLineStartOffset(line) + start;
|
||||
int highlighterLength = useLength ? length : myReplacementLength;
|
||||
int endOffset = startOffset + highlighterLength;
|
||||
TextAttributes defaultTestAttributes =
|
||||
EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.LIVE_TEMPLATE_ATTRIBUTES);
|
||||
defaultTestAttributes.setEffectColor(JBColor.BLUE);
|
||||
RangeHighlighter highlighter =
|
||||
editor.getMarkupModel().addRangeHighlighter(startOffset, endOffset, HighlighterLayer.LAST + 1, defaultTestAttributes,
|
||||
HighlighterTargetArea.EXACT_RANGE);
|
||||
highlighter.setGreedyToLeft(true);
|
||||
highlighter.setGreedyToRight(true);
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
public void setReplacementLength(int replacementLength) {
|
||||
myReplacementLength = replacementLength;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public int getRealStartOffset(Document document) {
|
||||
return document.getLineStartOffset(line) + start;
|
||||
}
|
||||
|
||||
public void setLine(int line) {
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(int start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull AnswerPlaceholder answerPlaceholder) {
|
||||
int lineDiff = line - answerPlaceholder.line;
|
||||
if (lineDiff == 0) {
|
||||
return start - answerPlaceholder.start;
|
||||
}
|
||||
return lineDiff;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void createGuardedBlocks(@NotNull final Editor editor) {
|
||||
Document document = editor.getDocument();
|
||||
if (document instanceof DocumentImpl) {
|
||||
DocumentImpl documentImpl = (DocumentImpl)document;
|
||||
List<RangeMarker> blocks = documentImpl.getGuardedBlocks();
|
||||
int start = getRealStartOffset(document);
|
||||
int end = start + getReplacementLength();
|
||||
if (start != 0) {
|
||||
createGuardedBlock(editor, blocks, start - 1, start);
|
||||
}
|
||||
if (end != document.getTextLength()) {
|
||||
createGuardedBlock(editor, blocks, end, end + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void createGuardedBlock(Editor editor, List<RangeMarker> blocks, int start, int end) {
|
||||
RangeHighlighter rh = editor.getMarkupModel()
|
||||
.addRangeHighlighter(start, end, HighlighterLayer.LAST + 1, null, HighlighterTargetArea.EXACT_RANGE);
|
||||
blocks.add(rh);
|
||||
}
|
||||
|
||||
public void setLength(int length) {
|
||||
this.length = length;
|
||||
}
|
||||
}
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
package com.jetbrains.edu.coursecreator.format;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Course {
|
||||
@Expose private List<Lesson> lessons = new ArrayList<Lesson>();
|
||||
@Expose private String description;
|
||||
|
||||
@Expose private String name;
|
||||
@Expose private String author;
|
||||
|
||||
@Expose private String language;
|
||||
|
||||
private Map<String, Lesson> myLessonsMap = new HashMap<String, Lesson>();
|
||||
|
||||
public Map<String, Lesson> getLessonsMap() {
|
||||
return myLessonsMap;
|
||||
}
|
||||
|
||||
public Lesson getLesson(@NotNull final String name) {
|
||||
return myLessonsMap.get(name);
|
||||
}
|
||||
|
||||
public Course() {
|
||||
}
|
||||
|
||||
public Course(@NotNull final String name, @NotNull final String author, @NotNull final String description) {
|
||||
this.description = description;
|
||||
this.name = name;
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public List<Lesson> getLessons() {
|
||||
return lessons;
|
||||
}
|
||||
|
||||
public void addLesson(@NotNull final Lesson lesson, @NotNull final PsiDirectory directory) {
|
||||
lessons.add(lesson);
|
||||
myLessonsMap.put(directory.getName(), lesson);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
lessons.clear();
|
||||
for (Lesson lesson: myLessonsMap.values()) {
|
||||
lessons.add(lesson);
|
||||
lesson.init();
|
||||
}
|
||||
Collections.sort(lessons);
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public void setLessons(List<Lesson> lessons) {
|
||||
this.lessons = lessons;
|
||||
}
|
||||
|
||||
public void setLessonsMap(Map<String, Lesson> lessonsMap) {
|
||||
myLessonsMap = lessonsMap;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public void setLanguage(String language) {
|
||||
this.language = language;
|
||||
}
|
||||
}
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
package com.jetbrains.edu.coursecreator.format;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Lesson implements Comparable{
|
||||
@Expose private String name;
|
||||
@Expose private List<Task> task_list = new ArrayList<Task>();
|
||||
|
||||
public int myIndex;
|
||||
public Map<String, Task> myTasksMap = new HashMap<String, Task>();
|
||||
|
||||
public Lesson() {}
|
||||
|
||||
public Lesson(@NotNull final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void addTask(@NotNull final Task task, PsiDirectory taskDirectory) {
|
||||
myTasksMap.put(taskDirectory.getName(), task);
|
||||
task_list.add(task);
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Task getTask(@NotNull final String name) {
|
||||
return myTasksMap.get(name);
|
||||
}
|
||||
|
||||
public List<Task> getTaskList() {
|
||||
return task_list;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
public Map<String, Task> getTasksMap() {
|
||||
return myTasksMap;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
task_list.clear();
|
||||
for (Task task : myTasksMap.values()) {
|
||||
task_list.add(task);
|
||||
}
|
||||
Collections.sort(task_list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull Object o) {
|
||||
Lesson lesson = (Lesson) o;
|
||||
return myIndex - lesson.getIndex();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<Task> getTask_list() {
|
||||
return task_list;
|
||||
}
|
||||
|
||||
public void setTask_list(List<Task> task_list) {
|
||||
this.task_list = task_list;
|
||||
}
|
||||
|
||||
public void setTasksMap(Map<String, Task> tasksMap) {
|
||||
myTasksMap = tasksMap;
|
||||
}
|
||||
}
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
package com.jetbrains.edu.coursecreator.format;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.jetbrains.edu.coursecreator.CCProjectService;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Task implements Comparable{
|
||||
@Expose public String name;
|
||||
@Expose public Map<String, TaskFile> task_files = new HashMap<String, TaskFile>();
|
||||
private int myIndex;
|
||||
|
||||
public Task() {}
|
||||
|
||||
public Task(@NotNull final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
public void addTaskFile(@NotNull final String name, int index) {
|
||||
TaskFile taskFile = new TaskFile();
|
||||
taskFile.setIndex(index);
|
||||
task_files.put(name, taskFile);
|
||||
}
|
||||
|
||||
public TaskFile getTaskFile(@NotNull final String name) {
|
||||
String fileName = CCProjectService.getRealTaskFileName(name);
|
||||
return fileName != null ? task_files.get(fileName) : null;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
public Map<String, TaskFile> getTaskFiles() {
|
||||
return task_files;
|
||||
}
|
||||
|
||||
public boolean isTaskFile(String name) {
|
||||
return task_files.get(name) != null;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull Object o) {
|
||||
Task task = (Task) o;
|
||||
return myIndex - task.getIndex();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Map<String, TaskFile> getTask_files() {
|
||||
return task_files;
|
||||
}
|
||||
|
||||
public void setTask_files(Map<String, TaskFile> task_files) {
|
||||
this.task_files = task_files;
|
||||
}
|
||||
}
|
||||
-121
@@ -1,121 +0,0 @@
|
||||
package com.jetbrains.edu.coursecreator.format;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TaskFile {
|
||||
@Expose private List<AnswerPlaceholder> task_windows = new ArrayList<AnswerPlaceholder>();
|
||||
private int myIndex;
|
||||
|
||||
public TaskFile() {
|
||||
}
|
||||
|
||||
public void addTaskWindow(@NotNull final AnswerPlaceholder answerPlaceholder, int index) {
|
||||
answerPlaceholder.setIndex(index);
|
||||
task_windows.add(answerPlaceholder);
|
||||
}
|
||||
|
||||
public List<AnswerPlaceholder> getAnswerPlaceholders() {
|
||||
return task_windows;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param pos position in editor
|
||||
* @return task window located in specified position or null if there is no task window in this position
|
||||
*/
|
||||
@Nullable
|
||||
public AnswerPlaceholder getAnswerPlaceholder(@NotNull final Document document, @NotNull final LogicalPosition pos) {
|
||||
int line = pos.line;
|
||||
if (line >= document.getLineCount()) {
|
||||
return null;
|
||||
}
|
||||
int column = pos.column;
|
||||
int offset = document.getLineStartOffset(line) + column;
|
||||
for (AnswerPlaceholder tw : task_windows) {
|
||||
if (tw.getLine() <= line) {
|
||||
int twStartOffset = tw.getRealStartOffset(document);
|
||||
final int length = tw.getReplacementLength() > 0 ? tw.getReplacementLength() : 0;
|
||||
int twEndOffset = twStartOffset + length;
|
||||
if (twStartOffset <= offset && offset <= twEndOffset) {
|
||||
return tw;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void copy(@NotNull final TaskFile target) {
|
||||
target.setIndex(myIndex);
|
||||
for (AnswerPlaceholder answerPlaceholder : task_windows) {
|
||||
AnswerPlaceholder savedWindow = new AnswerPlaceholder(answerPlaceholder.getLine(), answerPlaceholder.getStart(),
|
||||
answerPlaceholder.getLength(), "");
|
||||
target.getAnswerPlaceholders().add(savedWindow);
|
||||
savedWindow.setIndex(answerPlaceholder.getIndex());
|
||||
savedWindow.setReplacementLength(answerPlaceholder.getReplacementLength());
|
||||
}
|
||||
}
|
||||
|
||||
public void update(@NotNull final TaskFile source) {
|
||||
for (AnswerPlaceholder answerPlaceholder : source.getAnswerPlaceholders()) {
|
||||
AnswerPlaceholder answerPlaceholderUpdated = getAnswerPlaceholder(answerPlaceholder.getIndex());
|
||||
if (answerPlaceholderUpdated == null) {
|
||||
break;
|
||||
}
|
||||
answerPlaceholderUpdated.setLine(answerPlaceholder.getLine());
|
||||
answerPlaceholderUpdated.setStart(answerPlaceholder.getStart());
|
||||
answerPlaceholderUpdated.setReplacementLength(answerPlaceholder.getReplacementLength());
|
||||
answerPlaceholderUpdated.setLength(answerPlaceholder.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private AnswerPlaceholder getAnswerPlaceholder(int index) {
|
||||
for (AnswerPlaceholder answerPlaceholder : task_windows) {
|
||||
if (answerPlaceholder.getIndex() == index) {
|
||||
return answerPlaceholder;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks symbols adjacent to task windows as read-only fragments
|
||||
*/
|
||||
public void createGuardedBlocks(@NotNull final Editor editor) {
|
||||
for (AnswerPlaceholder answerPlaceholder : task_windows) {
|
||||
answerPlaceholder.createGuardedBlocks(editor);
|
||||
}
|
||||
}
|
||||
|
||||
public void sortTaskWindows() {
|
||||
Collections.sort(task_windows);
|
||||
for (int i = 0; i < task_windows.size(); i++) {
|
||||
task_windows.get(i).setIndex(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public List<AnswerPlaceholder> getTask_windows() {
|
||||
return task_windows;
|
||||
}
|
||||
|
||||
public void setTask_windows(List<AnswerPlaceholder> task_windows) {
|
||||
this.task_windows = task_windows;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return myIndex;
|
||||
}
|
||||
}
|
||||
-251
@@ -1,251 +0,0 @@
|
||||
package com.jetbrains.edu.learning.course;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.process.CapturingProcessHandler;
|
||||
import com.intellij.execution.process.ProcessOutput;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.markup.*;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.jetbrains.edu.learning.StudyDocumentListener;
|
||||
import com.jetbrains.edu.learning.StudyTestRunner;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Implementation of windows which user should type in
|
||||
*/
|
||||
|
||||
public class AnswerPlaceholder implements Comparable, Stateful {
|
||||
private static final String WINDOW_POSTFIX = "_window";
|
||||
private static final Logger LOG = Logger.getInstance(AnswerPlaceholder.class);
|
||||
private int line = 0;
|
||||
private int start = 0;
|
||||
private String hint = "";
|
||||
private String possibleAnswer = "";
|
||||
private int length = 0;
|
||||
private TaskFile myTaskFile;
|
||||
private int myIndex = -1;
|
||||
private int myInitialLine = -1;
|
||||
private int myInitialStart = -1;
|
||||
private int myInitialLength = -1;
|
||||
private StudyStatus myStatus = StudyStatus.Unchecked;
|
||||
|
||||
public StudyStatus getStatus() {
|
||||
return myStatus;
|
||||
}
|
||||
|
||||
public void setStatus(StudyStatus status, StudyStatus oldStatus) {
|
||||
myStatus = status;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void setLength(int length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(int start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public void setLine(int line) {
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw task window with color according to its status
|
||||
*/
|
||||
public void draw(@NotNull final Editor editor) {
|
||||
Document document = editor.getDocument();
|
||||
if (!isValid(document)) {
|
||||
return;
|
||||
}
|
||||
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
|
||||
final TextAttributes defaultTestAttributes = new TextAttributes(scheme.getDefaultForeground(), scheme.getDefaultBackground(), null,
|
||||
EffectType.BOXED, Font.PLAIN);
|
||||
final JBColor color = getColor();
|
||||
int startOffset = document.getLineStartOffset(line) + start;
|
||||
RangeHighlighter
|
||||
highlighter = editor.getMarkupModel().addRangeHighlighter(startOffset, startOffset + length, HighlighterLayer.LAST + 1,
|
||||
defaultTestAttributes,
|
||||
HighlighterTargetArea.EXACT_RANGE);
|
||||
highlighter.setCustomRenderer(new CustomHighlighterRenderer() {
|
||||
@Override
|
||||
public void paint(@NotNull Editor editor, @NotNull RangeHighlighter highlighter, @NotNull Graphics g) {
|
||||
g.setColor(color);
|
||||
Point point = editor.logicalPositionToXY(editor.offsetToLogicalPosition(highlighter.getStartOffset()));
|
||||
Point pointEnd = editor.logicalPositionToXY(editor.offsetToLogicalPosition(highlighter.getEndOffset()));
|
||||
g.drawRect(point.x, point.y, (pointEnd.x - point.x), editor.getLineHeight() + 1);
|
||||
}
|
||||
});
|
||||
editor.getCaretModel().moveToOffset(startOffset);
|
||||
highlighter.setGreedyToLeft(true);
|
||||
highlighter.setGreedyToRight(true);
|
||||
}
|
||||
|
||||
public boolean isValid(@NotNull final Document document) {
|
||||
boolean isLineValid = line < document.getLineCount() && line >= 0;
|
||||
if (!isLineValid) return false;
|
||||
boolean isStartValid = start >= 0 && start < document.getLineEndOffset(line);
|
||||
boolean isLengthValid = (getRealStartOffset(document) + length) <= document.getTextLength();
|
||||
return isLengthValid && isStartValid;
|
||||
}
|
||||
|
||||
private JBColor getColor() {
|
||||
if (myStatus == StudyStatus.Solved) {
|
||||
return JBColor.GREEN;
|
||||
}
|
||||
if (myStatus == StudyStatus.Failed) {
|
||||
return JBColor.RED;
|
||||
}
|
||||
return JBColor.BLUE;
|
||||
}
|
||||
|
||||
public int getRealStartOffset(@NotNull final Document document) {
|
||||
return document.getLineStartOffset(line) + start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes window
|
||||
*
|
||||
* @param file task file which window belongs to
|
||||
*/
|
||||
public void init(final TaskFile file, boolean isRestarted) {
|
||||
if (!isRestarted) {
|
||||
myInitialLine = line;
|
||||
myInitialLength = length;
|
||||
myInitialStart = start;
|
||||
}
|
||||
myTaskFile = file;
|
||||
}
|
||||
|
||||
public TaskFile getTaskFile() {
|
||||
return myTaskFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull Object o) {
|
||||
AnswerPlaceholder answerPlaceholder = (AnswerPlaceholder)o;
|
||||
if (answerPlaceholder.getTaskFile() != myTaskFile) {
|
||||
throw new ClassCastException();
|
||||
}
|
||||
int lineDiff = line - answerPlaceholder.line;
|
||||
if (lineDiff == 0) {
|
||||
return start - answerPlaceholder.start;
|
||||
}
|
||||
return lineDiff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns window to its initial state
|
||||
*/
|
||||
public void reset() {
|
||||
myStatus = StudyStatus.Unchecked;
|
||||
line = myInitialLine;
|
||||
start = myInitialStart;
|
||||
length = myInitialLength;
|
||||
}
|
||||
|
||||
public String getHint() {
|
||||
return hint;
|
||||
}
|
||||
|
||||
public void setHint(@NotNull final String hint) {
|
||||
this.hint = hint;
|
||||
}
|
||||
|
||||
public String getPossibleAnswer() {
|
||||
return possibleAnswer;
|
||||
}
|
||||
|
||||
public void setPossibleAnswer(String possibleAnswer) {
|
||||
this.possibleAnswer = possibleAnswer;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
public void smartCheck(@NotNull final Project project,
|
||||
@NotNull final VirtualFile answerFile,
|
||||
@NotNull final TaskFile answerTaskFile,
|
||||
@NotNull final TaskFile usersTaskFile,
|
||||
@NotNull final StudyTestRunner testRunner,
|
||||
@NotNull final VirtualFile virtualFile,
|
||||
@NotNull final Document usersDocument) {
|
||||
|
||||
try {
|
||||
final VirtualFile windowCopy =
|
||||
answerFile.copy(this, answerFile.getParent(), answerFile.getNameWithoutExtension() + myIndex + WINDOW_POSTFIX + "." + answerFile.getExtension());
|
||||
final FileDocumentManager documentManager = FileDocumentManager.getInstance();
|
||||
final Document windowDocument = documentManager.getDocument(windowCopy);
|
||||
if (windowDocument != null) {
|
||||
final File resourceFile = StudyUtils.copyResourceFile(virtualFile.getName(), windowCopy.getName(), project, usersTaskFile.getTask());
|
||||
final TaskFile windowTaskFile = new TaskFile();
|
||||
TaskFile.copy(answerTaskFile, windowTaskFile);
|
||||
StudyDocumentListener listener = new StudyDocumentListener(windowTaskFile);
|
||||
windowDocument.addDocumentListener(listener);
|
||||
int start = getRealStartOffset(windowDocument);
|
||||
int end = start + getLength();
|
||||
final AnswerPlaceholder userAnswerPlaceholder = usersTaskFile.getAnswerPlaceholders().get(getIndex());
|
||||
int userStart = userAnswerPlaceholder.getRealStartOffset(usersDocument);
|
||||
int userEnd = userStart + userAnswerPlaceholder.getLength();
|
||||
String text = usersDocument.getText(new TextRange(userStart, userEnd));
|
||||
windowDocument.replaceString(start, end, text);
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
documentManager.saveDocument(windowDocument);
|
||||
}
|
||||
});
|
||||
VirtualFile fileWindows = StudyUtils.flushWindows(windowTaskFile, windowCopy);
|
||||
Process smartTestProcess = testRunner.createCheckProcess(project, windowCopy.getPath());
|
||||
final CapturingProcessHandler handler = new CapturingProcessHandler(smartTestProcess);
|
||||
final ProcessOutput output = handler.runProcess();
|
||||
boolean res = testRunner.getTestsOutput(output).equals(StudyTestRunner.TEST_OK);
|
||||
userAnswerPlaceholder.setStatus(res ? StudyStatus.Solved : StudyStatus.Failed, StudyStatus.Unchecked);
|
||||
StudyUtils.deleteFile(windowCopy);
|
||||
if (fileWindows != null) {
|
||||
StudyUtils.deleteFile(fileWindows);
|
||||
}
|
||||
if (!resourceFile.delete()) {
|
||||
LOG.error("failed to delete", resourceFile.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
-134
@@ -1,134 +0,0 @@
|
||||
package com.jetbrains.edu.learning.course;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.edu.learning.StudyNames;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Course {
|
||||
private static final Logger LOG = Logger.getInstance(Course.class.getName());
|
||||
public static final String SANDBOX_DIR = "Sandbox";
|
||||
public List<Lesson> lessons = new ArrayList<Lesson>();
|
||||
private String description;
|
||||
private String name;
|
||||
private String myCourseDirectory = "";
|
||||
private String author="";
|
||||
private boolean myUpToDate;
|
||||
private String myLanguage;
|
||||
|
||||
|
||||
public List<Lesson> getLessons() {
|
||||
return lessons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes state of course
|
||||
*/
|
||||
public void init(boolean isRestarted) {
|
||||
for (Lesson lesson : lessons) {
|
||||
lesson.init(this, isRestarted);
|
||||
}
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates course directory in project user created
|
||||
*
|
||||
* @param baseDir project directory
|
||||
* @param resourceRoot directory where original course is stored
|
||||
*/
|
||||
public void create(@NotNull final VirtualFile baseDir, @NotNull final File resourceRoot,
|
||||
@NotNull final Project project) {
|
||||
ApplicationManager.getApplication().invokeLater(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
for (int i = 0; i < lessons.size(); i++) {
|
||||
Lesson lesson = lessons.get(i);
|
||||
lesson.setIndex(i);
|
||||
lesson.create(baseDir, resourceRoot, project);
|
||||
}
|
||||
baseDir.createChildDirectory(this, SANDBOX_DIR);
|
||||
File[] files = resourceRoot.listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return !name.contains(StudyNames.LESSON_DIR) && !name.equals("course.json") && !name.equals("hints");
|
||||
}
|
||||
});
|
||||
for (File file : files) {
|
||||
FileUtil.copy(file, new File(baseDir.getPath(), file.getName()));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setCourseDirectory(@NotNull final String courseDirectory) {
|
||||
myCourseDirectory = courseDirectory;
|
||||
}
|
||||
|
||||
public String getCourseDirectory() {
|
||||
return myCourseDirectory;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public boolean isUpToDate() {
|
||||
return myUpToDate;
|
||||
}
|
||||
|
||||
public void setUpToDate(boolean upToDate) {
|
||||
myUpToDate = upToDate;
|
||||
}
|
||||
|
||||
public Language getLanguageById() {
|
||||
return Language.findLanguageByID(myLanguage);
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return myLanguage;
|
||||
}
|
||||
public void setLanguage(@NotNull final String language) {
|
||||
myLanguage = language;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
package com.jetbrains.edu.learning.course;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implementation of class which contains information to be shawn in course description in tool window
|
||||
* and when project is being created
|
||||
*/
|
||||
public class CourseInfo {
|
||||
boolean is_public;
|
||||
public List<Integer> sections;
|
||||
@SerializedName("title")
|
||||
private String myName;
|
||||
@SerializedName("summary")
|
||||
private String myDescription;
|
||||
|
||||
private String myAuthor;
|
||||
public static CourseInfo INVALID_COURSE = new CourseInfo("", "", "");
|
||||
|
||||
public CourseInfo(String name, String author, String description) {
|
||||
myName = name;
|
||||
myAuthor = author;
|
||||
myDescription = description;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return myAuthor;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return myDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CourseInfo that = (CourseInfo)o;
|
||||
return that.getName().equals(myName) && that.getAuthor().equals(myAuthor)
|
||||
&& that.getDescription().equals(myDescription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = myName != null ? myName.hashCode() : 0;
|
||||
result = 31 * result + (myAuthor != null ? myAuthor.hashCode() : 0);
|
||||
result = 31 * result + (myDescription != null ? myDescription.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
-126
@@ -1,126 +0,0 @@
|
||||
package com.jetbrains.edu.learning.course;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.xmlb.annotations.Transient;
|
||||
import com.jetbrains.edu.learning.StudyNames;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Lesson implements Stateful {
|
||||
@Transient
|
||||
String id;
|
||||
@Transient
|
||||
public List<Integer> steps;
|
||||
@Transient
|
||||
public List<String> tags;
|
||||
@Transient
|
||||
Boolean is_public;
|
||||
@SerializedName("title")
|
||||
private String name;
|
||||
|
||||
public List<Task> taskList = new ArrayList<Task>();
|
||||
private Course myCourse = null;
|
||||
private int myIndex = -1;
|
||||
private LessonInfo myLessonInfo = new LessonInfo();
|
||||
|
||||
public LessonInfo getLessonInfo() {
|
||||
return myLessonInfo;
|
||||
}
|
||||
|
||||
@Transient
|
||||
public StudyStatus getStatus() {
|
||||
for (Task task : taskList) {
|
||||
StudyStatus taskStatus = task.getStatus();
|
||||
if (taskStatus == StudyStatus.Unchecked || taskStatus == StudyStatus.Failed) {
|
||||
return StudyStatus.Unchecked;
|
||||
}
|
||||
}
|
||||
return StudyStatus.Solved;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatus(StudyStatus status, StudyStatus oldStatus) {
|
||||
for (Task task : taskList) {
|
||||
task.setStatus(status, oldStatus);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Task> getTaskList() {
|
||||
return taskList;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates lesson directory in its course folder in project user created
|
||||
*
|
||||
* @param courseDir project directory of course
|
||||
* @param resourceRoot directory where original lesson stored
|
||||
* @throws IOException
|
||||
*/
|
||||
public void create(@NotNull final VirtualFile courseDir, @NotNull final File resourceRoot,
|
||||
@NotNull final Project project) throws IOException {
|
||||
String lessonDirName = StudyNames.LESSON_DIR + Integer.toString(myIndex + 1);
|
||||
VirtualFile lessonDir = courseDir.createChildDirectory(this, lessonDirName);
|
||||
for (int i = 0; i < taskList.size(); i++) {
|
||||
Task task = taskList.get(i);
|
||||
task.setIndex(i);
|
||||
task.create(lessonDir, new File(resourceRoot, lessonDir.getName()), project);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes state of lesson
|
||||
*
|
||||
* @param course course which lesson belongs to
|
||||
*/
|
||||
public void init(final Course course, boolean isRestarted) {
|
||||
myCourse = course;
|
||||
myLessonInfo.setTaskNum(taskList.size());
|
||||
myLessonInfo.setTaskUnchecked(taskList.size());
|
||||
for (Task task : taskList) {
|
||||
task.init(this, isRestarted);
|
||||
}
|
||||
}
|
||||
|
||||
public Lesson next() {
|
||||
List<Lesson> lessons = myCourse.getLessons();
|
||||
if (myIndex + 1 >= lessons.size()) {
|
||||
return null;
|
||||
}
|
||||
return lessons.get(myIndex + 1);
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
public Lesson prev() {
|
||||
if (myIndex - 1 < 0) {
|
||||
return null;
|
||||
}
|
||||
return myCourse.getLessons().get(myIndex - 1);
|
||||
}
|
||||
|
||||
public Course getCourse() {
|
||||
return myCourse;
|
||||
}
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
package com.jetbrains.edu.learning.course;
|
||||
|
||||
/**
|
||||
* Implementation of class which contains information about student progress in current lesson
|
||||
*/
|
||||
public class LessonInfo {
|
||||
private int myTaskNum;
|
||||
private int myTaskFailed;
|
||||
private int myTaskSolved;
|
||||
private int myTaskUnchecked;
|
||||
|
||||
public int getTaskNum() {
|
||||
return myTaskNum;
|
||||
}
|
||||
|
||||
public void setTaskNum(int taskNum) {
|
||||
myTaskNum = taskNum;
|
||||
}
|
||||
|
||||
public int getTaskFailed() {
|
||||
return myTaskFailed;
|
||||
}
|
||||
|
||||
public void setTaskFailed(int taskFailed) {
|
||||
myTaskFailed = taskFailed;
|
||||
}
|
||||
|
||||
public int getTaskSolved() {
|
||||
return myTaskSolved;
|
||||
}
|
||||
|
||||
public void setTaskSolved(int taskSolved) {
|
||||
myTaskSolved = taskSolved;
|
||||
}
|
||||
|
||||
public int getTaskUnchecked() {
|
||||
return myTaskUnchecked;
|
||||
}
|
||||
|
||||
public void setTaskUnchecked(int taskUnchecked) {
|
||||
myTaskUnchecked = taskUnchecked;
|
||||
}
|
||||
|
||||
public void update(StudyStatus status, int delta) {
|
||||
switch (status) {
|
||||
case Solved: {
|
||||
myTaskSolved += delta;
|
||||
break;
|
||||
}
|
||||
case Failed: {
|
||||
myTaskFailed += delta;
|
||||
break;
|
||||
}
|
||||
case Unchecked: {
|
||||
myTaskUnchecked += delta;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
package com.jetbrains.edu.learning.course;
|
||||
|
||||
public interface Stateful {
|
||||
StudyStatus getStatus();
|
||||
void setStatus(StudyStatus status, StudyStatus oldStatus);
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
package com.jetbrains.edu.learning.course;
|
||||
|
||||
/**
|
||||
* @see {@link AnswerPlaceholder#myStatus}
|
||||
*/
|
||||
public enum StudyStatus {
|
||||
Unchecked, Solved, Failed
|
||||
}
|
||||
-214
@@ -1,214 +0,0 @@
|
||||
package com.jetbrains.edu.learning.course;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.xmlb.annotations.Transient;
|
||||
import com.jetbrains.edu.learning.StudyNames;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Implementation of task which contains task files, tests, input file for tests
|
||||
*/
|
||||
public class Task implements Stateful {
|
||||
public static final String TASK_DIR = "task";
|
||||
private String name;
|
||||
private String text;
|
||||
private String testsText;
|
||||
public Map<String, TaskFile> taskFiles = new HashMap<String, TaskFile>();
|
||||
private Lesson myLesson;
|
||||
private int myIndex;
|
||||
private List<UserTest> userTests = new ArrayList<UserTest>();
|
||||
public static final String USER_TESTS = "userTests";
|
||||
|
||||
public Map<String, TaskFile> getTaskFiles() {
|
||||
return taskFiles;
|
||||
}
|
||||
|
||||
@Transient
|
||||
public StudyStatus getStatus() {
|
||||
for (TaskFile taskFile : taskFiles.values()) {
|
||||
StudyStatus taskFileStatus = taskFile.getStatus();
|
||||
if (taskFileStatus == StudyStatus.Unchecked) {
|
||||
return StudyStatus.Unchecked;
|
||||
}
|
||||
if (taskFileStatus == StudyStatus.Failed) {
|
||||
return StudyStatus.Failed;
|
||||
}
|
||||
}
|
||||
return StudyStatus.Solved;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setStatus(@NotNull final StudyStatus status, @NotNull final StudyStatus oldStatus) {
|
||||
LessonInfo lessonInfo = myLesson.getLessonInfo();
|
||||
if (status != oldStatus) {
|
||||
lessonInfo.update(oldStatus, -1);
|
||||
lessonInfo.update(status, +1);
|
||||
}
|
||||
for (TaskFile taskFile : taskFiles.values()) {
|
||||
taskFile.setStatus(status, oldStatus);
|
||||
}
|
||||
}
|
||||
|
||||
public void setUserTests(@NotNull final List<UserTest> userTests) {
|
||||
this.userTests = userTests;
|
||||
}
|
||||
|
||||
public List<UserTest> getUserTests() {
|
||||
return userTests;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates task directory in its lesson folder in project user created
|
||||
*
|
||||
* @param lessonDir project directory of lesson which task belongs to
|
||||
* @param resourceRoot directory where original task file stored
|
||||
* @throws IOException
|
||||
*/
|
||||
public void create(@NotNull final VirtualFile lessonDir, @NotNull final File resourceRoot,
|
||||
@NotNull final Project project) throws IOException {
|
||||
VirtualFile taskDir = lessonDir.createChildDirectory(this, TASK_DIR + Integer.toString(myIndex + 1));
|
||||
StudyUtils.markDirAsSourceRoot(taskDir, project);
|
||||
File newResourceRoot = new File(resourceRoot, taskDir.getName());
|
||||
int i = 0;
|
||||
for (Map.Entry<String, TaskFile> taskFile : taskFiles.entrySet()) {
|
||||
TaskFile taskFileContent = taskFile.getValue();
|
||||
taskFileContent.setIndex(i);
|
||||
i++;
|
||||
taskFileContent.create(taskDir, newResourceRoot, taskFile.getKey());
|
||||
}
|
||||
File[] filesInTask = newResourceRoot.listFiles();
|
||||
if (filesInTask != null) {
|
||||
for (File file : filesInTask) {
|
||||
String fileName = file.getName();
|
||||
if (!isTaskFile(fileName)) {
|
||||
File resourceFile = new File(newResourceRoot, fileName);
|
||||
File fileInProject = new File(taskDir.getCanonicalPath(), fileName);
|
||||
FileUtil.copy(resourceFile, fileInProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isTaskFile(@NotNull final String fileName) {
|
||||
return taskFiles.get(fileName) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TaskFile getFile(@NotNull final String fileName) {
|
||||
return taskFiles.get(fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes state of task file
|
||||
*
|
||||
* @param lesson lesson which task belongs to
|
||||
*/
|
||||
public void init(final Lesson lesson, boolean isRestarted) {
|
||||
myLesson = lesson;
|
||||
for (TaskFile taskFile : taskFiles.values()) {
|
||||
taskFile.init(this, isRestarted);
|
||||
}
|
||||
}
|
||||
|
||||
public Task next() {
|
||||
Lesson currentLesson = this.myLesson;
|
||||
List<Task> taskList = myLesson.getTaskList();
|
||||
if (myIndex + 1 < taskList.size()) {
|
||||
return taskList.get(myIndex + 1);
|
||||
}
|
||||
Lesson nextLesson = currentLesson.next();
|
||||
if (nextLesson == null) {
|
||||
return null;
|
||||
}
|
||||
return StudyUtils.getFirst(nextLesson.getTaskList());
|
||||
}
|
||||
|
||||
public Task prev() {
|
||||
Lesson currentLesson = this.myLesson;
|
||||
if (myIndex - 1 >= 0) {
|
||||
return myLesson.getTaskList().get(myIndex - 1);
|
||||
}
|
||||
Lesson prevLesson = currentLesson.prev();
|
||||
if (prevLesson == null) {
|
||||
return null;
|
||||
}
|
||||
//getting last task in previous lesson
|
||||
return prevLesson.getTaskList().get(prevLesson.getTaskList().size() - 1);
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
public Lesson getLesson() {
|
||||
return myLesson;
|
||||
}
|
||||
|
||||
public String getTestsText() {
|
||||
return testsText;
|
||||
}
|
||||
|
||||
public void setTestsText(@NotNull final String testsText) {
|
||||
this.testsText = testsText;
|
||||
}
|
||||
|
||||
public void setText(@NotNull final String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VirtualFile getTaskDir(Project project) {
|
||||
String lessonDirName = StudyNames.LESSON_DIR + String.valueOf(myLesson.getIndex() + 1);
|
||||
String taskDirName = TASK_DIR + String.valueOf(myIndex + 1);
|
||||
VirtualFile courseDir = project.getBaseDir();
|
||||
if (courseDir != null) {
|
||||
VirtualFile lessonDir = courseDir.findChild(lessonDirName);
|
||||
if (lessonDir != null) {
|
||||
return lessonDir.findChild(taskDirName);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets text of resource file such as test input file or task text in needed format
|
||||
*
|
||||
* @param fileName name of resource file which should exist in task directory
|
||||
* @param wrapHTML if it's necessary to wrap text with html tags
|
||||
* @return text of resource file wrapped with html tags if necessary
|
||||
*/
|
||||
@Nullable
|
||||
public String getResourceText(@NotNull final Project project, @NotNull final String fileName, boolean wrapHTML) {
|
||||
VirtualFile taskDir = getTaskDir(project);
|
||||
if (taskDir != null) {
|
||||
return StudyUtils.getFileText(taskDir.getCanonicalPath(), fileName, wrapHTML, "UTF-8");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
-279
@@ -1,279 +0,0 @@
|
||||
package com.jetbrains.edu.learning.course;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.editor.markup.HighlighterLayer;
|
||||
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.xmlb.annotations.Transient;
|
||||
import com.jetbrains.edu.learning.StudyUtils;
|
||||
import com.jetbrains.edu.learning.TaskWindowDeleteHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implementation of task file which contains task windows for student to type in and
|
||||
* which is visible to student in project view
|
||||
*/
|
||||
|
||||
public class TaskFile implements Stateful {
|
||||
public String name;
|
||||
public String text;
|
||||
@SerializedName("placeholders")
|
||||
private List<AnswerPlaceholder> myAnswerPlaceholders = new ArrayList<AnswerPlaceholder>();
|
||||
|
||||
private Task myTask;
|
||||
@Transient
|
||||
private AnswerPlaceholder mySelectedAnswerPlaceholder = null;
|
||||
private int myIndex = -1;
|
||||
private boolean myUserCreated = false;
|
||||
private boolean myTrackChanges = true;
|
||||
private boolean myHighlightErrors = false;
|
||||
|
||||
/**
|
||||
* @return if all the windows in task file are marked as resolved
|
||||
*/
|
||||
@Transient
|
||||
public StudyStatus getStatus() {
|
||||
for (AnswerPlaceholder answerPlaceholder : myAnswerPlaceholders) {
|
||||
StudyStatus windowStatus = answerPlaceholder.getStatus();
|
||||
if (windowStatus == StudyStatus.Failed) {
|
||||
return StudyStatus.Failed;
|
||||
}
|
||||
if (windowStatus == StudyStatus.Unchecked) {
|
||||
return StudyStatus.Unchecked;
|
||||
}
|
||||
}
|
||||
return StudyStatus.Solved;
|
||||
}
|
||||
|
||||
public Task getTask() {
|
||||
return myTask;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Transient
|
||||
public AnswerPlaceholder getSelectedAnswerPlaceholder() {
|
||||
return mySelectedAnswerPlaceholder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param selectedAnswerPlaceholder window from this task file to be set as selected
|
||||
*/
|
||||
public void setSelectedAnswerPlaceholder(@NotNull final AnswerPlaceholder selectedAnswerPlaceholder) {
|
||||
if (selectedAnswerPlaceholder.getTaskFile() == this) {
|
||||
mySelectedAnswerPlaceholder = selectedAnswerPlaceholder;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Window may be set as selected only in task file which it belongs to");
|
||||
}
|
||||
}
|
||||
|
||||
public List<AnswerPlaceholder> getAnswerPlaceholders() {
|
||||
return myAnswerPlaceholders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates task files in its task folder in project user created
|
||||
*
|
||||
* @param taskDir project directory of task which task file belongs to
|
||||
* @param resourceRoot directory where original task file stored
|
||||
* @throws IOException
|
||||
*/
|
||||
public void create(@NotNull final VirtualFile taskDir, @NotNull final File resourceRoot,
|
||||
@NotNull final String name) throws IOException {
|
||||
String systemIndependentName = FileUtil.toSystemIndependentName(name);
|
||||
final int index = systemIndependentName.lastIndexOf("/");
|
||||
if (index > 0) {
|
||||
systemIndependentName = systemIndependentName.substring(index + 1);
|
||||
}
|
||||
File resourceFile = new File(resourceRoot, name);
|
||||
File fileInProject = new File(taskDir.getPath(), systemIndependentName);
|
||||
FileUtil.copy(resourceFile, fileInProject);
|
||||
}
|
||||
|
||||
public void drawAllWindows(Editor editor) {
|
||||
editor.getMarkupModel().removeAllHighlighters();
|
||||
for (AnswerPlaceholder answerPlaceholder : myAnswerPlaceholders) {
|
||||
answerPlaceholder.draw(editor);
|
||||
}
|
||||
final Document document = editor.getDocument();
|
||||
EditorActionManager.getInstance()
|
||||
.setReadonlyFragmentModificationHandler(document, new TaskWindowDeleteHandler(editor));
|
||||
createGuardedBlocks(editor);
|
||||
editor.getColorsScheme().setColor(EditorColors.READONLY_FRAGMENT_BACKGROUND_COLOR, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pos position in editor
|
||||
* @return task window located in specified position or null if there is no task window in this position
|
||||
*/
|
||||
@Nullable
|
||||
public AnswerPlaceholder getAnswerPlaceholder(@NotNull final Document document, @NotNull final LogicalPosition pos) {
|
||||
int line = pos.line;
|
||||
if (line >= document.getLineCount()) {
|
||||
return null;
|
||||
}
|
||||
int column = pos.column;
|
||||
int offset = document.getLineStartOffset(line) + column;
|
||||
for (AnswerPlaceholder tw : myAnswerPlaceholders) {
|
||||
if (tw.getLine() <= line) {
|
||||
int twStartOffset = tw.getRealStartOffset(document);
|
||||
final int length = tw.getLength() > 0 ? tw.getLength() : 0;
|
||||
int twEndOffset = twStartOffset + length;
|
||||
if (twStartOffset <= offset && offset <= twEndOffset) {
|
||||
return tw;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes state of task file
|
||||
*
|
||||
* @param task task which task file belongs to
|
||||
*/
|
||||
|
||||
public void init(final Task task, boolean isRestarted) {
|
||||
myTask = task;
|
||||
for (AnswerPlaceholder answerPlaceholder : myAnswerPlaceholders) {
|
||||
answerPlaceholder.init(this, isRestarted);
|
||||
}
|
||||
Collections.sort(myAnswerPlaceholders);
|
||||
for (int i = 0; i < myAnswerPlaceholders.size(); i++) {
|
||||
myAnswerPlaceholders.get(i).setIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index index of task file in list of task files of its task
|
||||
*/
|
||||
public void setIndex(int index) {
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
|
||||
public static void copy(@NotNull final TaskFile source, @NotNull final TaskFile target) {
|
||||
List<AnswerPlaceholder> sourceAnswerPlaceholders = source.getAnswerPlaceholders();
|
||||
List<AnswerPlaceholder> windowsCopy = new ArrayList<AnswerPlaceholder>(sourceAnswerPlaceholders.size());
|
||||
for (AnswerPlaceholder answerPlaceholder : sourceAnswerPlaceholders) {
|
||||
AnswerPlaceholder answerPlaceholderCopy = new AnswerPlaceholder();
|
||||
answerPlaceholderCopy.setLine(answerPlaceholder.getLine());
|
||||
answerPlaceholderCopy.setStart(answerPlaceholder.getStart());
|
||||
answerPlaceholderCopy.setLength(answerPlaceholder.getLength());
|
||||
answerPlaceholderCopy.setPossibleAnswer(answerPlaceholder.getPossibleAnswer());
|
||||
answerPlaceholderCopy.setIndex(answerPlaceholder.getIndex());
|
||||
windowsCopy.add(answerPlaceholderCopy);
|
||||
}
|
||||
target.setAnswerPlaceholders(windowsCopy);
|
||||
}
|
||||
|
||||
public void setAnswerPlaceholders(List<AnswerPlaceholder> answerPlaceholders) {
|
||||
this.myAnswerPlaceholders = answerPlaceholders;
|
||||
}
|
||||
|
||||
public void setStatus(@NotNull final StudyStatus status, @NotNull final StudyStatus oldStatus) {
|
||||
for (AnswerPlaceholder answerPlaceholder : myAnswerPlaceholders) {
|
||||
answerPlaceholder.setStatus(status, oldStatus);
|
||||
}
|
||||
}
|
||||
|
||||
public void setUserCreated(boolean userCreated) {
|
||||
myUserCreated = userCreated;
|
||||
}
|
||||
|
||||
public boolean isUserCreated() {
|
||||
return myUserCreated;
|
||||
}
|
||||
|
||||
public void navigateToFirstTaskWindow(@NotNull final Editor editor) {
|
||||
if (!myAnswerPlaceholders.isEmpty()) {
|
||||
AnswerPlaceholder firstAnswerPlaceholder = StudyUtils.getFirst(myAnswerPlaceholders);
|
||||
navigateToTaskWindow(editor, firstAnswerPlaceholder);
|
||||
}
|
||||
}
|
||||
|
||||
public void navigateToTaskWindow(@NotNull final Editor editor, @NotNull final AnswerPlaceholder answerPlaceholder) {
|
||||
if (!answerPlaceholder.isValid(editor.getDocument())) {
|
||||
return;
|
||||
}
|
||||
mySelectedAnswerPlaceholder = answerPlaceholder;
|
||||
LogicalPosition taskWindowStart = new LogicalPosition(answerPlaceholder.getLine(), answerPlaceholder.getStart());
|
||||
editor.getCaretModel().moveToLogicalPosition(taskWindowStart);
|
||||
}
|
||||
|
||||
public void navigateToFirstFailedTaskWindow(@NotNull final Editor editor) {
|
||||
for (AnswerPlaceholder answerPlaceholder : myAnswerPlaceholders) {
|
||||
if (answerPlaceholder.getStatus() != StudyStatus.Failed) {
|
||||
continue;
|
||||
}
|
||||
navigateToTaskWindow(editor, answerPlaceholder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasFailedTaskWindows() {
|
||||
return myAnswerPlaceholders.size() > 0 && getStatus() == StudyStatus.Failed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks symbols adjacent to task windows as read-only fragments
|
||||
*/
|
||||
public void createGuardedBlocks(@NotNull final Editor editor) {
|
||||
final Document document = editor.getDocument();
|
||||
if (document instanceof DocumentImpl) {
|
||||
DocumentImpl documentImpl = (DocumentImpl)document;
|
||||
List<RangeMarker> blocks = documentImpl.getGuardedBlocks();
|
||||
for (AnswerPlaceholder answerPlaceholder : myAnswerPlaceholders) {
|
||||
if (!answerPlaceholder.isValid(document)) {
|
||||
return;
|
||||
}
|
||||
int start = answerPlaceholder.getRealStartOffset(document);
|
||||
int end = start + answerPlaceholder.getLength();
|
||||
if (start != 0) {
|
||||
createGuardedBlock(editor, blocks, start - 1, start);
|
||||
}
|
||||
if (end != document.getTextLength()) {
|
||||
createGuardedBlock(editor, blocks, end, end + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void createGuardedBlock(Editor editor, List<RangeMarker> blocks, int start, int end) {
|
||||
RangeHighlighter rh = editor.getMarkupModel()
|
||||
.addRangeHighlighter(start, end, HighlighterLayer.LAST + 1, null, HighlighterTargetArea.EXACT_RANGE);
|
||||
blocks.add(rh);
|
||||
}
|
||||
|
||||
public boolean isTrackChanges() {
|
||||
return myTrackChanges;
|
||||
}
|
||||
|
||||
public void setTrackChanges(boolean trackChanges) {
|
||||
myTrackChanges = trackChanges;
|
||||
}
|
||||
|
||||
public boolean isHighlightErrors() {
|
||||
return myHighlightErrors;
|
||||
}
|
||||
|
||||
public void setHighlightErrors(boolean highlightErrors) {
|
||||
myHighlightErrors = highlightErrors;
|
||||
}
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
package com.jetbrains.edu.learning.course;
|
||||
|
||||
public class UserTest {
|
||||
private String input;
|
||||
private String output;
|
||||
private StringBuilder myInputBuffer = new StringBuilder();
|
||||
private StringBuilder myOutputBuffer = new StringBuilder();
|
||||
private boolean myEditable = false;
|
||||
|
||||
public String getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public void setInput(String input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public String getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
public void setOutput(String output) {
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
public StringBuilder getInputBuffer() {
|
||||
return myInputBuffer;
|
||||
}
|
||||
|
||||
public StringBuilder getOutputBuffer() {
|
||||
return myOutputBuffer;
|
||||
}
|
||||
|
||||
public boolean isEditable() {
|
||||
return myEditable;
|
||||
}
|
||||
|
||||
public void setEditable(boolean editable) {
|
||||
myEditable = editable;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user