removed obsolete duplicated course formats

This commit is contained in:
Ekaterina Tuzova
2015-02-14 17:53:20 +03:00
parent 124c05e4fd
commit ab6527d454
15 changed files with 0 additions and 1717 deletions
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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);
}
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
}
}
@@ -1,6 +0,0 @@
package com.jetbrains.edu.learning.course;
public interface Stateful {
StudyStatus getStatus();
void setStatus(StudyStatus status, StudyStatus oldStatus);
}
@@ -1,8 +0,0 @@
package com.jetbrains.edu.learning.course;
/**
* @see {@link AnswerPlaceholder#myStatus}
*/
public enum StudyStatus {
Unchecked, Solved, Failed
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}