Merge remote-tracking branch 'origin/master' into medvedev/oc-11785
[idea/community.git] / python / educational-core / student / src / com / jetbrains / edu / learning / courseFormat / TaskFile.java
1 package com.jetbrains.edu.learning.courseFormat;
2
3 import com.google.gson.annotations.Expose;
4 import com.google.gson.annotations.SerializedName;
5 import com.intellij.openapi.editor.Document;
6 import com.intellij.openapi.editor.LogicalPosition;
7 import com.intellij.util.xmlb.annotations.Transient;
8 import org.jetbrains.annotations.NotNull;
9 import org.jetbrains.annotations.Nullable;
10
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
14
15 /**
16  * Implementation of task file which contains task windows for student to type in and
17  * which is visible to student in project view
18  */
19
20 public class TaskFile {
21   @SerializedName("placeholders")
22   @Expose
23   private List<AnswerPlaceholder> myAnswerPlaceholders = new ArrayList<AnswerPlaceholder>();
24   private int myIndex = -1;
25
26   @Expose
27   public String name;
28   @Expose
29   public String text;
30   @Transient private Task myTask;
31   private boolean myUserCreated = false;
32   private boolean myTrackChanges = true;
33   private boolean myHighlightErrors = false;
34
35   public void initTaskFile(final Task task, boolean isRestarted) {
36     setTask(task);
37     final List<AnswerPlaceholder> answerPlaceholders = getAnswerPlaceholders();
38     for (AnswerPlaceholder answerPlaceholder : answerPlaceholders) {
39       answerPlaceholder.initAnswerPlaceholder(this, isRestarted);
40     }
41     Collections.sort(answerPlaceholders, new AnswerPlaceholderComparator());
42     for (int i = 0; i < answerPlaceholders.size(); i++) {
43       answerPlaceholders.get(i).setIndex(i);
44     }
45   }
46
47   public List<AnswerPlaceholder> getAnswerPlaceholders() {
48     return myAnswerPlaceholders;
49   }
50
51   public void setAnswerPlaceholders(List<AnswerPlaceholder> answerPlaceholders) {
52     this.myAnswerPlaceholders = answerPlaceholders;
53   }
54
55   public void addAnswerPlaceholder(AnswerPlaceholder answerPlaceholder) {
56     myAnswerPlaceholders.add(answerPlaceholder);
57   }
58
59   public int getIndex() {
60     return myIndex;
61   }
62
63   public void setIndex(int index) {
64     myIndex = index;
65   }
66
67   @Transient
68   public Task getTask() {
69     return myTask;
70   }
71
72   @Transient
73   public void setTask(Task task) {
74     myTask = task;
75   }
76
77   /**
78    * @param pos position in editor
79    * @return task window located in specified position or null if there is no task window in this position
80    */
81   @Nullable
82   public AnswerPlaceholder getAnswerPlaceholder(@NotNull final Document document, @NotNull final LogicalPosition pos) {
83     return getAnswerPlaceholder(document, pos, false);
84   }
85
86   @Nullable
87   public AnswerPlaceholder getAnswerPlaceholder(@NotNull final Document document, @NotNull final LogicalPosition pos,
88                                                 boolean useAnswerLength) {
89     int line = pos.line;
90     if (line >= document.getLineCount()) {
91       return null;
92     }
93     int column = pos.column;
94     int offset = document.getLineStartOffset(line) + column;
95     for (AnswerPlaceholder placeholder : myAnswerPlaceholders) {
96       if (placeholder.getLine() <= line) {
97         int realStartOffset = placeholder.getRealStartOffset(document);
98         int placeholderLength = useAnswerLength ? placeholder.getPossibleAnswerLength() : placeholder.getLength();
99         final int length = placeholderLength > 0 ? placeholderLength : 0;
100         int endOffset = realStartOffset + length;
101         if (realStartOffset <= offset && offset <= endOffset) {
102           return placeholder;
103         }
104       }
105     }
106     return null;
107   }
108
109
110   public static void copy(@NotNull final TaskFile source, @NotNull final TaskFile target) {
111     List<AnswerPlaceholder> sourceAnswerPlaceholders = source.getAnswerPlaceholders();
112     List<AnswerPlaceholder> answerPlaceholdersCopy = new ArrayList<AnswerPlaceholder>(sourceAnswerPlaceholders.size());
113     for (AnswerPlaceholder answerPlaceholder : sourceAnswerPlaceholders) {
114       AnswerPlaceholder answerPlaceholderCopy = new AnswerPlaceholder();
115       answerPlaceholderCopy.setLine(answerPlaceholder.getLine());
116       answerPlaceholderCopy.setStart(answerPlaceholder.getStart());
117       answerPlaceholderCopy.setTaskText(answerPlaceholder.getTaskText());
118       answerPlaceholderCopy.setLength(answerPlaceholder.getLength());
119       answerPlaceholderCopy.setPossibleAnswer(answerPlaceholder.getPossibleAnswer());
120       answerPlaceholderCopy.setIndex(answerPlaceholder.getIndex());
121       answerPlaceholdersCopy.add(answerPlaceholderCopy);
122     }
123     target.name = source.name;
124     target.setAnswerPlaceholders(answerPlaceholdersCopy);
125   }
126
127   public void setUserCreated(boolean userCreated) {
128     myUserCreated = userCreated;
129   }
130
131   public boolean isUserCreated() {
132     return myUserCreated;
133   }
134
135   public boolean isTrackChanges() {
136     return myTrackChanges;
137   }
138
139   public void setTrackChanges(boolean trackChanges) {
140     myTrackChanges = trackChanges;
141   }
142
143   public boolean isHighlightErrors() {
144     return myHighlightErrors;
145   }
146
147   public void setHighlightErrors(boolean highlightErrors) {
148     myHighlightErrors = highlightErrors;
149   }
150
151   public void sortAnswerPlaceholders() {
152     Collections.sort(myAnswerPlaceholders, new AnswerPlaceholderComparator());
153     for (int i = 0; i < myAnswerPlaceholders.size(); i++) {
154       myAnswerPlaceholders.get(i).setIndex(i + 1);
155     }
156   }
157
158
159   @Override
160   public boolean equals(Object o) {
161     if (this == o) return true;
162     if (o == null || getClass() != o.getClass()) return false;
163
164     TaskFile that = (TaskFile)o;
165
166     if (getIndex() != that.getIndex()) return false;
167     if (!name.equals(that.name)) return false;
168
169     final List<AnswerPlaceholder> answerPlaceholders = getAnswerPlaceholders();
170     final List<AnswerPlaceholder> thatAnswerPlaceholders = that.getAnswerPlaceholders();
171     if (answerPlaceholders.size() != thatAnswerPlaceholders.size()) return false;
172     for (int i = 0; i < answerPlaceholders.size(); i++) {
173       final AnswerPlaceholder placeholder = answerPlaceholders.get(i);
174       final AnswerPlaceholder thatPlaceholder = thatAnswerPlaceholders.get(i);
175       if (!placeholder.equals(thatPlaceholder)) return false;
176     }
177     return true;
178   }
179
180   @Override
181   public int hashCode() {
182     int result = getIndex();
183     result = 31 * result + name.hashCode();
184     for (AnswerPlaceholder placeholder : myAnswerPlaceholders) {
185       result = 31 * result + placeholder.hashCode();
186     }
187     return result;
188   }
189 }