diff options
-rwxr-xr-x | ws2015/ffp/blaetter/10/FFP_U10_STM.hs | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/ws2015/ffp/blaetter/10/FFP_U10_STM.hs b/ws2015/ffp/blaetter/10/FFP_U10_STM.hs new file mode 100755 index 0000000..9a99e86 --- /dev/null +++ b/ws2015/ffp/blaetter/10/FFP_U10_STM.hs | |||
@@ -0,0 +1,491 @@ | |||
1 | {-# LANGUAGE RecordWildCards #-} | ||
2 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | ||
3 | |||
4 | -- Fortgeschrittene Funktionale Programmierung, | ||
5 | -- LMU, TCS, Wintersemester 2015/16 | ||
6 | -- Steffen Jost, Alexander Isenko | ||
7 | -- | ||
8 | -- Übungsblatt 10. 23.12.2015 | ||
9 | -- | ||
10 | -- Thema: Software Transactional Memory | ||
11 | -- | ||
12 | -- Hinweis: | ||
13 | -- Heute gibt es nur eine größere Aufgabe! | ||
14 | -- Wer damit fertig ist, sollte im Anschluß zuvor | ||
15 | -- übersprunge Aufgaben behandeln. | ||
16 | -- | ||
17 | -- Für diese Übung reicht auch ein Rechner mit einem Kern. | ||
18 | -- | ||
19 | |||
20 | |||
21 | -- A10-1 The Santa Claus problem | ||
22 | -- | ||
23 | -- Heute wollen wir uns von Haskell ganz nebenläufig | ||
24 | -- in eine weihnachtliche Stimmung versetzen lassen: | ||
25 | -- | ||
26 | -- Der Weihnachtsmann schläft friedlich am Nordpol. | ||
27 | -- Er läßt sich jedoch nur in zwei Situationen wecken: | ||
28 | -- 1) Alle seine 9 Rentiere sind bereits aus dem Karibik-Urlaub | ||
29 | -- zurückgekommen. Dann ist es bereits höchste Zeit, | ||
30 | -- diese an den Schlitten zu binden und die Geschenke | ||
31 | -- auzuliefern, denn die Rentiere möchten möglichst viel Zeit | ||
32 | -- in der Karibik verbringen und kommen ungern früher als | ||
33 | -- nötig zum Nordpol zurück. (Deswegen beeilen sich die | ||
34 | -- Rentiere auch so beim Ausliefern aller Geschenke!) | ||
35 | -- 2) Einige seiner elf Elfen haben Probleme mit | ||
36 | -- Innovationsmanagement oder Fertigungstechnik | ||
37 | -- für die Produktion der Geschenke und verlangen | ||
38 | -- ein Executive Meeting. | ||
39 | -- Da die Elfen immer irgendwelche Probleme haben, | ||
40 | -- läßt sich der Weihnachtsmann nur wecken, wenn | ||
41 | -- mindestens 3 Elfen nach einem Meeting verlangen; | ||
42 | -- Falls nur ein oder zwei Elfen ein Gesprächsbedürfnis | ||
43 | -- hegen, so müssen diese ruhig und erfurchtsvoll im | ||
44 | -- Vorzimmmer abwarten. | ||
45 | -- Da andererseits Meetings mit mehr als 3 Elfen | ||
46 | -- absolut unproduktiv sind, müssen alle Elfen ab dem | ||
47 | -- vierten ebenfalls warten, bis der Weihnachtsmann das | ||
48 | -- vorherige Meeting beendet hat (waren es z.B. insgesamt | ||
49 | -- 5 Elfen, dann müssen der vierte und fünfte Elf natürlich | ||
50 | -- erneut auf einen sechsten Elfen warten). | ||
51 | -- Der Weihnachtsmann beendet immer zuerst eine angefangene Aufgabe, | ||
52 | -- bevor er eine neue Aufgabe beginnt. | ||
53 | -- Treten beide Ereignisse gleichzeitig ein, so gibt er den Rentieren | ||
54 | -- den Vorrang, da die Geschenke ja pünktlich ausgeliefert werden müssen. | ||
55 | -- | ||
56 | -- Diese Problem wollen wir in Haskell mithilfe der | ||
57 | -- Implementationstechnik "Software Transactional Memory" | ||
58 | -- modellieren. | ||
59 | -- | ||
60 | -- | ||
61 | -- Diese Aufgabenstellung stammt aus "A new excercise in concurrency" | ||
62 | -- von John A. Trono, SIGCSE Bulletin, 26:8-10, 1994. | ||
63 | -- | ||
64 | -- Eine elegante Lösung dieses Problems unter Verwendung von | ||
65 | -- Software Transactional Memory wird detailliert behandelt von | ||
66 | -- Simon Peyton Jones im Kapitel "Beautiful Concurrency" | ||
67 | -- aus dem Buch "Beautiful Code" von Greg Wilson und Andy Oram, O'Reilly, 2007. | ||
68 | -- | ||
69 | -- | ||
70 | -- Das Gerüst in dieser Datei macht bereits einige Vorschläge, | ||
71 | -- doch Sie dürfen ALLES ABÄNDERN, z.B. zusätzliche Funktionsargumente | ||
72 | -- zum Übergeben von TVars werden vermutlich notwendig sein, etc. | ||
73 | -- | ||
74 | -- Versuchen Sie zuerst einmal, Santa & die Rentiere | ||
75 | -- zu synchronisieren und deaktivieren Sie die Elfen. | ||
76 | -- | ||
77 | -- Die zentrale Frage lautet: | ||
78 | -- Wie viele TVars welcher Art werden gebraucht? | ||
79 | -- | ||
80 | -- Am Ende dieser Datei befinden sich weitere Hinweise. | ||
81 | -- Schauen Sie dort nach, falls Sie nicht weiter wissen. | ||
82 | -- | ||
83 | |||
84 | |||
85 | |||
86 | module Main where | ||
87 | |||
88 | |||
89 | import Data.List | ||
90 | import Control.Concurrent.STM | ||
91 | import Control.Concurrent | ||
92 | import Control.Monad | ||
93 | import System.Random | ||
94 | import System.IO | ||
95 | |||
96 | import Control.DeepSeq | ||
97 | import qualified Data.Set as Set | ||
98 | import Data.Set (Set) | ||
99 | |||
100 | |||
101 | newtype ElfId = Elf Integer | ||
102 | deriving (Num, Enum, Show, Eq, Ord, NFData) | ||
103 | newtype RaindeerId = Raindeer Integer | ||
104 | deriving (Num, Enum, Show, Eq, Ord, NFData) | ||
105 | |||
106 | data GroupState id = GroupState | ||
107 | { waiting :: TVar [id] | ||
108 | , working :: TVar (Set id) | ||
109 | } | ||
110 | |||
111 | data State = State | ||
112 | { elfs :: GroupState ElfId | ||
113 | , raindeers :: GroupState RaindeerId | ||
114 | , outChan :: Chan String | ||
115 | } | ||
116 | |||
117 | initState :: IO State | ||
118 | initState = State | ||
119 | <$> initGroupState | ||
120 | <*> initGroupState | ||
121 | <*> newChan | ||
122 | |||
123 | initGroupState :: IO (GroupState a) | ||
124 | initGroupState = GroupState | ||
125 | <$> newTVarIO [] | ||
126 | <*> newTVarIO Set.empty | ||
127 | |||
128 | |||
129 | main :: IO () | ||
130 | main = initState >>= main' | ||
131 | |||
132 | main' :: State -> IO () | ||
133 | main' state@(State{..}) = do | ||
134 | mapM_ (forkIO . elf state) [1..11] | ||
135 | mapM_ (forkIO . rentier state) [1..9] | ||
136 | forkIO $ santa state | ||
137 | |||
138 | hSetBuffering stdin NoBuffering | ||
139 | forkIO $ forever $ readChan outChan >>= putStrLn | ||
140 | |||
141 | mloop | ||
142 | where | ||
143 | mloop = getChar >>= flip unless mloop . (== 'q') | ||
144 | |||
145 | |||
146 | |||
147 | santa :: State -> IO () | ||
148 | santa State{..} = forever . join . atomically $ deliver `orElse` meeting | ||
149 | where | ||
150 | deliver = do | ||
151 | check . (>= 9) . length =<< readTVar (waiting raindeers) | ||
152 | mapM_ (flip setWorking raindeers) =<< readTVar (waiting raindeers) | ||
153 | return $ do | ||
154 | writeChan outChan "Ho! Ho! Ho! Hüja Rentiere!" | ||
155 | atomically $ check . Set.null =<< readTVar (working raindeers) | ||
156 | meeting = do | ||
157 | check . (>= 3) . length =<< readTVar (waiting elfs) | ||
158 | mapM_ (flip setWorking elfs) =<< take 3 <$> readTVar (waiting elfs) | ||
159 | return $ do | ||
160 | writeChan outChan "Ho! Ho! Ho! Besprechung eröffnet!" | ||
161 | atomically $ check . Set.null =<< readTVar (working elfs) | ||
162 | |||
163 | |||
164 | |||
165 | elf :: State -> ElfId -> IO () | ||
166 | elf State{..} eid = forever $ do | ||
167 | writeChan outChan $ show eid ++ " arbeitet." | ||
168 | randomDelay 6 | ||
169 | writeChan outChan $ show eid ++ " ist traurig." | ||
170 | |||
171 | atomically $ setWaiting eid elfs | ||
172 | atomically $ check =<< isWorking eid elfs | ||
173 | |||
174 | writeChan outChan $ show eid ++ " hat Besprechung." | ||
175 | randomDelay 1 | ||
176 | writeChan outChan $ show eid ++ " hat Besprechung verlassen." | ||
177 | atomically $ unregister eid elfs | ||
178 | |||
179 | |||
180 | |||
181 | rentier :: State -> RaindeerId -> IO () | ||
182 | rentier State{..} rid = forever $ do | ||
183 | writeChan outChan $ show rid ++ " ist im Urlaub." | ||
184 | randomDelay 8 | ||
185 | writeChan outChan $ show rid ++ " ist zurück." | ||
186 | |||
187 | atomically $ setWaiting rid raindeers | ||
188 | atomically $ check =<< isWorking rid raindeers | ||
189 | |||
190 | writeChan outChan $ show rid ++ " liefert Geschenke." | ||
191 | randomDelay 2 | ||
192 | writeChan outChan $ show rid ++ " ist fertig mit ausliefern." | ||
193 | atomically $ unregister rid raindeers | ||
194 | |||
195 | |||
196 | |||
197 | -------------------- | ||
198 | -- Hilfsfunktionen | ||
199 | -------------------- | ||
200 | |||
201 | randomDelay :: Int -> IO () | ||
202 | -- Delay for a random time between 1 and n * 500,000 microseconds | ||
203 | randomDelay n = do | ||
204 | let t = n * 500000 | ||
205 | waitTime <- getStdRandom (randomR (1, t)) | ||
206 | threadDelay waitTime | ||
207 | |||
208 | snoc :: a -> [a] -> [a] | ||
209 | snoc = flip (++) . pure | ||
210 | |||
211 | setWaiting :: (Ord id, NFData id) => id -> GroupState id -> STM () | ||
212 | setWaiting id st@(GroupState{..}) = unregister id st >> modifyTVar' waiting (snoc id $!!) | ||
213 | |||
214 | setWorking :: (Ord id, NFData id) => id -> GroupState id -> STM () | ||
215 | setWorking id st@(GroupState{..}) = unregister id st >> modifyTVar' working (Set.insert id $!!) | ||
216 | |||
217 | isWorking :: (Ord id, NFData id) => id -> GroupState id -> STM Bool | ||
218 | isWorking id GroupState{..} = Set.member id <$> readTVar working | ||
219 | |||
220 | unregister :: (Ord id, NFData id) => id -> GroupState id -> STM () | ||
221 | unregister id GroupState{..} = do | ||
222 | modifyTVar' waiting (filter (/= id) $!!) | ||
223 | modifyTVar' working (Set.delete id $!!) | ||
224 | |||
225 | {- Eventuell nützliche Funktion aus Modul Control.Monad.STM: | ||
226 | |||
227 | check :: Bool -> STM () | ||
228 | check b = if b then return () else retry | ||
229 | |||
230 | -} | ||
231 | |||
232 | |||
233 | |||
234 | |||
235 | |||
236 | ---------------------------------------------------------------- | ||
237 | -- WEITERE HINWEISE: | ||
238 | ---------------------------------------------------------------- | ||
239 | |||
240 | |||
241 | |||
242 | {- | ||
243 | * Beide Quellen zur Aufgabe finden sich problemlos im Internet, | ||
244 | unter anderem auch im Haskell Center auf fpcomplete.com. | ||
245 | Die elegante Lösung von Simon Peyton Jones ist auf einem sehr hohen | ||
246 | Abstraktionsniveau, welches wir vermutlich nicht auf Anhieb in der | ||
247 | Übung erreichen können. | ||
248 | |||
249 | Natürlich ist es schön und vermeidet Fehler, wenn man zum Beispiel | ||
250 | den ähnlichen Code für Rentiere und Elfe mit einer generischen | ||
251 | Funktion abhandeln kann, aber für den Anfang is es okay, spezielleren | ||
252 | Code zu schreiben, so lange dieser korrekt ist. | ||
253 | Gemeinsamkeiten im Code kann man hinterher immer noch Erkennen | ||
254 | und generalisieren. | ||
255 | |||
256 | Unser Lösungsvorschlag im UniworX wird daher auch eine weniger elegante | ||
257 | Version zeigen. Es wird jedoch ausdrücklich empfohlen, hinterher | ||
258 | einmal auch die kürzere Lösung von Simon Peyton Jones durchzudenken. | ||
259 | -} | ||
260 | |||
261 | |||
262 | |||
263 | {- | ||
264 | * Die Grundidee ist wie folgt: | ||
265 | |||
266 | Jedes Rentier/Elf durchläuft folgende Endlosschleife: | ||
267 | 1. Eigene Arbeit erledigen (durch Aufruf an "randomDelay" symbolisiert) | ||
268 | 2. Bereitschaft an Weihnachtsmann Prozess signalisieren | ||
269 | 3. Warten, bis Weihnachtsmann Startzeichen gibt. | ||
270 | 4. Arbeit mit Weihnachtsmann erledigen (durch Aufruf an "randomDelay" symbolisiert) | ||
271 | 5. Weihnachtsmann das Ende der eigenen Arbeit signalisieren | ||
272 | |||
273 | Der Weihnachtsmann (bzw. dessen PA, da der Weihnachtsmann | ||
274 | selbst ja eigentlich schläft), prüft ständig ob genug | ||
275 | Rentiere oder Elfen seine Aufmerksamkeit verlangen, und | ||
276 | gibt ggf. den entsprechenden Rentieren/Elfen das Startsignal. | ||
277 | Danach wartet er darauf, dass diese noch das Ende der jeweiligen Aufgabe signalisieren. | ||
278 | -} | ||
279 | |||
280 | |||
281 | |||
282 | {- | ||
283 | Signalisieren soll ausschließlich über TVars erfolgen, | ||
284 | warten kann mit retry oder check (siehe Hilfsfunktionen) realisiert werden. | ||
285 | -} | ||
286 | |||
287 | |||
288 | |||
289 | {- | ||
290 | Die Antowrt auf die Frage, wie viele TVars welcher Art gebraucht werden, | ||
291 | kann ganz unterschiedlich beantwortet werden. | ||
292 | |||
293 | Zum Beispiel verwendet unser Lösungsvorschlag mehrere globale TVars, | ||
294 | während die Lösung von Simon Peyton Jones nur 2 in einem | ||
295 | speziellen Datentyp verpackte TVars verwendet, welche auf weitere, | ||
296 | je nach Aufgabe dynamisch angelegte, TVars verweisen. | ||
297 | -} | ||
298 | |||
299 | |||
300 | |||
301 | {- | ||
302 | |||
303 | Beispielausgabe mit vielen Extra-Ausgaben an der Konsole zum Verständnis des Ablaufs: | ||
304 | |||
305 | |||
306 | Elf 21 ist traurig. Wartezimmer vorher: 0 | ||
307 | Elf 16 ist traurig. Wartezimmer vorher: 1 | ||
308 | Elf 11 ist traurig. Wartezimmer vorher: 2 | ||
309 | Ho! Ho! Ho! Besprechung eröffnet [21,16,11] ! | ||
310 | Elf 21 hat Besprechung. | ||
311 | Elf 16 hat Besprechung. | ||
312 | Elf 11 hat Besprechung. | ||
313 | Rentier 8 ist zurück. Vorher im Stall: 0 | ||
314 | Elf 20 ist traurig. Wartezimmer vorher: 0 | ||
315 | Elf 13 ist traurig. Wartezimmer vorher: 1 | ||
316 | Rentier 7 ist zurück. Vorher im Stall: 1 | ||
317 | Ho! Ho! Ho! Besprechung vorbei! | ||
318 | Rentier 6 ist zurück. Vorher im Stall: 2 | ||
319 | Elf 14 ist traurig. Wartezimmer vorher: 2 | ||
320 | Elf 11 ist traurig. Wartezimmer vorher: 3 | ||
321 | Elf 17 ist traurig. Wartezimmer vorher: 4 | ||
322 | Elf 15 ist traurig. Wartezimmer vorher: 5 | ||
323 | Ho! Ho! Ho! Besprechung eröffnet [20,13,14] ! | ||
324 | Elf 20 hat Besprechung. | ||
325 | Elf 13 hat Besprechung. | ||
326 | Elf 14 hat Besprechung. | ||
327 | Rentier 2 ist zurück. Vorher im Stall: 3 | ||
328 | Ho! Ho! Ho! Besprechung vorbei! | ||
329 | Ho! Ho! Ho! Besprechung eröffnet [11,17,15] ! | ||
330 | Elf 11 hat Besprechung. | ||
331 | Elf 17 hat Besprechung. | ||
332 | Elf 15 hat Besprechung. | ||
333 | Elf 14 ist traurig. Wartezimmer vorher: 0 | ||
334 | Elf 13 ist traurig. Wartezimmer vorher: 1 | ||
335 | Elf 17 ist traurig. Wartezimmer vorher: 2 | ||
336 | Elf 19 ist traurig. Wartezimmer vorher: 3 | ||
337 | Elf 16 ist traurig. Wartezimmer vorher: 4 | ||
338 | Ho! Ho! Ho! Besprechung vorbei! | ||
339 | Ho! Ho! Ho! Besprechung eröffnet [14,13,17] ! | ||
340 | Elf 14 hat Besprechung. | ||
341 | Elf 13 hat Besprechung. | ||
342 | Elf 17 hat Besprechung. | ||
343 | Elf 18 ist traurig. Wartezimmer vorher: 2 | ||
344 | Elf 21 ist traurig. Wartezimmer vorher: 3 | ||
345 | Elf 12 ist traurig. Wartezimmer vorher: 4 | ||
346 | Ho! Ho! Ho! Besprechung vorbei! | ||
347 | Ho! Ho! Ho! Besprechung eröffnet [19,16,18] ! | ||
348 | Elf 19 hat Besprechung. | ||
349 | Elf 16 hat Besprechung. | ||
350 | Elf 18 hat Besprechung. | ||
351 | Rentier 9 ist zurück. Vorher im Stall: 4 | ||
352 | Rentier 3 ist zurück. Vorher im Stall: 5 | ||
353 | Elf 20 ist traurig. Wartezimmer vorher: 2 | ||
354 | Ho! Ho! Ho! Besprechung vorbei! | ||
355 | Ho! Ho! Ho! Besprechung eröffnet [21,12,20] ! | ||
356 | Elf 21 hat Besprechung. | ||
357 | Elf 12 hat Besprechung. | ||
358 | Elf 20 hat Besprechung. | ||
359 | Rentier 5 ist zurück. Vorher im Stall: 6 | ||
360 | Elf 15 ist traurig. Wartezimmer vorher: 0 | ||
361 | Rentier 4 ist zurück. Vorher im Stall: 7 | ||
362 | Ho! Ho! Ho! Besprechung vorbei! | ||
363 | Rentier 1 ist zurück. Vorher im Stall: 8 | ||
364 | Elf 12 ist traurig. Wartezimmer vorher: 1 | ||
365 | Elf 20 ist traurig. Wartezimmer vorher: 2 | ||
366 | Ho! Ho! Ho! Hüja Rentiere [1,4,5,3,9,2,6,7,8] ! | ||
367 | Rentier 8 liefert Geschenke. | ||
368 | Rentier 7 liefert Geschenke. | ||
369 | Rentier 6 liefert Geschenke. | ||
370 | Rentier 2 liefert Geschenke. | ||
371 | Rentier 9 liefert Geschenke. | ||
372 | Rentier 3 liefert Geschenke. | ||
373 | Rentier 5 liefert Geschenke. | ||
374 | Rentier 4 liefert Geschenke. | ||
375 | Rentier 1 liefert Geschenke. | ||
376 | Elf 17 ist traurig. Wartezimmer vorher: 3 | ||
377 | Elf 21 ist traurig. Wartezimmer vorher: 4 | ||
378 | Elf 11 ist traurig. Wartezimmer vorher: 5 | ||
379 | Elf 13 ist traurig. Wartezimmer vorher: 6 | ||
380 | Ho! Ho! Ho! Was für ein Fest! | ||
381 | Ho! Ho! Ho! Besprechung eröffnet [15,12,20] ! | ||
382 | Elf 15 hat Besprechung. | ||
383 | Elf 12 hat Besprechung. | ||
384 | Elf 20 hat Besprechung. | ||
385 | Rentier 6 ist zurück. Vorher im Stall: 0 | ||
386 | Ho! Ho! Ho! Besprechung vorbei! | ||
387 | Ho! Ho! Ho! Besprechung eröffnet [17,21,11] ! | ||
388 | Elf 17 hat Besprechung. | ||
389 | Elf 21 hat Besprechung. | ||
390 | Elf 11 hat Besprechung. | ||
391 | Elf 14 ist traurig. Wartezimmer vorher: 1 | ||
392 | Ho! Ho! Ho! Besprechung vorbei! | ||
393 | Elf 19 ist traurig. Wartezimmer vorher: 2 | ||
394 | Elf 16 ist traurig. Wartezimmer vorher: 3 | ||
395 | Rentier 9 ist zurück. Vorher im Stall: 1 | ||
396 | Elf 18 ist traurig. Wartezimmer vorher: 4 | ||
397 | Ho! Ho! Ho! Besprechung eröffnet [13,14,19] ! | ||
398 | Elf 13 hat Besprechung. | ||
399 | Elf 14 hat Besprechung. | ||
400 | Elf 19 hat Besprechung. | ||
401 | Elf 17 ist traurig. Wartezimmer vorher: 2 | ||
402 | Elf 12 ist traurig. Wartezimmer vorher: 3 | ||
403 | Rentier 3 ist zurück. Vorher im Stall: 2 | ||
404 | Ho! Ho! Ho! Besprechung vorbei! | ||
405 | Ho! Ho! Ho! Besprechung eröffnet [16,18,17] ! | ||
406 | Elf 16 hat Besprechung. | ||
407 | Elf 18 hat Besprechung. | ||
408 | Elf 17 hat Besprechung. | ||
409 | Elf 11 ist traurig. Wartezimmer vorher: 1 | ||
410 | Rentier 5 ist zurück. Vorher im Stall: 3 | ||
411 | Elf 14 ist traurig. Wartezimmer vorher: 2 | ||
412 | Elf 18 ist traurig. Wartezimmer vorher: 3 | ||
413 | Rentier 1 ist zurück. Vorher im Stall: 4 | ||
414 | Ho! Ho! Ho! Besprechung vorbei! | ||
415 | Ho! Ho! Ho! Besprechung eröffnet [12,11,14] ! | ||
416 | Elf 12 hat Besprechung. | ||
417 | Elf 11 hat Besprechung. | ||
418 | Elf 14 hat Besprechung. | ||
419 | Elf 15 ist traurig. Wartezimmer vorher: 1 | ||
420 | Elf 19 ist traurig. Wartezimmer vorher: 2 | ||
421 | Ho! Ho! Ho! Besprechung vorbei! | ||
422 | Ho! Ho! Ho! Besprechung eröffnet [18,15,19] ! | ||
423 | Elf 18 hat Besprechung. | ||
424 | Elf 15 hat Besprechung. | ||
425 | Elf 19 hat Besprechung. | ||
426 | Elf 21 ist traurig. Wartezimmer vorher: 0 | ||
427 | Rentier 8 ist zurück. Vorher im Stall: 5 | ||
428 | Rentier 2 ist zurück. Vorher im Stall: 6 | ||
429 | Elf 17 ist traurig. Wartezimmer vorher: 1 | ||
430 | Rentier 7 ist zurück. Vorher im Stall: 7 | ||
431 | Elf 13 ist traurig. Wartezimmer vorher: 2 | ||
432 | Elf 20 ist traurig. Wartezimmer vorher: 3 | ||
433 | Ho! Ho! Ho! Besprechung vorbei! | ||
434 | Ho! Ho! Ho! Besprechung eröffnet [21,17,13] ! | ||
435 | Elf 21 hat Besprechung. | ||
436 | Elf 17 hat Besprechung. | ||
437 | Elf 13 hat Besprechung. | ||
438 | Rentier 4 ist zurück. Vorher im Stall: 8 | ||
439 | Elf 16 ist traurig. Wartezimmer vorher: 1 | ||
440 | Elf 12 ist traurig. Wartezimmer vorher: 2 | ||
441 | Elf 19 ist traurig. Wartezimmer vorher: 3 | ||
442 | Ho! Ho! Ho! Besprechung vorbei! | ||
443 | Ho! Ho! Ho! Hüja Rentiere [4,7,2,8,1,5,3,9,6] ! | ||
444 | Rentier 6 liefert Geschenke. | ||
445 | Rentier 9 liefert Geschenke. | ||
446 | Rentier 3 liefert Geschenke. | ||
447 | Rentier 5 liefert Geschenke. | ||
448 | Rentier 1 liefert Geschenke. | ||
449 | Rentier 8 liefert Geschenke. | ||
450 | Rentier 2 liefert Geschenke. | ||
451 | Rentier 7 liefert Geschenke. | ||
452 | Rentier 4 liefert Geschenke. | ||
453 | Elf 17 ist traurig. Wartezimmer vorher: 4 | ||
454 | Elf 13 ist traurig. Wartezimmer vorher: 5 | ||
455 | Ho! Ho! Ho! Was für ein Fest! | ||
456 | Ho! Ho! Ho! Besprechung eröffnet [20,16,12] ! | ||
457 | Elf 20 hat Besprechung. | ||
458 | Elf 16 hat Besprechung. | ||
459 | Elf 12 hat Besprechung. | ||
460 | Rentier 3 ist zurück. Vorher im Stall: 0 | ||
461 | Ho! Ho! Ho! Besprechung vorbei! | ||
462 | Ho! Ho! Ho! Besprechung eröffnet [19,17,13] ! | ||
463 | Elf 19 hat Besprechung. | ||
464 | Elf 17 hat Besprechung. | ||
465 | Elf 13 hat Besprechung. | ||
466 | Rentier 5 ist zurück. Vorher im Stall: 1 | ||
467 | Elf 11 ist traurig. Wartezimmer vorher: 0 | ||
468 | Elf 16 ist traurig. Wartezimmer vorher: 1 | ||
469 | Rentier 4 ist zurück. Vorher im Stall: 2 | ||
470 | Elf 15 ist traurig. Wartezimmer vorher: 2 | ||
471 | Elf 14 ist traurig. Wartezimmer vorher: 3 | ||
472 | Elf 18 ist traurig. Wartezimmer vorher: 4 | ||
473 | Rentier 6 ist zurück. Vorher im Stall: 3 | ||
474 | Ho! Ho! Ho! Besprechung vorbei! | ||
475 | Ho! Ho! Ho! Besprechung eröffnet [11,16,15] ! | ||
476 | Elf 11 hat Besprechung. | ||
477 | Elf 16 hat Besprechung. | ||
478 | Elf 15 hat Besprechung. | ||
479 | Elf 21 ist traurig. Wartezimmer vorher: 2 | ||
480 | Elf 12 ist traurig. Wartezimmer vorher: 3 | ||
481 | Ho! Ho! Ho! Besprechung vorbei! | ||
482 | Ho! Ho! Ho! Besprechung eröffnet [14,18,21] ! | ||
483 | Elf 14 hat Besprechung. | ||
484 | Elf 18 hat Besprechung. | ||
485 | Elf 21 hat Besprechung. | ||
486 | Elf 14 ist traurig. Wartezimmer vorher: 1 | ||
487 | Rentier 2 ist zurück. Vorher im Stall: 4 | ||
488 | Ho! Ho! Ho! Besprechung vorbei! | ||
489 | q | ||
490 | |||
491 | -} | ||