Merge branch 'patch-1' of https://github.com/ryenus/intellij-community
[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 = placeholder.getRealLength();
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       answerPlaceholderCopy.setHint(answerPlaceholder.getHint());
122       answerPlaceholdersCopy.add(answerPlaceholderCopy);
123     }
124     target.name = source.name;
125     target.setAnswerPlaceholders(answerPlaceholdersCopy);
126   }
127
128   public void setUserCreated(boolean userCreated) {
129     myUserCreated = userCreated;
130   }
131
132   public boolean isUserCreated() {
133     return myUserCreated;
134   }
135
136   public boolean isTrackChanges() {
137     return myTrackChanges;
138   }
139
140   public void setTrackChanges(boolean trackChanges) {
141     myTrackChanges = trackChanges;
142   }
143
144   public boolean isHighlightErrors() {
145     return myHighlightErrors;
146   }
147
148   public void setHighlightErrors(boolean highlightErrors) {
149     myHighlightErrors = highlightErrors;
150   }
151
152   public void sortAnswerPlaceholders() {
153     Collections.sort(myAnswerPlaceholders, new AnswerPlaceholderComparator());
154     for (int i = 0; i < myAnswerPlaceholders.size(); i++) {
155       myAnswerPlaceholders.get(i).setIndex(i + 1);
156     }
157   }
158
159
160   @Override
161   public boolean equals(Object o) {
162     if (this == o) return true;
163     if (o == null || getClass() != o.getClass()) return false;
164
165     TaskFile that = (TaskFile)o;
166
167     if (getIndex() != that.getIndex()) return false;
168     if (!name.equals(that.name)) return false;
169
170     final List<AnswerPlaceholder> answerPlaceholders = getAnswerPlaceholders();
171     final List<AnswerPlaceholder> thatAnswerPlaceholders = that.getAnswerPlaceholders();
172     if (answerPlaceholders.size() != thatAnswerPlaceholders.size()) return false;
173     for (int i = 0; i < answerPlaceholders.size(); i++) {
174       final AnswerPlaceholder placeholder = answerPlaceholders.get(i);
175       final AnswerPlaceholder thatPlaceholder = thatAnswerPlaceholders.get(i);
176       if (!placeholder.equals(thatPlaceholder)) return false;
177     }
178     return true;
179   }
180
181   @Override
182   public int hashCode() {
183     int result = getIndex();
184     result = 31 * result + name.hashCode();
185     for (AnswerPlaceholder placeholder : myAnswerPlaceholders) {
186       result = 31 * result + placeholder.hashCode();
187     }
188     return result;
189   }
190 }