Module excursion
[hide private]
[frames] | no frames]

Source Code for Module excursion

  1  ''' 
  2  Created on Aug 26, 2011 
  3   
  4  @author: santtu 
  5  ''' 
  6   
7 -class Excursion(object):
8 ''' 9 The class C{Excursion} represents excursions 10 that students can sign up for. Each excursion object has 11 a maximum number of "places" for students, a name and 12 a sequence number which indicates if the excursion is 13 a "re-run" of a previous one. An excursion object keeps 14 track of which students have signed up for the 15 excursion. There may be more students signed up for 16 an excursion than there are places, in the hopes that 17 places are freed by cancellations or more places are 18 added to the excursion. Such students are called "reserves". 19 See the method C{sign_up} for more details 20 about the signing up and queuing process. 21 ''' 22
23 - def __init__(self, name, number, places):
24 ''' 25 Creates a new excursion with the given name, sequence number 26 and number of places. No students are registered yet for 27 the new excursion. 28 29 @param name: the name of the excursion, e.g. "Nokian aula" 30 @param number: the sequence number of the excursion. 31 1 indicates that the excursion is organized for 32 the first time, a higher number indicates a 33 re-run of a previously organized excursion. 34 @param places: the number of students that can take part in 35 the excursion 36 ''' 37 self.name = name # fixed value 38 self.number = number # fixed value 39 self.places = places # gatherer 40 self.students = [] # container: all the student who have signed up, including reserves
41 42 43
44 - def get_description(self):
45 ''' 46 Returns a string description of the excursion's main data. This description 47 is of the form "C{Name #Number (StudentCount/Places)}" where 48 C{StudentCount} is the total number of students who have signed up 49 for the excursion, including reserves. Examples: 50 - C{Nokia #1 (25/50)}- C{Nokia #3 (53/50)}</UL> 51 52 @return: a string description of the excursion 53 ''' 54 return self.name + " #" + str(self.number) + " (" + str(len(self.students)) + "/" + str(self.places) + ")"
55 56 57
58 - def add_places(self, increase):
59 ''' 60 Adds more places to the excursion. 61 62 @param increase: a positive number indicating how many more 63 students the excursion can now accommodate 64 ''' 65 if increase > 0: 66 self.places += increase
67 68 69 70
71 - def get_places(self):
72 ''' 73 Returns the number of students that can take part in the 74 excursion. 75 76 @return: number of places 77 ''' 78 return self.places
79 80 81
82 - def has_place(self, student):
83 ''' 84 Returns a boolean value indicating if, as matters currently 85 stand, the student will be able to take part 86 in the excursion. That is, a return value of C{True} 87 means that the student will be able to participate if 88 not too many younger students sign up later. A return value 89 of C{False} means that either the given student has not 90 even tried to sign up for the excursion, or that the student is 91 a "reserve" and will not be able to participate unless places are 92 freed due to cancellations or more places are added to the excursion. 93 94 @param student: a student 95 @return: a boolean value indicating the student's queuing status, 96 as described above 97 ''' 98 if student not in self.students: 99 return False 100 index = self.students.index(student) 101 return index < self.places
102 103 104
105 - def get_reserve_position(self, student):
106 ''' 107 Determines if the given student is a "reserve", that is, 108 if the student has signed up but currently does not have 109 a place available. If so, determines the position of the 110 student in the queue of reserves. A positive return value 111 indicates the students position: 1 means the first of the 112 reserves (the one who will be the first to get a place if 113 someone cancels), 2 means the next reserve, and so on. 114 115 @param student: a student 116 @return: zero if the student is not a reserve, a positive number 117 indicating the student's position amongst the 118 reserves otherwise. 119 ''' 120 if student not in self.students: 121 return 0 122 index = self.students.index(student) 123 if index < self.places: 124 return 0 125 else: 126 return index - self.places + 1
127 128 129
130 - def sign_up(self, new_student):
131 ''' 132 Signs up the given student for the excursion. 133 If the given student was already signed up for the excursion, 134 nothing needs to be done. Otherwise, the excursion determines 135 the position in which the student is placed amongst other 136 students who have signed up. This is done according 137 to two rules: 138 139 - Younger students (in terms of years studied) always 140 have the preference over older students. That is, 141 a younger student will be able to "cut the line" and 142 get in before older ones. 143 - Of the students with the same year of study, the one 144 that signs up first will have the preference. 145 146 @param new_student: the student who is signing up 147 ''' 148 if len(self.students) == 0: 149 self.students.append(new_student) 150 elif self.students[0].is_older_than(new_student): 151 self.students.insert(0, new_student) 152 elif not (new_student in self.students): 153 index = len(self.students) # stepper: this index searches for the first "not-older" student in the list, starting at the end 154 while True: 155 index -= 1 156 current_student = self.students[index] # most-recent holder 157 if index < 1 or not current_student.is_older_than(new_student): 158 break 159 self.students.insert(index + 1, new_student)
160 161 162 163
164 - def cancel(self, student):
165 ''' 166 Cancels the given students registration for the excursion. 167 168 @param student: the cancelling student 169 ''' 170 self.students.remove(student)
171 172 173
174 - def get_participant_listing(self):
175 ''' 176 Returns a listing of the students who currently have places 177 on the excursion, in order. The listing is prefaced by a generic 178 description of the excursion obtained by calling 179 C{self.get_description()} The rest of the listing consists 180 of lines of the form " - StudentName (YearOfStudy)". E.g.:: 181 182 MiniExqu #1 (5/3) 183 - Bob (1) 184 - Adam (1) 185 - Cecilia (3) 186 187 Note that students in reserve are not included in this listing. 188 189 @return: a multi-line participant listing 190 @see: #has_place(Student) 191 @see: Student#get_description() 192 ''' 193 listing = self.get_description() 194 index = 0 # gatherer 195 while index < self.places and index < len(self.students): # stepper 196 listing += '\n - ' + self.students[index].get_description() 197 index += 1 198 199 return listing
200 201 202
203 - def get_reserves(self):
204 ''' 205 Returns the students who are in reserve for this excursion. That is, 206 returns a list containing the students who are queuing up in hopes of 207 cancellations or additional available places. 208 209 @return: a list of the reserves, in queueing order (if there are none, an empty list is returned) 210 ''' 211 queue = [] # container 212 for index in range(self.get_places(), len(self.students)): # stepper 213 queue.append(self.students[index]) 214 215 return queue
216 217 218
219 - def redo(self, places):
220 ''' 221 Creates and returns a new excursion which is a "re-run" of this 222 excursion. The new excursion has the same name as this one, 223 a sequence number which is higher by one than this one's, and the 224 given number of places available. Furthermore, all this excursion's 225 reserve students are moved (in the same order) to the newly created 226 re-run excursion. ("Moving" means that they are removed from the old 227 excursion and added to the new one.) 228 229 @param places: 230 @return: the new re-run excursion 231 ''' 232 rerun = Excursion(self.name, self.number + 1, places) 233 reserves = self.get_reserves() 234 for student in reserves: 235 self.students.remove(student) # could also use .subList.clear() 236 rerun.students.extend(reserves) 237 return rerun
238 239 240 if __name__ == '__main__': 241 pass 242