diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2015-12-23 20:46:07 +0100 |
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2015-12-23 20:46:07 +0100 |
| commit | 3bc43b689c1177ddeca6ea012aa74728f2b121c7 (patch) | |
| tree | b811150e0f40e9b66e32f764c827b5a4b8874f07 | |
| parent | 1d27f7b9aac4058f28aa8e56cb112ad1018614d7 (diff) | |
| download | uni-3bc43b689c1177ddeca6ea012aa74728f2b121c7.tar uni-3bc43b689c1177ddeca6ea012aa74728f2b121c7.tar.gz uni-3bc43b689c1177ddeca6ea012aa74728f2b121c7.tar.bz2 uni-3bc43b689c1177ddeca6ea012aa74728f2b121c7.tar.xz uni-3bc43b689c1177ddeca6ea012aa74728f2b121c7.zip | |
FFP 10
| -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 | -} | ||
