diff --git a/.pep8 b/.pep8 new file mode 100644 index 0000000..a2d556f --- /dev/null +++ b/.pep8 @@ -0,0 +1,2 @@ +[pycodestyle] +max_line_length = 99 diff --git a/00_example_render_byid/__init__.py b/00_example_render_byid/__init__.py index 7c6874b..f066308 100644 --- a/00_example_render_byid/__init__.py +++ b/00_example_render_byid/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/13np/__init__.py b/13np/__init__.py index 2747d5b..095c17a 100644 --- a/13np/__init__.py +++ b/13np/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/14np/__init__.py b/14np/__init__.py index ad50022..4e0ebb5 100644 --- a/14np/__init__.py +++ b/14np/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/16c3/__init__.py b/16c3/__init__.py index 98c1fc7..4c1ae0a 100644 --- a/16c3/__init__.py +++ b/16c3/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/1c2/__init__.py b/1c2/__init__.py index c49e297..05d4915 100644 --- a/1c2/__init__.py +++ b/1c2/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from itertools import zip_longest # URL to Schedule-XML diff --git a/30-jahre-btx/__init__.py b/30-jahre-btx/__init__.py index 54e55f8..86192ca 100644 --- a/30-jahre-btx/__init__.py +++ b/30-jahre-btx/__init__.py @@ -3,6 +3,7 @@ import svg.path, random from lxml import etree from renderlib import * +from schedulelib import * def introFrames(p): frames = 0 diff --git a/32c3sz/__init__.py b/32c3sz/__init__.py index e6f4557..f29f4c5 100644 --- a/32c3sz/__init__.py +++ b/32c3sz/__init__.py @@ -2,6 +2,7 @@ import subprocess from renderlib import * +from schedulelib import * def pyconFrames(params): frames = 500 diff --git a/36c3/__init__.py b/36c3/__init__.py index b6287b3..9a1c16b 100644 --- a/36c3/__init__.py +++ b/36c3/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * import svg.path diff --git a/DS2016/__init__.py b/DS2016/__init__.py index 3fcc4dc..10eeb17 100644 --- a/DS2016/__init__.py +++ b/DS2016/__init__.py @@ -3,7 +3,9 @@ from lxml import etree from slugify import slugify from renderlib import * +from schedulelib import * from renderlib import * +from schedulelib import * from easing import * diff --git a/README.md b/README.md index 2d5ef38..7143770 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Yes! That's what I want! ------------------------ Okay, let's go. - - Install python3, python3-lxml, python3-cssutils (or use virtualenv, see below), inkscape and libav-tools + - Install python3, python3-lxml, python3-cssutils, python3-wand (or use virtualenv, see below), inkscape and libav-tools - Fork this repo on github and clone your personal fork to your local system. - Copy one of the existing setup: 00_example_render_byid - If you are using a newer version of intro-outro-generator, don't copy any of the other projects, as the __init.py__ may not contain all mandatory parameters in the tasks function. @@ -28,7 +28,7 @@ Okay, let's go. - search for `def debug()` and comment the sections about outro (postroll) and pause - run `./make.py yourproject/ --debug` to generate your first intro - if it looks good, duplicate intro.svg to outro.svg (postroll) and pause.svg (pause-loop) and modify them according to your needs. You can use different IDs in your SVG if required - - modify outroFrames and pauseFrames like before an test them using `./make.py yourproject/ --debug` + - modify outroFrames and pauseFrames like before and test them using `./make.py yourproject/ --debug` - if everything look like you'd want them to, run `./make.py yourproject/`. - You can use any debianesque linux (can be headless) to generate the videos. More cores help more. - Run `./make-snapshots.sh yourproject/` to generate a png from a specific time-index of your .ts or .dv-files. You can run `./make-snapshots.sh yourproject/ 5` to get a png for the frame at the 5th second of all your clips. Default is 3 seconds. @@ -109,7 +109,7 @@ The animation sequence is controlled by the three frame-generator routines vorsp ### CSS-Style-Modifications `('logo', 'style', 'opacity', 1),` - locate object with id `logo` in the svg, parse its `style`-attribute as css-inline-string and change the value of the css-property `opacity` to 1. The Tupel-Element `'style'` is fixed and declares the type of action which is applied to the specified element. All other tupel-mebers can be modified to suit your needs. -To form an fade-in-opacity-animation, the frame-generator could look like this: +To form a fade-in-opacity-animation, the frame-generator could look like this: # three seconds of animation frames = 3*fps @@ -150,7 +150,7 @@ FEM/VOC-Tracker-Integration *that script-Z-thingy* The [FEM](http://fem.tu-ilmenau.de/) and the [VOC](https://c3voc.de/) uses a special Ticket-Tracker to keep track of the Talks on an event. Various tasks are performed around the recorded Videomaterial (preparing, cutting, encoding, releasing) - synchronized by the Tracker. The files starting with `script-Z` are experiments to integrate the intro-rendering into this process. On some Events the Schedule is very fluid with talks being addes or names changing over the whole conference. Using the Scripts to render the prerols when they are actually needed (and not some days before the conference) would help to get the always-freshest prerolls but it would an additional (computational intense) task to the publishing process. -Generating an Live-Stream-Overlay +Generating a Live-Stream-Overlay --------------------------------- While your working on your Video-Artwork you can create another required asset: the stream overlay. When we'll live-stream your Talks we can't send prerolls ovet the live-stream. To let your viewer now what program they are watching at, we usually overlay a transparent image over the live-stream like most television programs do, too. Just create another SVG of the size 1920×1080 (or 1024×576 if you're only targeting the legacy SD-Pipeline) and throw your logo into your prefered corner. To have it looking good we would suggest diff --git a/afu-tm18/__init__.py b/afu-tm18/__init__.py index 8453d2d..20c220c 100644 --- a/afu-tm18/__init__.py +++ b/afu-tm18/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/afu/__init__.py b/afu/__init__.py index c26fe21..2c05c87 100644 --- a/afu/__init__.py +++ b/afu/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * def introFrames(p): diff --git a/archconf2020/__init__.py b/archconf2020/__init__.py index 4690ed7..1d08f63 100644 --- a/archconf2020/__init__.py +++ b/archconf2020/__init__.py @@ -320,7 +320,7 @@ def debug(): def tasks(queue, args, idlist, skiplist): # iterate over all events extracted from the schedule xml-export - for event in renderlib.events(scheduleUrl): + for event in schedulelib.events(scheduleUrl): if not (idlist == []): if 000000 in idlist: print("skipping id (%s [%s])" % (event["title"], event["id"])) diff --git a/asg2017/__init__.py b/asg2017/__init__.py index 39c9297..3ee089c 100644 --- a/asg2017/__init__.py +++ b/asg2017/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/asg2019/__init__.py b/asg2019/__init__.py index f12d7a5..b640e45 100644 --- a/asg2019/__init__.py +++ b/asg2019/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/bornhack2021/__init__.py b/bornhack2021/__init__.py index 45c88ad..4659a8a 100644 --- a/bornhack2021/__init__.py +++ b/bornhack2021/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * import math diff --git a/bub2018/__init__.py b/bub2018/__init__.py index ee3528e..6771e62 100644 --- a/bub2018/__init__.py +++ b/bub2018/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * import math diff --git a/camp1999/__init__.py b/camp1999/__init__.py index c1ee07e..b7aaae4 100644 --- a/camp1999/__init__.py +++ b/camp1999/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'http://annaberg6.de/stuff/camp99/schedule.xml' diff --git a/camp2023/beon.ttf b/camp2023/beon.ttf new file mode 100644 index 0000000..525497f Binary files /dev/null and b/camp2023/beon.ttf differ diff --git a/camp2023/config.ini b/camp2023/config.ini new file mode 100644 index 0000000..e8c7ab6 --- /dev/null +++ b/camp2023/config.ini @@ -0,0 +1,35 @@ +[meta] +schedule = https://pretalx.c3voc.de/camp2023/schedule/export/schedule.xml +template = intro.mp4 +alpha = false +prores = false +inout_type = t + +[title] +in = 16 +out = 24 +fontfile = saira.ttf +fontsize = 100 +fontcolor = #FB48C4 +x = (w-text_w)/2 +y = 100 + +[speaker] +in = 16 +out = 24 +fontfile = saira.ttf +fontsize = 70 +fontcolor = #3FFF21 +x = (w-text_w)/2 +y = 800 + +[text] +in = 16 +out = 24 +fontfile = saira.ttf +fontsize = 45 +fontcolor = #FB48C4 +x = (w-text_w)/2 +y = 1000 +text = Chaos Communication Camp 2023 + diff --git a/camp2023/saira.ttf b/camp2023/saira.ttf new file mode 100644 index 0000000..df08ba0 Binary files /dev/null and b/camp2023/saira.ttf differ diff --git a/cc15/__init__.py b/cc15/__init__.py index c48bacc..d96c15d 100644 --- a/cc15/__init__.py +++ b/cc15/__init__.py @@ -2,6 +2,7 @@ import subprocess from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'http://www.fossgis.de/konferenz/2014/programm/schedule.de.xml' diff --git a/cccamp15/__init__.py b/cccamp15/__init__.py index 865cf61..5dcca26 100644 --- a/cccamp15/__init__.py +++ b/cccamp15/__init__.py @@ -2,6 +2,7 @@ import random, sys from renderlib import * +from schedulelib import * from easing import * from colour import Color diff --git a/cccamp19/config.ini b/cccamp19/config.ini index f3c0668..d723d7d 100644 --- a/cccamp19/config.ini +++ b/cccamp19/config.ini @@ -1,13 +1,14 @@ -[default] +[meta] schedule = https://fahrplan.events.ccc.de/camp/2019/Fahrplan/schedule.xml template = cccamp19_talks_intro_1080p.mov alpha = true prores = true +inout_type = n [title] in = 193 out = 324 -font = Marvel-Bold.ttf +fontfile = Marvel-Bold.ttf fontsize = 120 fontcolor = #c68100 x = (w-text_w)/2 @@ -16,7 +17,7 @@ y = 480 [speaker] in = 233 out = 324 -font = Marvel-Regular.ttf +fontfile = Marvel-Regular.ttf fontsize = 70 fontcolor = #c68100 x = (w-text_w)/2 @@ -25,10 +26,10 @@ y = 845 [text] in = 242 out = 324 -font = Marvel-Regular.ttf +fontfile = Marvel-Regular.ttf fontsize = 45 fontcolor = #c68100 x = (w-text_w)/2 y = 927 -text = 'chaos communication camp 2019' +text = chaos communication camp 2019 diff --git a/chaosradio/__init__.py b/chaosradio/__init__.py index 684d686..0da241f 100644 --- a/chaosradio/__init__.py +++ b/chaosradio/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * scheduleUrl = "" diff --git a/coreboot16/__init__.py b/coreboot16/__init__.py index b4266b9..6d1ed7a 100644 --- a/coreboot16/__init__.py +++ b/coreboot16/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/datengarten/__init__.py b/datengarten/__init__.py index 79f55f6..b9842aa 100644 --- a/datengarten/__init__.py +++ b/datengarten/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * scheduleUrl = "https://berlin.ccc.de/datengarten/index.xml" diff --git a/denog11/config.ini b/denog11/config.ini index 20367cd..89c8096 100644 --- a/denog11/config.ini +++ b/denog11/config.ini @@ -1,13 +1,14 @@ -[default] +[meta] schedule = https://pretalx.denog.de/denog11/schedule/export/schedule.xml template = denog11_intro_template.ts alpha = false prores = false +inout_type = n [title] in = 1 out = 6.5 -font = DejaVuSans.ttf +fontfile = DejaVuSans.ttf fontsize = 100 fontcolor = #f9cc12 x = 640 @@ -16,7 +17,7 @@ y = 200 [speaker] in = 2 out = 6.5 -font = DejaVuSans.ttf +fontfile = DejaVuSans.ttf fontsize = 60 fontcolor = #ffffff x = 640 @@ -25,10 +26,10 @@ y = 900 [text] in = 3 out = 6.5 -font = DejaVuSans.ttf +fontfile = DejaVuSans.ttf fontsize = 45 fontcolor = #ffffff x = 640 y = 1000 -text = '' +; text = diff --git a/denog7/__init__.py b/denog7/__init__.py index 2869b02..eaa074b 100644 --- a/denog7/__init__.py +++ b/denog7/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/denog8/__init__.py b/denog8/__init__.py index 2869b02..eaa074b 100644 --- a/denog8/__init__.py +++ b/denog8/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/divoc-hs/__init__.py b/divoc-hs/__init__.py index 1cd54e9..208644f 100644 --- a/divoc-hs/__init__.py +++ b/divoc-hs/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/divoc-ptt/__init__.py b/divoc-ptt/__init__.py index f7092df..83a8869 100644 --- a/divoc-ptt/__init__.py +++ b/divoc-ptt/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/ds14/__init__.py b/ds14/__init__.py index 90c8031..f1f65e5 100644 --- a/ds14/__init__.py +++ b/ds14/__init__.py @@ -4,6 +4,7 @@ import svg.path, random from lxml import etree from slugify import slugify from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'https://www.datenspuren.de/2014/fahrplan/schedule.xml' diff --git a/easing.py b/easing.py index c362019..a7deb10 100644 --- a/easing.py +++ b/easing.py @@ -4,208 +4,233 @@ import math + def easeLinear(t, b, c, d): - return c*t/d + b + return c*t/d + b def easeOutCubic(t, b, c, d): - t=float(t)/d-1 - return c*((t)*t*t + 1) + b + t = float(t)/d-1 + return c*((t)*t*t + 1) + b + def easeInCubic(t, b, c, d): - t=float(t)/d - return c*(t)*t*t + b; + t = float(t)/d + return c*(t)*t*t + b def easeInQuad(t, b, c, d): - t /= d - return c*t*t + b + t /= d + return c*t*t + b + def easeOutQuad(t, b, c, d): - t /= d - return -c * t*(t-2) + b + t /= d + return -c * t*(t-2) + b + def easeInOutQuad(t, b, c, d): - t /= d/2 - if t < 1: - return c/2*t*t + b - t-=1 - return -c/2 * (t*(t-2) - 1) + b + t /= d/2 + if t < 1: + return c/2*t*t + b + t -= 1 + return -c/2 * (t*(t-2) - 1) + b def easeInOutCubic(t, b, c, d): - t /= d/2 - if t < 1: - return c/2*t*t*t + b - t -= 2 - return c/2*(t*t*t + 2) + b + t /= d/2 + if t < 1: + return c/2*t*t*t + b + t -= 2 + return c/2*(t*t*t + 2) + b + def easeInQuart(t, b, c, d): - t /= d - return c*t*t*t*t + b + t /= d + return c*t*t*t*t + b + def easeOutQuart(t, b, c, d): - t /= d - t -= 1 - return -c * (t*t*t*t - 1) + b + t /= d + t -= 1 + return -c * (t*t*t*t - 1) + b + def easeInOutQuart(t, b, c, d): - t /= d/2 - if t < 1: - return c/2*t*t*t*t + b - t -= 2 - return -c/2 * (t*t*t*t - 2) + b + t /= d/2 + if t < 1: + return c/2*t*t*t*t + b + t -= 2 + return -c/2 * (t*t*t*t - 2) + b + def easeInQuint(t, b, c, d): - t /= d - return c*t*t*t*t*t + b + t /= d + return c*t*t*t*t*t + b + def easeOutQuint(t, b, c, d): - t /= d - t -= 1 - return c*(t*t*t*t*t + 1) + b + t /= d + t -= 1 + return c*(t*t*t*t*t + 1) + b + def easeInOutQuint(t, b, c, d): - t /= d/2 - if t < 1: - return c/2*t*t*t*t*t + b - t -= 2 - return c/2*(t*t*t*t*t + 2) + b + t /= d/2 + if t < 1: + return c/2*t*t*t*t*t + b + t -= 2 + return c/2*(t*t*t*t*t + 2) + b + def easeInSine(t, b, c, d): - return -c * math.cos(t/d * (math.pi/2)) + c + b + return -c * math.cos(t/d * (math.pi/2)) + c + b + def easeOutSine(t, b, c, d): - return c * math.sin(t/d * (math.pi/2)) + b + return c * math.sin(t/d * (math.pi/2)) + b def easeInOutSine(t, b, c, d): - return -c/2 * (math.cos(math.pi*t/d) - 1) + b + return -c/2 * (math.cos(math.pi*t/d) - 1) + b + def easeInExpo(t, b, c, d): - return c * math.pow( 2, 10 * (t/d - 1) ) + b + return c * math.pow(2, 10 * (t/d - 1)) + b + def easeOutExpo(t, b, c, d): - return c * ( -math.pow( 2, -10 * t/d ) + 1 ) + b + return c * (-math.pow(2, -10 * t/d) + 1) + b def easeInOutExpo(t, b, c, d): - t /= d/2 - if t < 1: - return c/2 * math.pow( 2, 10 * (t - 1) ) + b - t -= 1 - return c/2 * ( -math.pow( 2, -10 * t) + 2 ) + b + t /= d/2 + if t < 1: + return c/2 * math.pow(2, 10 * (t - 1)) + b + t -= 1 + return c/2 * (-math.pow(2, -10 * t) + 2) + b + def easeInCirc(t, b, c, d): - t /= d - return -c * (math.sqrt(1 - t*t) - 1) + b + t /= d + return -c * (math.sqrt(1 - t*t) - 1) + b + def easeOutCirc(t, b, c, d): - t /= d; - t -= 1 - return c * math.sqrt(1 - t*t) + b + t /= d + t -= 1 + return c * math.sqrt(1 - t*t) + b + def easeInOutCirc(t, b, c, d): - t /= d/2 - if t < 1: - return -c/2 * (math.sqrt(1 - t*t) - 1) + b - t -= 2 - return c/2 * (math.sqrt(1 - t*t) + 1) + b + t /= d/2 + if t < 1: + return -c/2 * (math.sqrt(1 - t*t) - 1) + b + t -= 2 + return c/2 * (math.sqrt(1 - t*t) + 1) + b -def easeInElastic(t, b, c, d, s = 1.70158): - a = c +def easeInElastic(t, b, c, d, s=1.70158): + a = c - if t == 0: - return b - t /= d - if t == 1: - return b + c + if t == 0: + return b + t /= d + if t == 1: + return b + c - p = d * 0.3 - if a < abs(c): - a = c - s = p / 4 - else: - s = p / (2 * math.pi) * math.asin(c / a) + p = d * 0.3 + if a < abs(c): + a = c + s = p / 4 + else: + s = p / (2 * math.pi) * math.asin(c / a) - t -= 1 - return -(a * pow(2, 10 * t) * math.sin((t * d - s) * (2 * math.pi) / p)) + b + t -= 1 + return -(a * pow(2, 10 * t) * math.sin((t * d - s) * (2 * math.pi) / p)) + b -def easeOutElastic(t, b, c, d, a = 1.70158): - if t == 0: - return b - t /= d - if t == 1: - return b + c - p = d * 0.3 - if a < abs(c): - a, s = c, p / 4 - else: - s = p / (2 * math.pi) * math.asin(c / a) +def easeOutElastic(t, b, c, d, a=1.70158): + if t == 0: + return b + t /= d + if t == 1: + return b + c - return a * pow(2, -10 * t) * math.sin((t * d - s) * (2 * math.pi) / p) + c + b + p = d * 0.3 + if a < abs(c): + a, s = c, p / 4 + else: + s = p / (2 * math.pi) * math.asin(c / a) -def easeInOutElastic(t, b, c, d, a = 1.70158): - if t == 0: - return b - t /= (d / 2) - if t == 2: - return b + c + return a * pow(2, -10 * t) * math.sin((t * d - s) * (2 * math.pi) / p) + c + b - p = d * (0.3 * 1.5) - if a < abs(c): - a, s = c, p / 4 - else: - s = p / (2 * math.pi) * math.asin(c / a) - if t < 1: - t -= 1 - return -0.5 * (a * pow(2, 10 * t) * math.sin((t * d - s) * (2 * math.pi) / p)) + b +def easeInOutElastic(t, b, c, d, a=1.70158): + if t == 0: + return b + t /= (d / 2) + if t == 2: + return b + c - t -= 1 - return a * pow(2, -10 * t) * math.sin((t * d - s) * (2 * math.pi) / p ) * 0.5 + c + b + p = d * (0.3 * 1.5) + if a < abs(c): + a, s = c, p / 4 + else: + s = p / (2 * math.pi) * math.asin(c / a) -def easeInBack(t, b, c, d, s = 1.70158): - t /= d - return c * t * t * ((s + 1) * t - s) + b + if t < 1: + t -= 1 + return -0.5 * (a * pow(2, 10 * t) * math.sin((t * d - s) * (2 * math.pi) / p)) + b -def easeOutBack(t, b, c, d, s = 1.70158): - t = t / d - 1 - return c * (t * t * ((s + 1) * t + s) + 1) + b + t -= 1 + return a * pow(2, -10 * t) * math.sin((t * d - s) * (2 * math.pi) / p) * 0.5 + c + b -def easeInOutBack(t, b, c, d, s = 1.70158): - t /= d / 2 - s *= 1.525 - if t < 1: - return c / 2 * (t * t * ((s + 1) * t - s)) + b; - t -= 2 - return c/2 * (t * t * ((s + 1) * t + s) + 2) + b; +def easeInBack(t, b, c, d, s=1.70158): + t /= d + return c * t * t * ((s + 1) * t - s) + b + + +def easeOutBack(t, b, c, d, s=1.70158): + t = t / d - 1 + return c * (t * t * ((s + 1) * t + s) + 1) + b + + +def easeInOutBack(t, b, c, d, s=1.70158): + t /= d / 2 + s *= 1.525 + if t < 1: + return c / 2 * (t * t * ((s + 1) * t - s)) + b + + t -= 2 + return c/2 * (t * t * ((s + 1) * t + s) + 2) + b + def easeInBounce(t, b, c, d): - return c - easeOutBounce(d-t, 0, c, d) + b; + return c - easeOutBounce(d-t, 0, c, d) + b + def easeOutBounce(t, b, c, d): - t /= d - if t < (1/2.75): - return c*(7.5625*t*t) + b; + t /= d + if t < (1/2.75): + return c*(7.5625*t*t) + b - elif t < (2/2.75): - t -= (1.5/2.75) - return c*(7.5625*t*t + 0.75) + b; + elif t < (2/2.75): + t -= (1.5/2.75) + return c*(7.5625*t*t + 0.75) + b - elif t < (2.5/2.75): - t -= (2.25/2.75) - return c*(7.5625*t*t + 0.9375) + b; + elif t < (2.5/2.75): + t -= (2.25/2.75) + return c*(7.5625*t*t + 0.9375) + b + + else: + t -= (2.625/2.75) + return c*(7.5625*t*t + 0.984375) + b - else: - t -= (2.625/2.75) - return c*(7.5625*t*t + 0.984375) + b; def easeInOutBounce(t, b, c, d): - if t < d/2: - return easeInBounce(t*2, 0, c, d) * .5 + b; + if t < d/2: + return easeInBounce(t*2, 0, c, d) * .5 + b - return easeOutBounce(t*2-d, 0, c, d) * .5 + c*.5 + b; + return easeOutBounce(t*2-d, 0, c, d) * .5 + c*.5 + b diff --git a/eh14/__init__.py b/eh14/__init__.py index 9d302ff..7373cae 100644 --- a/eh14/__init__.py +++ b/eh14/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * import math # URL to Schedule-XML diff --git a/eh15/__init__.py b/eh15/__init__.py index 443f443..1a612b8 100644 --- a/eh15/__init__.py +++ b/eh15/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'https://eh15.easterhegg.eu/frab/en/eh15/public/schedule.xml' diff --git a/eh17/__init__.py b/eh17/__init__.py index a45482c..6538749 100644 --- a/eh17/__init__.py +++ b/eh17/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * import svg.path import random @@ -277,7 +278,7 @@ def tasks(queue, args, idlist, skiplist): if event['id'] == 8496: eventTitle = 'Know your tools - I’m firing my laser! -' - + # generate a task description and put them into the queue queue.put(Rendertask( infile='intro.svg', diff --git a/emf2016/__init__.py b/emf2016/__init__.py index cda51e3..942e8e2 100644 --- a/emf2016/__init__.py +++ b/emf2016/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML @@ -31,7 +32,7 @@ def introFrames(p): ('text', 'style', 'opacity', easeLinear(i, 1, 0, frames)), ('bg', 'style', 'opacity', easeLinear(i, 1, 0, frames)), ) - + frames = int(fps/2) for i in range(0, frames): yield ( @@ -40,7 +41,7 @@ def introFrames(p): ('text', 'style', 'opacity', 0), ('bg', 'style', 'opacity',0), ) - + # Show Sponsor frames = 5*fps for i in range(0, frames): diff --git a/emf2018/__init__.py b/emf2018/__init__.py index 64f561f..6147ce2 100644 --- a/emf2018/__init__.py +++ b/emf2018/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML @@ -15,13 +16,13 @@ def introFrames(p): nr = p['$id']; - # 1 Sekunde nix + # 1 Sekunde nix frames = 1*fps for i in range(0, frames): givenFrame += 1 yield ( ('bg', 'attr', '{http://www.w3.org/1999/xlink}href', "given-frames/frame%04d.png" % (givenFrame)), - ('layer1', 'style', 'opacity', "%.4f" % 0), # nix + ('layer1', 'style', 'opacity', "%.4f" % 0), # nix # ('text', 'attr', 'transform', 'translate(%.4f, 0)' % easeOutQuad(i, move, -move, frames)), ) @@ -44,7 +45,7 @@ def introFrames(p): ('layer1', 'style', 'opacity', "%.4f" %1), # ('text', 'attr', 'transform', 'translate(%.4f, 0)' % easeOutQuad(i, move, -move, frames)), ) - + # 1 Sekunde Text Fadeout frames = 1*fps for i in range(0, frames): @@ -54,7 +55,7 @@ def introFrames(p): ('layer1', 'style', 'opacity', "%.4f" % easeInQuad(i, 1, -1, frames)), # ('text', 'attr', 'transform', 'translate(%.4f, 0)' % easeOutQuad(i, move, -move, frames)), ) - + # Sponsors frames = 187 for i in range(0, frames): diff --git a/fiffkon/__init__.py b/fiffkon/__init__.py index e686fda..c535c32 100644 --- a/fiffkon/__init__.py +++ b/fiffkon/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * import math # URL to Schedule-XML diff --git a/fiffkon16/__init__.py b/fiffkon16/__init__.py index 6b6600a..851dc2e 100644 --- a/fiffkon16/__init__.py +++ b/fiffkon16/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * import math diff --git a/fiffkon17/__init__.py b/fiffkon17/__init__.py index b8a13b1..2979554 100644 --- a/fiffkon17/__init__.py +++ b/fiffkon17/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * import math diff --git a/fiffkon18/__init__.py b/fiffkon18/__init__.py index dfbf609..5b0f51a 100644 --- a/fiffkon18/__init__.py +++ b/fiffkon18/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * import math diff --git a/fiffkon21/__init__.py b/fiffkon21/__init__.py index 2510aa0..7afd707 100644 --- a/fiffkon21/__init__.py +++ b/fiffkon21/__init__.py @@ -2,6 +2,7 @@ # vim: tabstop=4 shiftwidth=4 expandtab from renderlib import * +from schedulelib import * from easing import * import math diff --git a/forumoe/__init__.py b/forumoe/__init__.py index 1613807..ea0815b 100644 --- a/forumoe/__init__.py +++ b/forumoe/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/forumoe19/__init__.py b/forumoe19/__init__.py index 906ec4c..c8c88a8 100644 --- a/forumoe19/__init__.py +++ b/forumoe19/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/foss4g-2016/__init__.py b/foss4g-2016/__init__.py index 0ba19a7..c37c272 100644 --- a/foss4g-2016/__init__.py +++ b/foss4g-2016/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/foss4g-2019/__init__.py b/foss4g-2019/__init__.py index 72da60e..81dea26 100644 --- a/foss4g-2019/__init__.py +++ b/foss4g-2019/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * import svg.path @@ -160,7 +161,7 @@ def pauseFrames(params): ('text1', 'style', 'opacity', 0), ('text2', 'style', 'opacity', 0), ) - + def debug(): render('intro.svg', '../intro.ts', diff --git a/fossgis14/__init__.py b/fossgis14/__init__.py index b71e4cb..6008f08 100644 --- a/fossgis14/__init__.py +++ b/fossgis14/__init__.py @@ -2,6 +2,7 @@ import subprocess from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'http://www.fossgis.de/konferenz/2014/programm/schedule.de.xml' diff --git a/fossgis15/__init__.py b/fossgis15/__init__.py index ac2b287..562bfb6 100644 --- a/fossgis15/__init__.py +++ b/fossgis15/__init__.py @@ -2,6 +2,7 @@ import subprocess from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'http://www.fossgis.de/konferenz/2015/programm/schedule.de.xml' diff --git a/fossgis16/__init__.py b/fossgis16/__init__.py index 2cf3bf3..c04f3d5 100644 --- a/fossgis16/__init__.py +++ b/fossgis16/__init__.py @@ -2,6 +2,7 @@ import subprocess from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/fossgis17/__init__.py b/fossgis17/__init__.py index c79c77f..cd6958c 100644 --- a/fossgis17/__init__.py +++ b/fossgis17/__init__.py @@ -2,6 +2,7 @@ import subprocess from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/fossgis19/__init__.py b/fossgis19/__init__.py index c64a235..3ab41ba 100755 --- a/fossgis19/__init__.py +++ b/fossgis19/__init__.py @@ -2,6 +2,7 @@ import subprocess from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/fossgis20/__init__.py b/fossgis20/__init__.py index df64e9a..20bfd26 100644 --- a/fossgis20/__init__.py +++ b/fossgis20/__init__.py @@ -2,6 +2,7 @@ import subprocess from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/froscon2014/__init__.py b/froscon2014/__init__.py index 6fb9db8..9946a49 100644 --- a/froscon2014/__init__.py +++ b/froscon2014/__init__.py @@ -3,6 +3,7 @@ import svg.path from lxml import etree from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'http://programm.froscon.de/2014/schedule.xml' diff --git a/froscon2015/__init__.py b/froscon2015/__init__.py index 30f1adb..5c53afa 100644 --- a/froscon2015/__init__.py +++ b/froscon2015/__init__.py @@ -3,6 +3,7 @@ import svg.path from lxml import etree from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/froscon2016/__init__.py b/froscon2016/__init__.py index 9d95357..06c3765 100644 --- a/froscon2016/__init__.py +++ b/froscon2016/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * import svg.path diff --git a/froscon2017/__init__.py b/froscon2017/__init__.py index 92039d5..143ab25 100644 --- a/froscon2017/__init__.py +++ b/froscon2017/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * import svg.path diff --git a/froscon2018/__init__.py b/froscon2018/__init__.py index 6aa79ab..bdde5c5 100644 --- a/froscon2018/__init__.py +++ b/froscon2018/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * import svg.path diff --git a/froscon2019/__init__.py b/froscon2019/__init__.py index 6b77980..af6786a 100644 --- a/froscon2019/__init__.py +++ b/froscon2019/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * import svg.path diff --git a/froscon2020/__init__.py b/froscon2020/__init__.py index 99787cf..37b0b4c 100644 --- a/froscon2020/__init__.py +++ b/froscon2020/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * import svg.path diff --git a/froscon2022/__init__.py b/froscon2022/__init__.py index 4df93e5..c14ae06 100644 --- a/froscon2022/__init__.py +++ b/froscon2022/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * import svg.path diff --git a/fusion16/__init__.py b/fusion16/__init__.py index 2acc41f..17bd760 100644 --- a/fusion16/__init__.py +++ b/fusion16/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/fusion18/__init__.py b/fusion18/__init__.py index 0a75727..0ce4ffb 100644 --- a/fusion18/__init__.py +++ b/fusion18/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/fusion19/__init__.py b/fusion19/__init__.py index f7b09ab..0f5f245 100644 --- a/fusion19/__init__.py +++ b/fusion19/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/fusion22/__init__.py b/fusion22/__init__.py index 04bb03f..21ff12d 100644 --- a/fusion22/__init__.py +++ b/fusion22/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/glt19/__init__.py b/glt19/__init__.py index 7c61455..4580856 100644 --- a/glt19/__init__.py +++ b/glt19/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/glt22/__init__.py b/glt22/__init__.py index 1053f05..afc95b2 100644 --- a/glt22/__init__.py +++ b/glt22/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/god2024/__init__.py b/god2024/__init__.py new file mode 100644 index 0000000..c04c938 --- /dev/null +++ b/god2024/__init__.py @@ -0,0 +1,145 @@ +#!/usr/bin/python3 + +from renderlib import * +from schedulelib import * +from easing import * + +# URL to Schedule-XML +scheduleUrl = 'https://import.c3voc.de/schedule/god2024.xml?showall=yes' + +titlemap = { + +} + +def introFrames(p): + givenFrame = 0 + + nr = p['$id']; + + # 1 Sekunden nix + frames = 1*fps + for i in range(0, frames): + givenFrame += 1 + yield ( + ('bg', 'attr', '{http://www.w3.org/1999/xlink}href', "given-frames/frame%04d.png" % (givenFrame)), + ('layer1', 'style', 'opacity', "%.4f" % 0), # nix + # ('text', 'attr', 'transform', 'translate(%.4f, 0)' % easeOutQuad(i, move, -move, frames)), + ) + + # 1 Sekunde Text Fadein + frames = 1*fps + for i in range(0, frames): + givenFrame += 1 + yield ( + ('bg', 'attr', '{http://www.w3.org/1999/xlink}href', "given-frames/frame%04d.png" % (givenFrame)), + ('layer1', 'style', 'opacity', "%.4f" % easeLinear(i, 0, 1, frames)), + # ('text', 'attr', 'transform', 'translate(%.4f, 0)' % easeOutQuad(i, move, -move, frames)), + ) + + # 5 Sekunden Text + frames = 5*fps + for i in range(0, frames): + givenFrame += 1 + yield ( + ('bg', 'attr', '{http://www.w3.org/1999/xlink}href', "given-frames/frame%04d.png" % (givenFrame)), + ('layer1', 'style', 'opacity', "%.4f" %1), + # ('text', 'attr', 'transform', 'translate(%.4f, 0)' % easeOutQuad(i, move, -move, frames)), + ) + +def outroFrames(p): + xml = etree.parse('god2024/artwork/outro.svg').getroot() + + frames = int(5*fps) + for i in range(0, frames): + yield () + +def pauseFrames(p): + # 1 sekunden fade in + frames = 1*fps + for i in range(0, frames): + yield ( + ('text1', 'style', 'opacity', "%.4f" % easeLinear(i, 0, 1, frames)), + ) + + # 1 sekunde sehen + for i in range(0, frames): + yield ( + ('text1', 'style', 'opacity', "%.4f" % 1), + ) + + # 1 sekunde fadeout + for i in range(0, frames): + yield ( + ('text1', 'style', 'opacity', "%.4f" % easeLinear(i, 1, -1, frames)), + ) + + # 1 sekunde bild + for i in range(0, frames): + yield ( + ('text1', 'style', 'opacity', "%.4f" % 0), + ) + +def debug(): + render( + 'intro.svg', + '../intro.ts', + introFrames, + { + '$id': 65, + '$title': 'OWASP Juice Shop 10th anniversary: Is it still fresh?'.upper(), + '$subtitle': '', + '$personnames': 'Jannik Hollenbach'.upper(), + #'only_render_frame': 353 + 'only_rerender_frames_after': 225 + } + ) + + # render( + # 'pause.svg', + # '../pause.ts', + # pauseFrames + # ) + +def tasks(queue, args, id_list, skip_list): + if not 'outro' in skip_list: + # place a task for the outro into the queue + queue.put(Rendertask( + infile = 'outro.svg', + outfile = 'outro.ts', + sequence = outroFrames + )) + + if not 'pause' in skip_list: + # place the pause-sequence into the queue + queue.put(Rendertask( + infile = 'pause.svg', + outfile = 'pause.ts', + sequence = pauseFrames + )) + + # iterate over all events extracted from the schedule xml-export + for event in events(scheduleUrl, titlemap): + + # skip events which will not be recorded + if event['room'] not in ('Da Capo',) or event['track'] == 'Nomnom': + print("skipping room %s (%s [%s])" % (event['room'], event['title'], event['id'])) + continue + + # when id_list is not empty, only render events which are in id_list + if id_list and int(event['id']) not in id_list: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + + # generate a task description and put them into the queue + queue.put(Rendertask( + infile = 'intro.svg', + outfile = str(event['id']) + ".ts", + sequence = introFrames, + parameters = { + '$id': event['id'], + '$title': event['title'].upper(), + '$subtitle': event['subtitle'], + '$personnames': event['personnames'].upper(), + } + )) + diff --git a/god2024/artwork/intro.svg b/god2024/artwork/intro.svg new file mode 100644 index 0000000..4a79ff0 --- /dev/null +++ b/god2024/artwork/intro.svg @@ -0,0 +1,101 @@ + + + +image/svg+xml$title$personnames diff --git a/god2024/artwork/outro.svg b/god2024/artwork/outro.svg new file mode 100644 index 0000000..8097ff8 --- /dev/null +++ b/god2024/artwork/outro.svg @@ -0,0 +1,131 @@ + + + +image/svg+xmlCreative Commons Attribution 4.0 International http://creativecommons.org/licenses/by/4.0/ diff --git a/god2024/artwork/pause.svg b/god2024/artwork/pause.svg new file mode 100644 index 0000000..6dd0f4e --- /dev/null +++ b/god2024/artwork/pause.svg @@ -0,0 +1,78 @@ + + + +image/svg+xmlPAUSE diff --git a/gpn15/__init__.py b/gpn15/__init__.py index f583648..7effafb 100644 --- a/gpn15/__init__.py +++ b/gpn15/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'http://bl0rg.net/~andi/gpn15-fahrplan/schedule.xml' diff --git a/gpn16/__init__.py b/gpn16/__init__.py index 3f622a9..9ac1b00 100644 --- a/gpn16/__init__.py +++ b/gpn16/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/gpn20/__init__.py b/gpn20/__init__.py index c2629d9..cd2d5e7 100644 --- a/gpn20/__init__.py +++ b/gpn20/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/guadec16/__init__.py b/guadec16/__init__.py index e202707..14dee6b 100644 --- a/guadec16/__init__.py +++ b/guadec16/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML @@ -100,7 +101,7 @@ def pauseFrames(p): yield ( ('onhold', 'style', 'opacity', "%.4f" % easeLinear(i, 1, -0.8, frames-1)), ) - + frames = int(1.5*fps) for i in range(0, frames): yield ( @@ -116,7 +117,7 @@ def outroFrames(p): scale = easeLinear(i, 1.3, 0.3 , frames-1) opacity = 0 if i > int(frames*0.7): - opacity = easeLinear(int(i-frames*0.7), 0, 1, int(frames-frames*0.7)-1) + opacity = easeLinear(int(i-frames*0.7), 0, 1, int(frames-frames*0.7)-1) yield ( ('guadeclogoscale', 'attr', 'transform', 'scale({scale},{scale})'.format(scale=scale),), ('fadetoblack', 'style', 'opacity', '{opac}'.format(opac=opacity),), @@ -129,7 +130,7 @@ def outroFrames(p): ('fadetoblack', 'style', 'opacity', "1"), ) - + def debug(): render( 'intro.svg', @@ -162,7 +163,7 @@ def tasks(queue, args): if not str(event['id']) in args: continue - if len(event['title']) < 71: + if len(event['title']) < 71: params = { '$title': event['title'], '$longtitle': '', diff --git a/hackerhotel2024/__init__.py b/hackerhotel2024/__init__.py new file mode 100644 index 0000000..ca82d00 --- /dev/null +++ b/hackerhotel2024/__init__.py @@ -0,0 +1,140 @@ +#!/usr/bin/python3 + +from renderlib import * +from schedulelib import * +from easing import * + +# URL to Schedule-XML +scheduleUrl = 'https://pretalx.hackerhotel.nl/hackerhotel-2024/schedule.xml' + +def bounce(i, min, max, frames): + if i == frames - 1: + return 0 + + if i <= frames/2: + return easeInOutQuad(i, min, max, frames/2) + else: + return max - easeInOutQuad(i - frames/2, min, max, frames/2) + +def introFrames(parameters): + # 3 Sekunde Text Fadein + frames = 1*fps + for i in range(0, frames): + yield ( + ('textblock', 'style', 'opacity', "%.4f" % easeLinear(i, 0, 1, frames)), + ) + + # 4 Sekunden stehen lassen + frames = 4*fps + for i in range(0, frames): + yield () + + # 1 Sekunde Fade to black layer + frames = 1*fps + for i in range(0, frames): + yield ( + ('all', 'style', 'opacity', "%.4f" % easeLinear(i, 1, -1, frames)), + ('textblock', 'style', 'opacity', "%.4f" % easeLinear(i, 1, -1, frames)), + ) + +def pauseFrames(parameters): + #5 Seconds Fade-In Hacker Fade-Out Hotel + frames = 5*fps + for i in range(0, frames): + yield ( + ('logohacker', 'style', 'opacity', "%.4f" % easeLinear(i, 0, 1, frames)), + ('logohotel', 'style', 'opacity', "%.4f" % easeLinear(i, 1, -1, frames)), + ) + #5 Seconds Fade-In Hotel Fade-Out Hacker + frames = 5*fps + for i in range(0, frames): + yield ( + ('logohacker', 'style', 'opacity', "%.4f" % easeLinear(i, 1, -1, frames)), + ('logohotel', 'style', 'opacity', "%.4f" % easeLinear(i, 0, 1, frames)), + ) + +def outroFrames(p): + # 4 Sekunden stehen bleiben + frames = 4*fps + for i in range(0, frames): + yield [] + # 1 Sekunde Fade to black layer + frames = 1*fps + for i in range(0, frames): + yield ( + ('all', 'style', 'opacity', "%.4f" % easeLinear(i, 1, -1, frames)), + ) + +def debug(): + render( + 'intro.svg', + '../intro.ts', + introFrames, + { + '$ID': 4711, + '$TITLE': "Long Long Long title is LONG", + '$SUBTITLE': 'Long Long Long Long subtitle is LONGER', + '$SPEAKER': 'Long Name of Dr. Dr. Prof. Dr. Long Long' + } + ) + + render( + 'pause.svg', + '../pause.ts', + pauseFrames + ) + +# render( +# 'infobeamer.svg', +# '../infobeamer.ts', +# pauseFrames +# ) + + render( + 'outro.svg', + '../outro.ts', + outroFrames + ) + +def tasks(queue, args, idlist, skiplist): + # iterate over all events extracted from the schedule xml-export + for event in events(scheduleUrl): + if event['room'] not in ('Leonardo Da Vinci', 'Rembrandt', 'Willem van Oranje'): + print("skipping room %s (%s [%s])" % (event['room'], event['title'], event['id'])) + continue + if not (idlist==[]): + if 000000 in idlist: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + if int(event['id']) not in idlist: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + + # generate a task description and put it into the queue + queue.put(Rendertask( + infile = 'intro.svg', + outfile = str(event['id'])+".ts", + sequence = introFrames, + parameters = { + '$ID': event['id'], + '$TITLE': event['title'], + '$SUBTITLE': event['subtitle'], + '$SPEAKER': event['personnames'] + } + )) + + # place a task for the outro into the queue + if not "out" in skiplist: + queue.put(Rendertask( + infile = 'outro.svg', + outfile = 'outro.ts', + sequence = outroFrames + )) + + # place the pause-sequence into the queue + if not "pause" in skiplist: + queue.put(Rendertask( + infile = 'pause.svg', + outfile = 'pause.ts', + sequence = pauseFrames + )) diff --git a/hackerhotel2024/artwork/bg.png b/hackerhotel2024/artwork/bg.png new file mode 100644 index 0000000..aca48ed Binary files /dev/null and b/hackerhotel2024/artwork/bg.png differ diff --git a/hackerhotel2024/artwork/bg.svg b/hackerhotel2024/artwork/bg.svg new file mode 100644 index 0000000..9337de2 --- /dev/null +++ b/hackerhotel2024/artwork/bg.svg @@ -0,0 +1,482 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hackerhotel2024/artwork/intro.svg b/hackerhotel2024/artwork/intro.svg new file mode 100644 index 0000000..24d9a1e --- /dev/null +++ b/hackerhotel2024/artwork/intro.svg @@ -0,0 +1,745 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + $TITLE $SUBTITLE + $SPEAKER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Hacker Hotel 2024 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hackerhotel2024/artwork/logos/HackerHotel.pdf b/hackerhotel2024/artwork/logos/HackerHotel.pdf new file mode 100644 index 0000000..5e0ccb7 --- /dev/null +++ b/hackerhotel2024/artwork/logos/HackerHotel.pdf @@ -0,0 +1,1605 @@ +%PDF-1.3 % +1 0 obj <>]/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + Adobe Illustrator CS6 (Windows) + 2015-03-26T21:09:06+02:00 + 2015-03-26T21:09:06+01:00 + 2015-03-26T21:09:06+01:00 + + + + 256 + 96 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAYAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A8tYGx2KuxV2KuxV2KuxV 2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVWtLO6vLlLa1 iaaeQ0SNRUmgqT7AAVJ7DIznGAuRoKAjpNL0qFzFJqsbSJs5hikkj5dwr/Dyp4jY9tsoGbIRYh8y GVDvQ+qaZPp116MjLLGwD29zESYpo2+zJGxAqD7ioNQQCCMsw5hkjY27x1B7j+PMbIIpvRLbTLrV 7O31S7Nhp0syJd3qoZTFGTRn4DdqDBqJzjjJgOKQGw5Woq90bcaJpD3NxDpmsw3IjdhbG5R7T1kD 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 6Yrb/9k= + + + + + + 1 + False + False + + 111.000115 + 41.000081 + Millimeters + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + + + application/pdf + + + HackerHotel + + + + + proof:pdf + xmp.did:D69572F2F3D3E411AD5D85A92A9E06F7 + uuid:1602b5fe-fc7a-4f8c-91b9-1c182423a182 + xmp.did:D69572F2F3D3E411AD5D85A92A9E06F7 + 1 + + proof:pdf + + + + + saved + xmp.iid:D69572F2F3D3E411AD5D85A92A9E06F7 + 2015-03-26T21:09:02+01:00 + Adobe Illustrator CS6 (Windows) + / + + + + + + Adobe PDF library 10.01 + False + + + PDF/X-1:2001 + + + PDF/X-1:2001 + PDF/X-1a:2001 + + + + + + + + + + + + + + + + + + + + + + + + + +endstream endobj 3 0 obj <> endobj 6 0 obj <>/Properties<>>>/TrimBox[0.0 0.0 314.646 116.221]/Type/Page>> endobj 7 0 obj <>stream +HWɒ W$Ees١Xq23\[mRI<ۇ??M~] ?Q)O>}~'&qID\4} v7קNd2~#\BRvDOc~{hCMޥuqvnĉ O$:߇_𲿌OINY' .K*Ἕ\@gBR'vv*;ϜtwӪmA#NxNgf +.`8.qgh +4DQ[(b@Hai;|iRMl &^)4KQM]Ga`hh^'] +"M~Ė0N@;#xXY.f֧a4l֠5Q?2+`F85X QM- iQ]ǟ@is۰ : + q4٣L,>қ{+ʰOdX$5c oJ`?p7Xk*.)@ӞW^:=?r^X}. +q+@)p%Jrd{ kxkx+VhOcy4kKiޕȡ:*e`5#(r,x%dTT*Vڼ2 |WFv1Tcˉ +'UGEQ"p|,~7"iɣPJ?tՄغ֗ILV_ݏb<6Hw)#(GAs5֥kΡ e2H%H *2ík@ P!"Hma` j/nx{q:"=r+K`odᷪQ E> endobj 8 0 obj <> endobj 5 0 obj <>stream +ADBEprtrCMYKLab acspAPPLADBE-ADBE +desc|wtptxA2B0A2B2A2B1B2A0E8B2A1~P8B2A28gamtcprtL7desc"Coated FOGRA27 (ISO 12647-2:2004)XYZ ޫ9mft2 zN"uJ + x L"|T.uP,~]=  !"#$%j&N'2(()*+,-.m/V0=1%22345678}9k:Z;I<9=&>??@ABCDEFGH|IrJgK[LPMEN;O2P*Q#RSTUV W XYYZ[\]^_`abcef +ghijkl$m*n0o8p@qJrTs_tkuwvwxyz{|}~ ->QcwÎӏ.AVkН"4FXk~ͬ !5H\pùغ0G]tŒãĻ"5H[nςЖѪҿ0Hazܔݮ#2BRd,Ji.NmWzE t +B + e/`/qAX,\ 5! !"#$w%S&1''()*+t,U-4../0123h4O5667789:;<|=g>S?@@.AB BCDEFGHIJKLxMoNhObP]QYRVSTTMUGVBW>X;Y:Z:[<\?]C^H_O`Wa`bgcjdoeuf}ghijklmnoq r s-t\0` 8!!"#$x%T&0' '()*+b,A-!../012m3R47566789:;m-?@@ABCDEFG~HpIcJWKLLBM9N/O%PQRSTTUVWXYZ[\]^_abc +defg'h1i;jGkRl\mgnsopqrstuvwyz%{:|M}`~sȃބ %>Wqُ ";Uoښ.Jgۤ1Nkí:Xuη 'D_y-F_xɑʪ %>Wpԉգֽ+>Qdx=a=d$HiO[` ! + d & m/{B +b*OzF y!G""#$%Q&!&'()d*5++,-.S/&/012y3O4%45678Z92: :;<=s>N?)@@ABC{DYE7FFGHIJyK[L>M!NNOPQR~SdTKU3VWWXYZ[\]n^Z_G`4a"bccdefghijkltmin^oTpJqAr8s0t)u#vwxyz { |}~ +$,4=GR^jw˜ԙ "7Ne|ȥ8Urί1Tw 4\1^ÍļSɆʸUύ>|ջ?لZީ`KBJhAUkozɻ~㓨~w~[\*~<~x}'~lz~b~hȬ~W~&v~Z(<a}& + },ğ}D^}u}uJ}iY~JP<~Z X|:ܠ|Jl|gR|U|t}BY"}<}狡j~\{|`{sS{Ϧ||Wr|WXh}<}N}3{=iZ{Im{f{i{줠q|CW|Z0iʖ@Q8UY7 8q ڹȡ<񘻂m ڡiZPݗu6b>l6 ` ڶחk%聑9h1 +P%|~6Z ~ źíςP~Zg{ө=O96~k zĞՑƂjd~26fဨOL 6^"~ l|`|G|z|}`||e63}BL0.}0~ ~i oC%!'6{{d+5Kp1DݐFþ_<*wz.c=GKG%.1dDŽ͏zV_ԖՊ=y9ݑ +b@~Jg +1uݎQ Y\wQaV +^J=Ȑ1ɹpȮڣ.gv`HIDžD1Tꂤ2ΣqgRòʉ"u燩_̆C?Iaښq1ăЋdeTBΌm̈ius8_' ?I&1\-UZJ؅͌_ ɉԼtaLw^ݬ5H_1ؚ׀ɜt{ͳju{{y {r|X\|Dʎ }_+KX~ 2jƸ>lO32qP[:BDt+ց:7šPel:w*o,|p'ZoӇD"z,+ x얡Ø딧[o!lYÍ(C,pf-sk`񥥬HRtb9ҐޙpnXnCy[,񇄿ט_ϕʫ݁m-XKOC Ȕ",Ð,̾n4ĔѮBl?7WB։P,Ƈ'1ӽpN;}odskW\lB,Ά.Aї^t~Uj|V'B2ġ,`b@{wڢ{\{k|:i{gK| S"|=)}P%~, ]:| ΃0zdfFRo=bꁫ&YG 2XoҠ֍<yƙyfg*Q蓃=4؆&ӎͅT `ˣϘCKxؐae38QZ0= E';>;&X›w;wdIP\< +'l牷|=ʬBv˞c}P`j0xge ﶸ Jܸq'a,Q@UA>0r`҈\|x|'i|Zky|1J|:am}5)j}K,DqxitGZ9&JF:ց)݁-W~Px^i%EZJ:q&*p4zޅ ד"lc{w h׶$YȯԍJ:Ф;j*͞ňjz¢[w%hwW"Y_Jh:ۣ1+XPs mI 0w/K+h]Y2RJ75:E+\y +φ@v׺ȧgɴnXﭼ'J':ࡘF+E.׌l b:vKg\X­6AIt:ơ+͚ߔu| ӻ,vEjgD8XI㦁b:y+Ța( GUyI}~kʷ|^N|P1|Az}2ǯC}#9~rəƁ:zJд'l^0PHvB%3Q[ +$u#{IzVlHǼ^M>JPrBV63;$Υ~TCz,lWƎ^c^Pō^B4;4%d͈ZtKz2@lRŌ^]0PB4c%ߢ[0,YzchlBĵ~^O&PחyB®Ĕb4ޑx&Fܚ YK0z|˼^l/^@n1P B\4 &ig %zg7'l{^0٥NPy}B_ 4q&aRʘt +pw xtjyJjQyw7zz0#un*ɵvvlwbx'8ixQ^y7zy_uA$GuVAvpʘw!wixPyR7y̙cyNau0ލuc)vNwvwhtxw,P|y@7qyy wǏxDxĘ:y_ }z gvVzMV{J1{g{)Yrkі/hK~>fS(MS*R23q؁–c|GSe|:e.2L7\2Z]܂P|Y՗uc[|w{k +d iL&jd2tt49o PrG. {~ɐ~ԙz,~ɖ/c#~ʒK~Ït2~=~GxZmi~¬~R`~eEx~TbB~KK~<2~1}a`ѱ~t~wN~8~w}a|}*J}ϙ|2}}|J~ʰ~~J™~}ճOw}@`}iJC}p2v}'-? >ĔEFƐZ|2@h{JSu>' ⇲N6/'4{nKgSI>{>'`F ۵H(W,z/ +f'R^|>ˌ('flpLސ5 +S1yLeQҔ=Ї)c(Og޲d6ﮐ-xdϊ,*QZlx=(t-Gܾ읎56w,d祥P̈$=MF#(lYʁ԰X✫gqvz$c%PcP</(t<DP`uqvnvsߗws`xaL͒y\8.z[!3{{UK}A ݜ+~B8~jrt~T_~gL1~8 ~!ڎ Ϩ.ĖY"lݘ13qpy<^ÒrK7v,"^ +s[ndۚe"r pT]yK7p~"ӋG Y?ioe]GSJ7Ì#Hh @C S:׀AFni{\}ՖJ7HK7̐ #y ن գۑFMm" [̐sI֘`7e7$#Jʹa~|lߧ[8&IFa72ɘ#ֈG#Ptڛя}͕lKZ쨄H>F6v#̇RuvyvhfAwfVxVD\yX1Guzcԕ{sl~-w~{~6x}gv }V~C~S1[~U5ktnwTf|UYCsE1c^ẃudvΌe%TCG{,1cl ԊK Lu1d~~T5"B1plp +׉uYxd| tddCSRBߓۑ1i 3z􄊢.s*cjSS8՚MBVl1ْ5 X1ԡۯPsQcRĖzB#1f[a؏5 dI+8{rŝbRf4A⒤O1/d_v IņTu}!ov"m[v]~0wqM;x`\hxcibZHԛK P4;˜۔,p G +ևx +Zh?YZxJ̜;a, ޓH5 Q2wԲh|ڬYJv;Yd+uV9 ev~iavov[avS!qwDA^xx4y$wz{?}~,o}a7f}R}D0}4 +~% ~#<iM}$oޅ`۲ RsDo5 %]5BT\}nٌ=`Rd/CB5 >%zleA|n@J`4RC95/!$&1*}֖ǃ|/NmѵV=_}#Q˩ܔKCn5J(,&x5gp{̺ɥ"muɡ +_n&Q;CȖ95Am&љ& ]!{Fm6E_6^QbCp15+ٖ'U K y{8l'^QA/YCw5QA'Γi ؈ڄp:vc vV&{w&Iw;x-Oy]z ʤ!|jp\F~]c0q}V9}I6\};аF}-Ϊ~0:~-Yjpnօc?VCCIPу8< .7ւ}kS=Fpnǝ2c:VGIhs<7?.L 3kp]Ɩfc(V8IiY}^Gz~}y-o?}O Zk|ld{J{={|Pt|3^&}%eF}-~ ,~zBz{zݏ:{PsT{ɋ7]#|@kFW|-} }ayHy1yztzDr{ F\2{{E{-|:|6,x +Vy#OyĆzpz~w[`zEb{\-{{>.xWxԙy'#yozZzEzᖥ-{zw³xŽsx{~xߴyLoyçYz7Dz-zyڊwίZxUgxLynVyYsyD?zFd-zP'ydMpxqQrׂtms*umWv@Ԅw''xۆ*yȆ{E_{G{lE{l| V|h@fO|'| +̈́|u+lTRjԂUӂW!@'(k& zUߺYUێۑۂg}͂iiTn?,i( ӂTZ#.|fMhxT?Hc8(ǀdˢu}*_{ɚgppSom>(L~ˡ6haȧ5ybRfR->6) ~+}vhՀnK y $erR.V>a~ҙM)~/}}HDԀdY1xHe*{;Q>~)}ו8|c&o㝿rpmr1w scSJtN@v@9Ӊw"xɉzVz z%xz^u'zb{7N/{9#|5" |N}v3ٌU?taցMp΁/9?#{z + mڎ}&n4rՈB`ׇL܆͆9ׅo#$L pӁQӃtq<_LL( *8Ą # | <ap{^8Kh8F#* ra%b.@ʉݨ\oO=]oK8[$&p,}MAHn\ɅȡcJ`8BR$Aȇ7O3ۉs5͈gn ˭\BJ(N7͂=$2|32:{U|Y}᝵kz9`i3*W8E]rz2I"AyQK&h9VEDތr2hy OlޕJ`x+yg5fV"dD2-N +TUQw 瘬fBΕU`˒D؏2iH3$t +لT1vaer`cTUCR2OHhuM ؂K:nMuM5dƎ "T+vC82$˕Z b,kpUBtd8ϩSZu,GwGE*xhw|>Sxxo̜y!_yOz@=z,5{0|7s~=~žnw^)Np=N,A\c󍪠Ŋ}m]㗚MӔԅ=K5,GɄ ]~gtm|w%l̏]ҍMWI= F,_rr+u`n{5EkE\q L<60j)ɠ!{!PGePYϷ>MB:L64VA)ş̑-J1ޔ!H*q +eüܨqYMiwB5wy6=)ܟ-MQ]˃U*q[lrnDusou&qyvqsEawtIxu-zvx +|%tnxtpWxqyesQywtz~`v4zHmw{A-x{ zlyL@l΄YfnqpՌq‚BvBs\_jt2GvT.!wdx}S˜k?3l8`nYptr5^SsևpG=uS.@vexw/j kZm؉oshqLF]SrFt .Su<viY汲k*ldqnʛpr'p\srOF4sڐ?.[tquĆ!)hɳׯjVlh n:qp [qƚ1EsSY.bti{uÝhi鮐j53lmЬ[p*oSZq`mEare.]t,tRh3/_ivwwJxw*yxmzSySX1{ yA{z(|z +i~zuNev2twUxl{xGWyAz({l~ "|}s؍B(t֋uщvՈk!w҇7V"xą@y)zK+ {IrȘ{sӕtݓ~u䐅iv*U@w@xȉ)-y]PzfHr As֐nt'|u3hv=2T~w;?x)Hx\yt,q| r + s/{~tgu1Sv?[w)`x5xյ*qzbr-Ts8WztCguN'S%vL?w`)gwkLx%pKqŌrysfXuRu>v˝)Ow2w*ӂjlBsnyoeqPsY;t"uR whCu4u׋[vwwfd&xBOĀOy:y#15z)*z~~9n~`+vP~~b~~O~~:k=~#~Z b}孻||#} t}ba}N$}儕9~##~\q ~p{2{|5_sv|y4`|Œ.Mc}K9}9a$(}Lm 7}zԗ{t}Uu\x& t[t~퇝u~lvhZFwaGxX3}y8y5;{i~}}7}kzz}Yw}Fl}3}x}f~ .;_e{„ͅjI=XF=I3̂т؀Kh@ozRiS WϊSEׂS3~Ӈ"Z` 򀊂̄IABy3 h=V߂EZ3S]4 +wn¦E<w삯g \VDڀp37Q5 ~љHcTݫ(vM)fLsU%DU2ϔ_ ~ꎘ +}ƘR'yFv: AeoUԣD52q,~vo w}b7zi:kNt_)mcnRE2p@a +r-ZtC'ur*yOs@|srۏjtb=uQPv?ʋlw-x͊y|)|e|qs|a|Pl3|?:}-e}Pn}iކ~Sڏ$d7p*6``eO>؂F-S0b*g.o‹_c=O >tχp-j }Ҍv*m +x^/NTO>-Jmwǁߍ\Z|ċl]eM=]-=2 k{ߋl4y\;M,F?=5g-`}gˌ Dы{ Kekҩ\9[LƆ<񅁛',كcD! +QrV&iwțk1hZElXޖnHp8nr`&tuHz˜Lrvascg%t>WLuAHJ5vZ8_wv'xy>;|Z{u^{f{V{G|7|}''K|r} V=~js-e܂V(8G7`o'3؁ h,r–AdU`F_7'J'T6ÊN ]ɖqЕm~c3TގF 7"'@b r4p֛LbuT$:EU6ԋ܏'ćP~ͧJp8maՒS›&EC6yT0' xD~Co#aNS5gD!6Ft'Y %|yOijk \ۡlNnt@-pT0gr- s&Iu{?wܦ~riգ0r[sN t?u0w!x..{yL"}vȤzh䡨z[(szMje{?P{r0{!C|^|~u£gkZh2Lؚ>20xw!{mˏ6Ut͢g"oY3ALG>0_F7!^t?ށsf[YeK=>?3I0i>"m,DžAsKA4e˝4X\K]}>lL0kf"ki!/rΣe7pCXK3=͕ 04ǒ"bdTr'd6WJĖ}=Y0G"C%Sk2ig^zjQڪllEn47ãp)qs +xv!u|jw0q~]ҬrFQPs3DtL7$u)ǝv.Nw +y獲}iiƯyq]:MyPҧ!yDV,zD7ooz){_"{ x}~i@:\P[ŀWD + 7H)oC Bbh}+\ڇO䤤C75* 3t 𑑂)ɈMgQm[OzC_(7*/`ٔQ sgn[->.O$CԐj6КߎT*,Z:2҅FgZᦘNJvB&z6)*JRN؆gGf#Z'NɝB❔26ڙ*T+]i@RN5jGl2;5m/o"qCsUkw!}%]M~pR*qFr;s/u"v]x\wzm}] x|QܵexFȰ2y;Gy/ͦz9#Xqz5{ {S}:&~\˹:QwF<;/#,ٜB +N +\QmFt\;pUa0#Ah =ԉ\MQ:NFP@;V3q0 \;$B"R #u?U\QfF3X7;GC=0dq$^W; "hp:[oEP=Fa;?~0 a$Zۍ! cv^mO[롐PȯiFC;90$s+Uc 9͂lSfmhoojȆqYmpso3ZKtq%Bv*r(wCszriWqӮkIr`m=t qo*uLoqvgYrwaB7tx$(ux> +xw f}~h}k*}wzmK}moZ}WqP}As}n)+t:| wb{ ?d%g5i{рkŅlmVp +A$q䂭)[s; ^v$~czeےXh8jjlۋVo@p)r'ubp2dۜ/gBa}i1ikU2n1@;p%)qgt>a%d'f|;hbhkGATpm-?o )pύs3a`cpe{-h_gjTSm7?~o)pXv7s`c,$eeMzLgfj^YS7l#?n)oOrԶtEe3BuHg|vPi{w]l,gxmndRyps;zrA#/{sB~t(qmpdrq.sryu>tevuSQwvz;xwr#yw|xo {Fp{q{wsk{d4t|=Pv,|t;wm|$x^|5 n{D{m7 n΅$p]v.qbsuOtb:v0$Gw +y~kՑ~mnTo&ztpËar\NGsۈK:Iu+$}v xʁFjӜm+lOn8OsKo~`q}Ms+9tX$u# w܃cjdkˣ2Ym~"r"o,I_pϗLr[9s\$tr wigQk@5lq.n ^pIVLJqٙ9^s)$sUvnxi'ip}kq]~mI~o5QZqڀrOusyodzopN-{qn{r\=|4tTH|u4}vd~wVҀWy [wyExKyIy z(mWyz[zzHC{A{c4{{|{R~|#!uĄ'CvY}wzkxVYy)Gky4UzB{<}7~ßtrkuc{vM +jw0XxFx䆽4y[z |Bsutqz~uekiMvOWw2F!xZ3xy +{Ǜr<]snyEthEuTWvEwW3w x8= Bz8=ir'1s-x?t&gluVjusEvї\3Zwn= w yeTqɸ8rβ)wfsŬjftUuDvj3wq w! ByKd +ifAw6yhe:jTIm/Aof.aqfr}vvϗinShoQubMpdg4rS(sA(7t.ozv/-avbyHnxomx\swxcyyBRy@qzn.4zY{||W~~_r7~݀a~hQ*$?:.<ag!~͑}Wˁ }}5-}<}v}Ă?{I~Z{ڛns|^|q||-|r)[|% |샀`{ }P{Om{b]{hN'{֘={ -{֑o{l |A~iz|szal{"(]V{J:M{l={-H{cz + {C4Ac{:3ek_.h[u9jnK'el:$o(1q ,ErO0w;mByqniӊoZ-7qVJ.xr9tW(uvzfvwԉwhd;wX{x0IIx8s˅xs7Bdۄ/V1PG^;8(:qKu&ʁ"r~ycՕUm*FS7э(97BD݀qc,JT΂zQU}5xm~NjUA~\p}N1}@[}1}"3{}~~wi+[pMƌ?犓a1]B"X0_hP@vh0 +ZMW?w1]'"ՆJ""-eu٘gOGUYދL6f?<1P1"ڊ7\[CQt2LqfY>&zL U> l0"уl s~騺eRNXK&">Sv0#"t߂lyoCcb eTXgGi9l7+RntPpq +rzmKl`圷mNS;nFp@9gq+'so +t vK{l˝etg_ݚuSduF5v8wj*xROy isz}k!}uk|^S|RA|E|8_|*ؐf}}G G}`p~j]Q|)EK89*ʍ+N w-i]*#!PϔDtHg7ՐB*΍Ԇ3υ5N׃ځiĔ\>SPOŐDd7C*ьފƄ_h].e[@O֓ECʐ7w`*#֋/̆j˂+gϗģ[{/ OpLC{.7?ԕ*Mm4G acVxeJW g4>\i{1ɞk$Kn ovs{a k7UP?lIn=⟦o1qJ$_LrFtTvwf|`3s(TTsIt=su1Pv$n5wŖBx PNz}_j?zS颻{HS{1={o1{$}f|54%| + }h~^SJhHt<1$܀Yk +@$*m^RXG凎0$ߐčԋD ]†xTNbJRd?Kf5C2i)֦k^amoיXt'|T4j\I\k?mN5n)ܤ#prZ̞sܖMx;}oSIJqIUr?]s4t)uvvx{2b~S[2y8I.y?*y4ԣzQ)"zK{^{t}~RZHܫ! +>Ӧ4x* 'PRSH_>n42)2 ߙnkdRWHWx>tg4g#)mCUB 1ʂdi/R̔H$R>P/4YE=)6{Y> ɃńQ3G|>4 4N)|5 Ò  g_i"bbk1e|gmEhYgoRkRqGmw<so#bspy%pck9AemhInzSjpfGlr6Qo#s;q t#r u]wvu`zvĞcwiexxjhaxdjy]PmDy;{oUz>$,pgy 4vy3^%C`恨c:vfcei4qOk ;my$qo~x +t|ˬ\:e_.χbJudb.gՇxNjw:l$m sϪbZؘ]ߕ`ޓRscՐaf}Mit":;kΉ$m rMYƣg\؟i_OrZb_eٕlM3h9k $lm% r8MX\ 0_$@qVb0_*e,?Lh9js~%k⎰Rq⥧Xs![,^#p~ao^dLg90i4$kttqBn^:p2a܄qdqs g^tjRJvl5wo xpG}1r+kNjmkւpnmp poz]frFq@Isr5uutLvt{`vH8hcu Cj^uĀ\l_v}n[nUwN[pfVjuErl3n Soy u%`Obgwe\g(gVRjEl2 3]n3 Anx 1tv^wwaGy5x]dgyy4x2}#znU}o}sqC}mc r}bR/t }t@uv}.v}uwu}j{}Jl܂-n0qoaqCQ8r@t(.u[?v2ozkElpn`pPGqH?s.OtHEt݅0Fyj2j;#koMm_o4+OypĐ? +r8.,sisxʂis}k.nMl۝^n}?Np>qb-rs5R }x+h}jmylQ^m9NOo>%q-r7rf w~^%}%`m]c]fxLi?;~k)7Sn64ou={h{|Bil|k\}+mK}o:~Iqm(s clsAxmy,qyyrjIzmsZ{ +tJ{u:|Zv(}w~ x;{*v{x(w{hxr{Yy1{Iy|#9z|b({`|| |e~}~u9\vvjgev냔XWwIxF9yO(y(0zqh}Nq+su tۍ f$uQWGvH2wj^8x/(xͅy"h|G rUssޕetȒVguGvV81wH1(twڊx{tYr"rs d4t Ut=Fu̔-7v>(HwQ"wHuz̓_qqrrczsUtcFu?7ov$(v!vAzL+b]qx`bcPSWfDL h4-k"mӈ-oxv~YgeoQi,a k R`lCJn3p"քTrOsXyK|tpmq_rQ)sB^u2v'"5w&Ww*{zylfz^Bz;PzAz2x.{Y"d{{4}y~5k~JK]~_O0~x.A~2M~z"~ՀZw|i}h\}.NQ}J@e}g1}"}{}~vy{h|m[|5(M|V?|v41|i"|z|}_}Áur{$g{QWZU{u8L{X?R{11{̏+"{{}tzQgz¢%Yz)Ly{v>{ 0{2"{{ /|nrҐ]e:`TWbJye;،h~,ь7kmh +ΌUo0xqfchV]j_H l[; Kn],epKωq ms>z&o}obBpU#qGr:Q8t(,ue懟vy jw|mx(`xrTxGy?9ty+zbz {}l_".RYFC9KX+aAG Fkw.^هR)E\8ꃯ+ z>ajzjry]ЄڏbQlmE\8|+gҁQ6ǀqiߙ]PʃSD88+8Ài a5hׄS\lPEjD1+7сB.*倏G ~9~{ez]yYqt_M>b@ڔeV3[h%pjڒlpz%dNeX.gL*i?Vk3Km%o0qot|{acTnZW +oK/p?6-q2ÎsZ%tu(u KIxN`|paȓavUvJKw>Tx2Mx%]yuz + *{}`~}U~>Iyb~=~1^~%B"~!~% +e~g5_[T"ӅdHÍ#=T10%QI"  GEB^t.SzxH9 <{v1O-%P> Âȁ[^/RڌGG:<1, %.? ф/]$RXYGS|:@T|P5ߔ,||*|.|͎i}2~Y'TUJ?ЕKd5vՁ*W{J8kiWSI~܉?f3H5'7*voFIHlA g҂S;I?K4̌L*]}-SD"x Mxf4gRȘHN>Вk4ݐ*{pvTA] pi`L\B^9aY/#d#$SfO"it ,ldrR|eKfcB e8`g.ʢj#$7:lO%nP ӚrpvA}?JkmAsl8(ng.|o$qɚs ctcKy_}J(~r@臘s7t.Ju$v6w x!{0~Iy@|z,7[Iz.z$ {^;;{\|Q~!I&Y@7ՀC-ƚr$U͑"5H1?àU6Ӝ-9#`..UрHmE +?~ez6-9#ݕ!!Zyv_H(G?E6x-rj(#ߔ7b<^)S{apY,c\&fG`8rwhc_Ak,fKJmsi6Jo\lM:omezCo]d_gbispqek]hLmJ5jp5lqmrvMw +sgY_p0\q\}_rnbs\Y{l~o]{l`t{Zc|HMf|F5i#|Aj{Ts{1S9WW|[kU^YaGzeC4gbh؀ r~?RȔ'zYsMi]X`FcՈ-4Zfj ga +uq€ŚPTiyfX%h[ד@W_oFb̍4eJ Qgs ;q̙OSYx3W#gZV^1Era3d kf pfN_mR)w6VdfZ.=V5]❝Da\3fdL Vf Rp hX̋j\Cr2i;0sktmC|pdc͈ff%xihfkLjU\m~m,CooK/qhq!rtr ztGancoufqDe(hrSjsBmFuf..hߎ`j^ sV|Ymr\?^(_Nc >^e-h?j6 spX}q[o{s _._$t_bNMue`t9bnee_'VgHj 8l#?(m߈a&pwƁ_o~sadd\V3f”Gpi8+kEq(mZoD}v^ ra#ccUfFhc7jt([lZUnv|xxXKsy[dy^UzbE{weS5||h\#}k: ltoxtb2qud}bvfTwiDDxk4ym#{o}[q-bw+~Hq7korom]a/snRtpXCv.q3wtsh#xt{u~y|Fn\umov%_q2vQurw_Btx!3ubx#vyshxy}9|_zgl"l@m~^Do:~ePIp~BAr?~32s~.#it~wc}|~`xj`Hjl]mO:o=A*p˄02rBg#ZsuCv{wNhyij`[l\iN_n@|o2&q~#UrIt?z2\vgߚhi[kXMm?n1p3s#/q\.t*yiugghןZbjM lEo?m>1moz:"psy;uހX.h [RZ@^LBa={d.R$g]j mvs} af!}[cX}f6J~"h<~k-dmZwoW qPxzqyjdfzVlLWzmI{ol;|-q-|r}t u"zpw+sbwtUxuDHyGv :z +v,zw{x ;}y|nbt|a]u|T{v|GwV|:hx+|,qy|y} {}b~\~hls&`t SdtFũ9v~, wxV|52f|׀%} }E@ ~ZI`{T{I:{7>={^2{%{Ņ*{݄? j}8*z~k_3ySzHz,=LzU1z(%Uzz |T}~^oy*S'yDHy^/Ă$Un6|]UJ@S25߂+*[ۂ̀RMlqT9Տ7Ih?ڂ5\9+ ˆ> gQ$S nIi#?kC5Xk*W\~ .~~ŁlP&pcj(fR (iMo{N^E[af;>bc1 fn&ohkJ msnM|;MΖfDh:^j0Zl{%nbp% rXTw};LnC o9Eq/ώrO%PistP"vG=z8~KvBJv8܎LwE/@w%_xiyUzN}|~JݐX}TAm}K8E}P.Ƌ}g$ˉ}}~  ~?sJ#x@7ˋC,.j$PBSXEq‣Ws6o/&ϐ6ڄ' ڂGɄD->6Y.ؑ&݌ֈ=܆\ ].q'M[R鋪]Vzy`[ ic^WfcbD6hf0Zji9lj}>mU^SYaHx\Vd7g _gU~biC2el_/hnioxz"rQiOTktuXymIe;\)o%T_pBCbr/ejsgtd wxv, M0tQ5uXsU2v5cY6wR] wAg`x/NcZw.?]ӌbj@ o)B{GalL&L]PޜGNKUnx>GY-] +b +rg.tjvfl Nznvs~h"ffjhXkiKml k2l&=nX&p vہRf{I`+cTe"Ig͌T> i2LkM%mXomu v_{;9_?b+TdjHf=h1je%lMun^ uo&z_RvTVHY<]K/ق`"d&f#kx]}<[RRW}{^F}`;<~Zc.f!%i\kpy[y2cPyfEzSh&:{ jP.{lx!}n|~p*t!{RZBulgO:vmD=wGo/9x*p-Cy&r z=s{2{t0~x|XrtMsuHCtu8$uv,vw ywx^oyy}{z!}Wapu|Lqs|B+rx|7ns|,Mt| u}*w}HL{~H~V9n}KoAep76qɂ+r+ >tv.Pz~>}U@lJn@o46XpaI+xq0r7uyW}TY'4\(d&`Nzc fl|ltB0P|u<%}v3Y}w"~xMW {~XLmyzBzzM9lzCz/zz%T{{Z`{{||k~}KpwہBx+8xT/!x%y4Rmy)}{]U}~JJv^Acv8>v؆.w;$w?x7gz7|~rIu'@ub(7u{.v +$v*wuyW{~hGQ'>T5|XX+ѐ[!(_|ѐb nf{mzFIY,=\4u_*܌b ^e g Ћ=k7qv|E#|`xvCCxgHyVY MyIQzV9Vz){Y){bdzv${ւ:xtO?͂3fEWJ_IHOi9cS退)IWcIaZ%t~i7nr=adBVHGMXN8R ) V`;tsfz4qF:ǔcc@UFTDȖmFJZh7OQ(T_1xqbZLu]Qbf`?UWcZ,Ge^U6hWb1$j,epgnTqWs/W[)dZ^U^!aFeaXe?61d@hJ$fMjmlyrbNbUpRDdbVg(TYiE]Rk5:`n4$bp[kq-|v4|IlnMn `QoRUq CYr4z]Os$d_u,juzytzEEQvlIw^N/wQRxZBVx3Zy$4]zuhzy|-x/AcjFv]_K)OOxATDP3TX?$$\ +~ga~[w~mvi>i8C\HNMxmA R"s2VK}#ZAfn)ve> vcgqv[WGi^nZ[`a#^M{cad>fd/i1gCk8jY slxtat&UarfYcYs\?fGK_qh=bk//eamvRgon yqhqw@qQk2dTlWX nMJ[o<_q.Gbs +etS ouw}1zoLtbPuZVTvvI0X?v;[w-_5xvby{ny{|ymI:~a0MT}TQg}HUo}:YP}-J\}a>}l}Szb~ql!F55_J SNυ'GS S:8W,Z_@Kk܁*y]jC;^H9BRLkF[Q9ULJ,PY^߆khxFiA˙ ]Fg&QJnEO96Sڎ, +Wp^%Ojw?miMa k QXT2lUFnY9p]*&ratdq{[hSsk^c_V^etZ/R.g]EFi`7l*d$)Hnng/pi 1xlvmi]`l\`DbPZbeUCeg6hjU(jlmn viqCxfXiZ[kmN^mBan5drps(+grjst +tsuiOzeTrYWsMG[t|AQ^0ul4aPva'dwRhx ry?}|c>Q {WT}{LW{@B[S{4^|1'Ba|sf| wq}a|~taN_VQQJUJ?kXG3j\S&_dhe pX{`zKUAO[CJS>Vڈl2ZpB&j]3d oЂ{ _lI5TaMIiQbh>;U:S2Xw&2\r`ck +oM|GzubGq[M(VrSQLJsoUu>tY1v`]#xDaEzdJ}i)v`kGVnTlYHn`] +=p`a0{qc"tfw,i!>|mx2]e_}RgbGHid~;kg /`mi"6pktmzqz[`hEPcAjEek:ygm.jDoa!l~q qUr|xu{Z3\pOO_MqDtar9udnt.fu!iYv.^owwy|XY?yNM[yCU^y8az;-@d6z!Bf{"dmJ{|u}~~wW7VALY/Bb\7_F,aـ d}ktB}VS̉KVۈKAY7+\,/_D c3qjӃz #s偿}0UQڑeKTW@Xn6[A+^FA WaEj^ 7sXU|WVy}ML2yQ AzmU76c{MYI*\|]6~U`cPj9wTsUJGtpY&?uu\w4v_)Bx)c|ye}4hn{yRn6^qHova >Epc3rbf3(Gthukz m_c~Fr{HPifFkh~K0/ez~B%g~Mj~`q~]x:+3K\u4BX^M9#a/cX%eFi[ṕwccJZA\ۋ8_4x/8a,%@c h0p pv͂^~KeLBP8vT.Q#X#. \` +VdQkey^I|VT@C|}XM6|[,}_"4~b@)Me% +(hozGw]>w_5zxLb}+yAe.!Xz{g| j +mHU>s|PFr}d=/sKg 41t6i$*uZk) vm'fxn +|eqHw?}xDn}l;on3po)qp %sQrc3us z6ue}zG~pCFkt#:l5t2*mwu).nvpYw=sFxQ lx\z|C|=B.g{9iN{1jj{(l;|28m|z3q_| v}N{~A:e9f:0hf(Rizk;o uzEY@mc8fe +0Yfy'h-jn҄ ty@)`K7IO/S&iaW[wG_@‰d}~m"z>qS6bW.Z%6]C{a<-dC3i p{<Հ[d4H^L,؀/a!$'cDf`i*Tmt}*;W|b3|e1+|g#S|i}jk~mvq6w~,9xj$2fx9k*xm"|yoHyp|r~Ju zx8tq>1`tri)uUs!ut vuyw|wy!~|7qx30rx)*ry^!IsLytgzw{X^z}}~s6o&/o(p; qdrq"lvxWy|66m-/Em(BnFb opu%x|4JE-N&RbKV䑏Z C^ɍ4e)-ob{3;Q,GU%0MY&P\._ *c*ir|1=Y6*\e$ _w]nbne- h~ymqu}01`R)b"eugj7 :m[Ƀr.exh~.g9(iZ" +2kfހmUсo kqv:Hz-`m'~o!L}q<}r_~0s v1Ry|,|dt&{u {.v{w {xq }Bzg~x|~3,:yz&QyB{t 2x{ox|ey| +{}}\~G~s+w݁%wIv݁)vƁxy +z|f~lmft2 zN"uJ + x L"|T.uP,~]=  !"#$%j&N'2(()*+,-.m/V0=1%22345678}9k:Z;I<9=&>??@ABCDEFGH|IrJgK[LPMEN;O2P*Q#RSTUV W XYYZ[\]^_`abcef +ghijkl$m*n0o8p@qJrTs_tkuwvwxyz{|}~ ->QcwÎӏ.AVkН"4FXk~ͬ !5H\pùغ0G]tŒãĻ"5H[nςЖѪҿ0Hazܔݮ#2BRd,Ji.NmWzE t +B + e/`/qAX,\ 5! !"#$w%S&1''()*+t,U-4../0123h4O5667789:;<|=g>S?@@.AB BCDEFGHIJKLxMoNhObP]QYRVSTTMUGVBW>X;Y:Z:[<\?]C^H_O`Wa`bgcjdoeuf}ghijklmnoq r s-t\0` 8!!"#$x%T&0' '()*+b,A-!../012m3R47566789:;m-?@@ABCDEFG~HpIcJWKLLBM9N/O%PQRSTTUVWXYZ[\]^_abc +defg'h1i;jGkRl\mgnsopqrstuvwyz%{:|M}`~sȃބ %>Wqُ ";Uoښ.Jgۤ1Nkí:Xuη 'D_y-F_xɑʪ %>Wpԉգֽ+>Qdx=a=d$HiO[` ! + d & m/{B +b*OzF y!G""#$%Q&!&'()d*5++,-.S/&/012y3O4%45678Z92: :;<=s>N?)@@ABC{DYE7FFGHIJyK[L>M!NNOPQR~SdTKU3VWWXYZ[\]n^Z_G`4a"bccdefghijkltmin^oTpJqAr8s0t)u#vwxyz { |}~ +$,4=GR^jw˜ԙ "7Ne|ȥ8Urί1Tw 4\1^ÍļSɆʸUύ>|ջ?لZީ`KBJhAUk}~얁~|]~b9%~Hy~-~3~sB$~jH7~si~~{~a@H-\/;4}2ߡ};0}VS}G}όy~!{`~}H6~텢0I{#|J@|^$é|Z|zn}x}u4`@}ތH0~X1*~^{E {ū {H|+Տ|w|_}aH}1~h{S{d${{Ȩ'|"v|O^|H}2y~{e{""6{@{{~M{بru|B^y|G}4X2}zyz{y{K={u|^|zG|H3N}xezzz5{.苿{th{]|UG|ӓ3}I%ω ~.Ԋ}M}}Յ=}s~[~bC~,5r: څ`9-iryZC-ifֆs3ϺF̄.)Sqf̉ZgMCЁ.k咅͌׃嘒g3Kp`%`Y܁Cف?/A҃z`ˇ1`ՂoiYS(CրD/=$ᖄɶر8H\Śn,mgԞ$(`=kylߒ܉ƒ}MhfSDžu?Ʉ-ҹΊZuK|^ƕg]S[j?փz..TۺmJƐ#&{UkfՅNRx?ۂ).flϓ4C_)zm%vf1R?ނ/$\\_7$yepRPۖ?ڂOo/zWe!IcKy˫e#EoR?Ȃ/a +ݛ{{Ҡp{ޓ|*wQ|bݎ!})N͋};;~))ٚ&Ŋbv+sb1Nҁ;L*CB𙯏_ዘ>uň7agaNB5;ˇ+.)>DٚÕ˛#st'`΋SN2<Dž+@>¤S?-jƚ#|ps-y`M< ,%OԒHGbrH_Mn<3-ƿθA{ ܄h\qҞK^MM2,<=.'{ v{!{U{md|sZ }H菵}7{~~'މZ\z]呸&bliZr +HʎR7L,(pO }Hcd~ k۔UY/H81F])ΆzЗߔ'|[k⌜Ypu4H8wgW*=(l< k|Kjn/YŽ@Hx:8+%˪Z6إ-'{ R^iƖXAHBc8׈+E0򡎳o4)zQ it[X(㕔H98󇊉, iLXq5y˦h|2WG9(,XUHUX?iyh +lWmekG8,If{d{^{uK|dO\|S}:Ce~4 5&3HyrKvSstp̂cPS8gCrf54$'g'_)_hDSsciRmCvd54ǃ(!ʔNgܐLr֞)bR&FCq5Bӄ)M/UG4xTrxb RQsCrʼn5L)34nʝeqpanR)ǐh?~H1I%ČAk;`EJ\Cyyvju[_-LT>.1D'&1~hUhyxići[ *(L>˔؃2 'SٗH㰡xzit茷ZOL]r>W2wJ(?6d +.wժhDZjL<㋥? 2ˍ (ЇKؖO5w;hrZL-0?Q3b)F7ֵ2 vͩ Hh4!YӝtL$?NG3_)󃃕RѲ1vR3gY+K7Y?;?3~JW){ݴukgm|YZK:?3*&|}L|fo4|Xac|SC}Fk}9~.d$bšU}Hn񴊂ua7SF/Z:SM8/ c2%狻:8|nnd]aS˅F:/&W|`na{`ӫSʉF:0 ']./~ٚ1|n +x`Đ^ShF˝;0l'9E{"m `NSU:FٜJ;FC[04([qՉþɧ{LQmk=`kS'FΛ1;u1(уN{%m8_ +S(^F<;1F8(T@A _zĶӬ$l򯟥9_ƨSFϚ;1T)5d~9g}q/F}/d*|XR#}(LI*}@&~>5۞ ~, $C[~q`ĿdXLA6huX,ȔPG%.B~˔qsdٻL-XKLɫPAXE}6ߛr-f|%8~vTqRd0XXòL$A+7@I-鑵&~Ʌq[Td7X̱$MGAѡ7݆.Wc'"G~ȼqd۸aXðPM!G"B+7ԗC.ׅ'8~~qqbdηXMB}e8 Dh.&'ꇓ~Ǚq^_d% +X MB8#U/-.(0~5oqJdXMvB8!P /@5(e{JyL{y꿭|zI|xzĎN|{Nu}{\~,|bDN~|+}yՃz z{(܌{̂=tS||\F}9 Dg~T-8VQxxCyYzz͉'s&{g[|kDu}S.B~]GwЗwxiey0 bz +r +zލ[ {‰Du|/}Ă|vcew wßϟ0x8ygqzOZu{<-Dl|;/}GehulvawN/xPxpyYzӒ'D\{׌0i|ㅙuvHKvsLw«6x.oHyYtzDL{O0|-uz^vēv/w߄xbenyRY zCD:{K91;|U^ui٪6uvtCw_8x96ny&5XzD#{!1|&ߠxȪ~xsÃxႢyWz^m "{#Vu{? |*[[}eXwp˜Y=y*l UF@0+N}ڇҀPxO6kk .Uu/@ME,o29 ֖ac}ujwDT@`-Yuc4ȩ^~6~h~ݔ@i3~oT~t@h S.". ~˪֧~+m~y}I~phh~vgT~@i~.~Ҏ~ǻF~ͦz~Iӑ4~)%|M~g~"S~&n@i~=/~J0~~WL~I/};{w}_g}螀S`}l@b}X/\}{ +~~D:O}wU}δz}f}gS } +@N}Ǐ/}ƇŌvԹiwX1.wxyydzP={;|(ㄅ}]k"0Ģ'JUxdOڄ<+*S2@ OEˈņ7wkc<؄O#bzѫNiӣaXޛHwՓ9Hʌ,]MDu՜Uve<&wxxf-yUWz@D{4|&a;~L(~ԗ~w`~sf~U?~Df4p'hd_0T_Db5(!q2Htf.c?SʋcDbوu5܅)ՂT<,7s}c:)"SU>*D8D$6>*,S̛ϔ<ߧJ6rb˗R֒Dʍ}6)u*qפٵgaÂr@rybRCp6?X*>?ځΔ`.qIaHwRCKDC1368s*턐ͩAu@ vx~w*mx^y,Nr%zg?H{1ew}E%X~읁~ ~M|~m~!]~~QN%~? ~1w&TEGNʆ{𞮄lP\փPMْ?2It'')Պآ{勬k\_!M?2;'؅<ϡh%zJ1j֙Cf[IMSZ?Kn2,(iZԜyUj7[M9j?34x*(d?&p~xE~i6[: L3e?3`M)>ԃPkSz1"xi$FZ☜Lے?3{{;)dGTwΩ:hdZYLj9?q`3|+)ƒ -+v:-vrwXd xAUy_Gz:Ӕ|.}$w1Q~c\~ qҧ}c}U~/Gᘏ~; +~/)i%j}ΆiEq&p=ckrU>qGȗp@;5T/,G&60I~ߪLpqb|T뛄2G{;TT=0&I~% oߐ_bōTQG;qx0[9*'l,(˝}}woLLa-TP,G;0zR'߅n>|naaDTG[d;Ϗ@0܆I(:ׂ܋|wnkW1`)SGN;1c(a$| i'n`TSOG-q;N1 +([`VvtwgʰwZxN\yBcz6.|Z,+}#/l~Ht}gwj}Zĩ@}NM!~&B5~7 ,ΐs$0…t$wg$.ZN;jBO7Rm-W%%k/Ձ)njsxfԭ/aZWN#׆dB` +7R-ɍx& _sWLfyXZWNBl7Ɠ`.) &ҀJ\r1f#YҥhM1lB_7g.|='Q0ء+rseܫgYϔTMgByL80.Njd'_zX4rceYwJMBhΎf8T]/ '7crTej)DYZԚM'BT8T/'ڄ؂u*ǷwTi.Ow]xR^xGS2z<{\2ߛR|*~:#"uI#~|i?~]R}R|}G~D<4~3c0*I#uCuZÅaiLYN]\RG;,=Jс3ҘP`+S$ uZ×iG*3]RV Gܦ=~40L+ҏ/%\܁=uKšWi7']TRUH=4,="%⁛u3ʘ`i!P]ڑRxH=󜧉 4ŕ.f,Ѓ&Lu!i ]$RHdV>4v,!&r&u"h]h^5爐-&Vt3hḦ]sJRH U?>5zR-'-~'{vsHwStPx/ugdyvzwn{xW|(y@}`z*~{tvuy~вv~?w~gx~my~W{!~@|u~R+W}};rˊosZu"יDv]wdl|x=Vuz?@{,]}Bڭq rɓحt +nu^^v*kqxUyW@{ -7|TpoqIsCIt} vjzwy@Uex}@z-|)#8p$qhre@tY~ulivzTxb@z +.}{Äepo:qgrM\s}uhvsTx$@yƌ@.{rlo7p%r sa\|tҥh5vVT%w%@y$/K{4?ѲogВp +qڽs0_|/tLgv#4Sw@yX/{Қ~q~sU~tHu|7Pvfx)Qty|<~zz(I||}$_}&} }e}}})z~}be~m}Q~}<w~)ˀ:~!a{gQ{|ʎ|yU|d}sP}<~*ZzBiz{s{Lx|Fc|CP}A(<}+~tytuyCzY0zړv{mb| ZO|=}W,=~ xpy]yԟzZ-uz억b={8OJ|.=|,}NxUx,Iyr"jyOtza{*N{̐=|-6}1xNNx%y.Jry#tzD`zN{=|7{-|zx0ɬ>xٚ2yyslz.`zNZ{QG=|-| +’p[rSsWo_trv-^;wKy;8z'It|{e1{nN{{qM|Y^|K6}S8i}(dA~\V +˄rE=Ӄp3jt]VKA9Bv)QCσʂK(΁9o~\@J9b6*qGނyզQ|1F}8>n V[րJOP9 *łlDBmf[?J ʋ9+<:`IT* ~8\lGwZ2I^9f+~˄&e]D-[~}}\kZ(lIo9~Ŋ+~uŴZ>5ʺɎU|k Y4_IN~ؓ9~ ,7~2@␁pV,qCr{}tAi^EuWhwrEy,5%f{&h|Îz<6Uz_zzi{hH +{V|MEm}5{7}'!~ƍn0bbxMgGbVEr5Ä4M(o͋(wT~fqUׅEl6 W(OH@X3_k(ؔBsġ{znkJ%[\]M@E=G3(ٮyݏ%jԝl[㊌MB@%܍E3)C.%Sy?j- [JMD,?󅖎35)}݃㔵p?q_uٜ2rfߘt)XuI@w;Ύy.狻{$}Sx؞&y3tŚyfz:W|:zIE{;ލ|/cX}%-~NsÙne8X%VH;猂/ʉ(%Ӆ̟Z􁘜wrؘdzeVg)H;닋0 (&֏8HqcǔaU^RHY;X0pP_' iq0Fc0UHw`<#0'R(ם>~'p~əby}U20H5ۍ<"p0 '܂Ă<~7ؤJotb-TՏ͕Gw'< k1 ($Ty }Eom7aɒםTG&V;舳1D(\QpqxCqjr]~tPPT&vCvw7oey,S {#D~2xwxj(jyY\zOzC`d{7|,ጏ}$0gv䥋iv(\mOCG-7Џ-XJ$ܨcvhӠ&[΄OXC-# 7񎯂8-6m%+u[h.X[vOCCA8ʄ.N&$WAZt FgQZPNǕC*8>.a&\ف|t.wg.ZNVDC䋺8}cN. +&ƂA)!s!fKZe8Npג@Bn8s.Շu'1P^Gs<ڥSfdWZN=}Bΐ8\.އx'gyKplȱq`rTئ!tI:vF="x.3z3*|O" ~YxõxYlKx`F y*TyI#!z>{3 |*~##~n'IJ44+>*$=wkg_TH񜨃 >7%n4s+'$݆w=j*_-Sۡ'iH⛫>E+F4, \%a'vñjn^֥ޏS_H->]V4…,aAd%̅Z5 ,>&"viGB^\S@*H>K(5AD,&e%4uȯ&i蠰^"AxS+H3>om5E @,t&Ƃklwq#arVksWLtB v8Nx0z()|"~ljxPaudxVy'L«yBˤcz98{0}$(ՐC~N"PZlW7af~V1~Lɩ~B~9z30ui)g#lnwpr$ztKevQRxr=;z*|(~̞kǏ·mopЍqXy\sBHdu3Pw5=QyQ+q{k@j,]ln~Ō`ppxrrct{Pav=^xÅ,"{ i{jkݡm͝oșbvqѕ8c1sOv=dxR,zETilkUmFFoGuqXVb}syOu=iwA-$zTWiajSl箰nupas'BOJu]9=fw-~z3ÐhǕ;j#NlntmpcaZr7Nu&=Pw-yŒyk/zSmzo{qht{|CsJ`S}u(L}w 9~x'vK|whpyx]y*KOz惱9|2)}Ts-5tHufvGo^w\x)Jz<~9{*|rvGns6mt@uqnVw!\,xfJy9{+||ٸ(qФst<\umVmrvc[w^J^yG69z+|ɶq+rs1~ulvRZwmJx9zc+{τq`Brjs}tҪ +lvZwcIxr9z,, { s kjl吘n}pk\rX끑tFv5y %͂j{Mu#v4w|F wj"xXDyFv{5ր|&7}0~!~K~v6z~i~Wk~Frh~6'~'ˀ7~ԯ|ˊ5-} %}HYym}g}V~3F~6N~(d?{ΔTg||kJx(|f}V}wE}ن?6t~H),~s{T{q/{Ɨv|f|{LU~|E}G}6})~,uaz,uzW{Iu{ eL|T|kEp|ьd6}J*}F"z;̗Szņzu-{Hd{eT||E7|y6|5*f}fzbz]օ2zt{d${hT!{ӗD|;6|j*}#qjl\n@s|pEbrdQԆ0tAkv2CyG$^{Υ^tiu,܇*vr]wax?Q(yvA)z2|%}zZ"~"$k}A}p˅ }`\}P~+AX~h2}~&~Ƈ␅#䄁oof_҃JP9A`3M'Q +ׄ͑`7~n _{OA&^3vՃ#'N9LU}Vml^A܎ODNA 38(dЌ`\|Nl]`NڀҎ@=3(8ϛ?a{r%lW]0Nlv +@ی3X)~؃`#{dzk|N^\N&,@3)O~јj̑l=yni;p,ZƐ ֋9r-d +-VJ]H <1 +'c^ۢquQcwȘU؆BBH<~"1('&SpL>p݉ 1b|^UHpi!blmcnMW/piKRr?7u*4Cw*8:zm"*}|@JroIsbŝtVdv'Jw?y,4w]z*Ċ|#W~0{>znn,{b {=V {JUa|F?|4 }+:d~q#І (zJmaa_aÙJ:>돚t4ËC+I$qyflӝ`l0UׅIȒC>َ4+]$xRlE`&TI{{>ߍ׆50,B%bT.%5Yn,%wok_OpTגI.E>R5S,}%Jvjj^S̓uIߑ>F)5@,ŅY&0VpjelYߦ$noO]pDcr:u}0x(4/z!}_oޭrdks~YhatNvDBw:/y<1Jz(Ό|"n[~^oD$3mwbW!Ml3C:tч24K**$llȧٚạWTJCMJC:g@w2]*%@ltya:WЖM;Cm:ŋ 2c"+ r%sd/kZClPnGhp>CsR5uu-x&t{;! }crIZsRPtG^v>Zw5yd-{.'>|!:~cy7YyPtzGS1z>nN{5`|.Y~}'~w"DcYPR\GRH>Y6! x.7(#-cG_YfP.x.G?a>‚6P. j(#jcaYTeLPuG+>Ʌ6C/>6(؉$b౔Y.OGȊ]>96/,/xxF) $_T0bYTO,G8>Um6/U)Tz)$ցvbs'XiOѤn?G>όF6/i,)h $Ѓulfnifp]kr1mutpAaFvrM,xt9]zDv&|xir)lsYntp.utrQw`4txDLvyl9y3zq'{{N6g}ji}l%}4nw}rp}_9s4}Lgݠ(UjnmM\ p$*JsM:v!M+{y9Vb$adEg_8XjGmPlޜd[o–mJzrN: u׊$+x9aҾdhBg~illn[ox5J(rz: u,xȄteۥxuhEvjwm4ly"oZzhrG{t5}_w%6yqpѢs}|ɑt}e}BW}mJ}Ĉ$=~ 0~`'~U{ҝR|gs|`e.|hW/|I}3<}g1!}݅'p~7{LY{r{0d|(V|sQI?|Ǝ<}1;}wg'}ׂz񭿀{Br{c{ΜVK|H|p<|ƌu17}-s'}'udefg.p:ibOlAT!oF;q9t,Ӆx "{ABn}?oxoG=qa,9rSN8tEĆ>v9 Lx-@pz#|ΊډQw|7kwmx8` yRyEVz8 {-<}$T~&8zƆlȆ#?_1X +Qꄌ E9 -97$Lцxy]k^r?QDȂ9/ +.V_%F&x\؎j"]kP񂶈D9!P.&aיIwa+iz\ǏPmDTg9!.3&\oTvi;{\qGrPD9 A.\&)CeuۃPh\瘽O8CԀ$8ꊒ.ZF&~؂ QesyHgNfL=iYu1ldL׎&o7@ r.5$uH*oDx!͆{mr0o#e*GpXZrLv/phvdwWÌxkKyx?z5,F{+S}#{~J|Ɛ~ko~1c/4~W +t~K-~;?~v56'~+l$M{jnۅPbKRV\cvJψ?5M6X+$'zAmɌ5^,\6%>tFJe h5Lgg\MiQ0LlF Iou;?Er1SJu(Kjx!(|$s%mIg-;n[UpvPmrXEte;"v1x(Ԉ{,"V}\rQu9f@wuZ핟vOwELy;zf1D{)G}#"Å ~hp|e^|Z96|Ozo}&D}:}1Ή~b)\~#`MpId܃sYNRD:ڊҁ(1)j^# o.hcՔX('NjDq_:2#;*N$KYnޒCcKXXAN4DD::2e*$ā-mMbÓ"X!MD(V:2b*Ń$OmpfbUWɐLMCC::2RR*уK%he#]wgqSqdiISl?Ao6-r.'v&zIyl |~gMdl\]nnR^p6I0br5?ftb6fv.bry '{m!uW}ftC\Bu2Rdv7Hטwm?x6z<.{'<}3"*~eأ{e[ {Q{H=|N?dd|6}y.݋~' ~"Me2<[́Q}6H@ +?R66ge/8(S #>dŻhQ(G ?(@6Ѝv/J(:7#8dZ9P͘Gщ6+/u). $4$NchYĕP^ӒYG? +E6鋙/)A$fǁ\Te/SlgJڧ{j#BzBm:9 p2KsP+6v$y )|[loSn*J_pBW9r0:=t|2~v+yP%;{ 4}[seR¨tJ_uB7pw:Bdx2Zz,+o{& }K!~[-JzRvztJ&zB'{:H|T2Ԓ},B}&~"9MZتNR1IB:^2,&"ZƆ@Q=IƟ}PA皂}:S3, ,ʌ +g'5#`ZKۋQIYAԙ:K_3;-G'{#cYZ QJIՋAʘቶ:J +36F-'gJ#܁Y觏CQs[ Iq>A˜K1:Oz3E-/'…#Ђ{O:g`ZCj ckblDf}~nimplyZsbo]Hur=5xu%P{w5dwkģfmio~l0qgl nsEYquGtv6|@|g&ۓi{jkNqnBapQsD~B)u~3x~'{~Ze{"g󈰀jq[pl`oPrKAu3x1'zПd: hfȑCi]2ofk_nP`qLAti3wsx(-zk CcAeߚQ~hn`k8P^nOp|As3wm(zbe2|gmj[^JmzOWpqAAPsz4 v(yޛb d|gllj1]m:NpA s04vjf))y`w_wbx}xemayh]YzkM| n>I}QrJ/~u#3vy"siu-k{vcmkwo\$xqLzTt(>{vr0!}~x$@?{%qHsrtyt/ujguv[+w5wL/xy/=zzl0|^{% ~=|vo-}Ӈp}x:rj}it}Z)u}Kw}=yw~%0{r~O%}h~omxoNIvq2grք:YStRJvy=}x0z&v|lU^n*ukpfqߊXs̈JuІ=\w䄽1z&|+Ւ@k`mDtPo*eqWsJu/=BwS1;y'W{jlscnIe1p WBrIt=v1Sy4'{cqj+zlrnydp7Vr&IetW_xRSyȁEezX9c|.V}55%d~[tyukv^wȈlQxEz =9R{A.|%}{ssx|t̓ju㐦]wQ x*ZDyd9Hz2.|&9}Clarwtj*u?]9vePwuD[x9+z0^.{&|vr}qvs]itƜl\uP9w-D"x8yڊ,.{I &|;$_ivPbJheN[{h}NekAoC5ar*5v!+zYQNhtjgPlZSfnM#q[A(s5v+yG"t{qsresYFu4Lρsv@hxP5hy+`z{#>}^~z>qzudzX[{4L) {@c"|w5?})+l}#思~}k~Tp\~oc~W~K~ր@C Z5C,$p|}(o3}Rbb}~V}vK4},@~,5~w,F~ҁ$'uz|3n9|lXa|V.|ወJ})O?}{5}ф,y~=%;~&z{}ymg{aP{pU|A)JV|?r|5}R,}Ʉ%~9y5zl{>`{~U@{ƔOJ|@?H|K5z|,}t%}#w_kRba^efS.hG1l*ƃK$fenac+)X^NNDm:c/2mև*i$kY_`b}U蓥eKVhAplL7o.s&w @{RjAg_hiTVl)J/nAqH7{t.ۈv'y!f|i}o^gdqT'SrJAOt6@Pv7XXw/ny'{!҄}gwU]vwSfxIyw@Czq7;{/)|'x}"j +~f0~\:~uRM~_I5m~g@~7*~/C~(=A"'f[ۍR1H]?L74ہ/q5(#Pm*ea^[HQ=Hkv.?73A/{(ׂ #ـdBZ^Q@GH1?n7ws/p(#e"d66ZLՔPMG3&?F)6N/y) $P$ w`)_VbMlZeDi;l3Rp^+_t:$pxŇ{_gOUFiLĘkD n;qT3RtA,w:%z5 f|^>[nU$pTL.qCs;Iu3Rw,=y%Q|!G}]nuTT]vKEwCKEx;Xy3Uv{(,r|k&a}!ڃ~\|S|K'|B}H; +}3\@~,~&"S t\ÃS,xJBȁu:Ӌ3t;,ن{' A="M [|ĉ.RJgnBeۅ::3ll- 'O8#[Rc挛J%B;:d3[Dž-/Il' #D;Z]RKIMB.xo:ˈ3<-8τ'#tށ5T=_MbEle=iH6:l/sp)&t#x\| TUfLi9Ek=Tn6}qz/t)w$"Gz &@}SɥdmLoDq|=|Ys6nplACBso2w,s>$zv^ezagmdj{u]gmdJk.oSSnqBr+tv3 uv%1yy3[p^gqTasJsevtciv#R}lwBpx3ftz8&+y {i~X6{k[{f_{rcz|,agl|Qkz|BLo}3t}J&xj}Y VY]ڄ7pao`fQj]Bnʁ3sd'wTXDX_@\wJoW`g_dPviyAn3r܂(2w{o6SYKW(.}[]n?_ ^d' OhNJAm4 ro(w'R V=|ZymZ^G^:c"OXhAA\m4ru(v傊rQSwU{Y_l^b]cNgڒeAl͍4q);vHCiYk]~zma1nFpd^rmhNtl)>wyo/zQs#}Rw~edPhPg5|ajilmal]\poMgrq>ut\0Vxw$|:yęboHeFpzuhr#kks[n uLLq+v>.tqx0wz3%{R{ŗ_ybyxezPiizZla{XKo{=sM|0v} %z}p]`wd//hSgYk $KRn=ra.1v@&my\ Dd_gubӉg#fU7XiJm=q10u&yxIZĂ^5toaf*e^rXi!J]m +2=tq 1Vu0'XySyY]Lsm`e_dAWzh{Il=Dp1ltԅu'xƂ)RY \}r`IoddVgIl=pHN1dt'xђqJYՃr]]tzt`eudVwRhiHy|$|}e8{h mjH`AmDRpEr9ui.xx8%R{1cdz&fliIr_6l'R-nEq9u.xMK%{C%bMxeekrh5H^[kQnEqC9txE.wȃ&1zҁtawd}:jg`]jZXQmvDp9js.wb&~zyτj`vcӟ6if]iȖ7PlDrpH98s.w&z5exYxwy]Xjzi`]-{GdO|AhxB}_le6I~pv*ˀt!MxPuIcvzv_fiwh[xkmNznOB{jqN6%|th+1~w"G@zȂAr/ltsngptp+ZvzrMx sAyu6 {|x+}\zM#%|h_ov5sq/vfrwYtxfM.v]yeA3xDzx6z>{+|O|#~;}~mqoW~dq*~Xs ~~Lu~@w~5y?~,&{u~$V}{}kp(mjcoօDWq؄BKsX@xv(y5xm,]zÀ$|ހ{jolbnŋVpብKGs@&uh5wÄ ,z3`%(|bziėnk֔amVHpJrk?tֈ5wCE,yă%q|~yiYmJk+a\mOUo +JqE?tb5v ,yu%{zeZm]~a=aUdI/h=^l2p(uB Qyxr}Dc-k}e_}heS~lk@H7~n@<qb2zFt)w!{:vzKljWzm^k{oR|=q|Gs}s<{}u2n~x)bzw"I|twthxuw]5yviQzgwmF{_x<+|my2s}{K)~|"}svu}gv|\)w}Q!x}-Fpy}t<{2}2|u~6*}~#v~rtCfmuU[6vq@PbwExށ;z5]2{*M}U#~Lpsett4ZlucOvEkx;yo2z*|n$=}ƀordsO@YtOEuތEwM;IxևB2z]*{$}]5o,qgcrY:ssNuEDv;%xZ2ry*{$} nZGc,]X)DaJMaeBĆ i +8~m,/1qs&uzlۅubae~Vꄄh?Lh k2BnO8.q/)ht'Xxb كY{kPk?`\TmÛnKqAsY7u/6x+'z!|iEsJ_!,tQTɀutJɀ"v@9x7`y/C{'׀|"1~h~`{ ^~h{AS~{{J~{@~|7$}"/az}(,~n"<gp|]|S }cI}V@V}7~]/~"(#fz{\A{+R{I|U{@ |ĄQ7o}F7/}т.(~q:#p~rez\[zڍQ{%H{?| +76|/}?(}E#~dy|[z-6Qz}Hgz.?{wj7|!/|хM(}#~8\c8)Z[YJo]OaqFH5eL=i]4 [m,q$vnuza׍b~X|e3NhEk!<~n`3Rq,A=u?%rLx J{`8j_Vl_MLjnqDՇp<s#3̅u,dxB%z E}%_`qUs*LtDDu;w3 yD,Oz&@|!3~'^Ky"U yL:z3C8z;s{3|,,}g&~E"P]S +TDKCCq;9Gn3z,6&"t\HShK&B郡;V3ˀԂ +-=m['A/"ĀI[[S}JŁBʁI;3&@-<҂'i#[^GRΏJkBb:B3-2[)'yBo#46XyZQP]Gߔa?葋e8 i0un)r#v{WdhbOdGcg?Vk7n|0hr)숾u$&yӅ|CVciN5OkFhm>Ռpi7nr0\u* x^${ ;}SUvqpMn/rEȍs>puX73!w%0VZy*Nz$D|!!~ sy7z0W |*z}%S<~"!7S}L$}Dlj}=)~6݆|~`0l~*%a\!xSDփKɃDiقg=o6m0^*؂À%b"4߀'Rɋ։JKAԇDy=><;60I`*# &&5"qgRY@JC1=.6U0nDŽ+*&." +N Z3G!']@wXa9ߖe3LPj&,n']s"^1w~{dM@aFtm9+p02r-u'Tx#g{<  }|Kߚo2EIq?w8y 2݋zO-<{(d|$'~ !Jǖ{fDgA{>V|Y8q0|2{}s-\~ (~$r&!n8JZQD>r8IM2x2-_ (Ʉ܀$ ! +JLCɑ =8//K2-PQ(܄6J$t! hIXCF=9A8v2-[Y(݃F$]"!E\T0_Xq~c \nfo`^aie%NSmiL>qm}/uq"yuМ@W_e>[ub~|s_7elch] g)kM}k`o +>or00VtZuK$xxYvSj_Wl^zg[nZk`9pk[drLidt>Qn:v0s?x% x)zP tTuxYvi]wZbxLgy>lz0r\{%w|M8LQvV~h8[~Ya~Kef~=l~1 q~&v~DbJNOu9UfZcX_ՄJewo=k:@1Lq' vI/NcsS[eY+ W^ӉJ\d=jj1rp'zv=GʜxM$rRye X8 WR^ +Id=Pj'*1pR'uۍFĥdL8qQȜdZWV]s3Ic=iӊ~1~pM(uǂcT@MfUXluEh\fUk`Wnne Hqid:uFm-Txr/!|v_^bbs6e9e)dhh`VUkkHon:sor@-wsu#{ex=Zi_^XkiqPamxc-eoU%iqGWmt&:Oqvu.vJx#z|{Wqst}[Otro_AuacbvT"gwFly:pzd.duV{$y|͉T}7{X}/m]}<`a{}aSJf}F/j}9o~.t~4%^y~URzV䅢l[__l_RpdǂEi)9nсV.sx%xPxUNkoY^~^ljQcŇERh"9n*F.ssg&Gx9O^wkTjwXߒi]]ԏqQ'bDhQ9m/s&wꁌNZ vqS&iX ] ]Pb`DgՌ9`mU/r҅S&w9k T`ylXyln\^eq/`Pse:Clv#i6xn#*{r!+~wwxfj^{whaj&ked\ngOpkZBsn6wrV+czcu"1}y-bRhvue2jhoh/l[kJnNnqWBEqs6uxvT+y!x# |{j_rsb>sfetQZGiuMlwApZx6it2z,x{#{}\W{:r_{^eqcp{Y%g#{Mk|dA9o |6Os&}l,RwJ}$X{~e}JZ3)p]Ud2aX#eLTiy@m6@rK,v$zs{XxoG\\c)`V>WRdsKh'@m'67q7,v%4zzW n8[#1bL_>sVcK:ga@&l6q,u?%yDyVmXZ7a^jV#bđJgO?l5pz,u_l%yc|riTosXcu\VvaJ^xder>ZzOi3#|_n(~si qx4zBm^2moaFaTqdyUBsgIWukH=xn3zr)9}vc!g{zx0jgklGi_nkTpn]Hssp=@v0s2xvL){y"5~`{vGfpj#iUq^dks?SntGqvN{Vpw_|e5b]ZaeOi3nElڈY;pR2t]`*x${7o^doas(YdOkhvEHl7;p2s!*w$z쁋q+yTezXZK{H]O3|'a^D:}1e9~cjj/o+&ց*t͂xo.u^cva"XwdaMy2gC\zk^9|0o/}r'Iv (zmVqfb/shiWftkwLvnBxbp8zIs/|=vi'~:y]!x|knoP`ppV)rwrIKtksAv|u8`xw/zy(}{"}fjlFw_fnHx'Up]xK2ryAtz~8BwI{/y|(_|!}"~1~hj;n^8ll!T,n~Jwq~A s~8 v,/x&({]L# }ngh]wfH5$Lj,o%rt?y|d[}]ZK}a P~5d_G~g=Wk4΀of,sU%wT { +byf-XzhOh{TkF*|,m=#}p4~-s,Ev%dy Ӂ^|da?wn"WwoNYxqEfzsT<{=uV4D|wq,}y&Q7{!mW}_tuVuuvMivwDx6x \oSq'Kyr‡kCMt;Zvh3xi-7zVb'T|>a"}π\nS^p>K qꋼBs;)u3wօ-(y'b{ނ8#}y[rUyRvYJ]Ab9=Yf13k)pp#jufȅQzZ ]QV`HfdT@ +g8k0o*$s$w{kXenP#hGj@m87p0΁s*Bv$Cy I|Wa0lO%nG0p?dbr7t0wG*^y$ { ܁u}V:|t N|u/FO}8ve>}w7~y0~z*}^|%6}i!U~U6zzMD{3{?E{{>O|!|=75||0}}*~\~*%.~!TT^y'\LyE%z&=zۀa7{50|*}%~}"GSwRLxtDy=y؄6z̃!0{܂M*|䁎%}"E~ӀiS vKwDex4=y;6z0v{C**|h& }"u~zQxUmJYBō]; bj4xg'-@l'q"RueYzsP;]H`Aߊd3:9g4 k-p 'Նt("؅Zx2-{O|dGg^AjB:XmM3p}-z s(bw#Jz*փ}|N kG }m@^po9䄕r?3wt-n_w#(1y#{ bd}MQrCFGOs?tuB9nv3MJxz-kz-(\{$}\ ׁ{~L>QxEvy^?=z.9 B{ 3{-~|(}$M~!6JK~E +~>Հ^~8ǀ~2-y>(u$!$KD؃e>S8 +32~-k <(#$h!DJD@~懔>V~bG8~!3 ~$-~V)~$~1!PGUVAʖY<^6Db0tvg*ό@l%؊Cq!`v9zF\@`a;Thd-5Ď h#01l<*ωpm&=t!xх|Eגc@'f:i5Rm5/p*·s&V~w<"\>zesN} +EjV?wl:(No_4fq/LJtv*҆Iw&y"{/}DJp>Trq9TtJ4v$/w*܄y&{#}P kA~Cv~>^w9Px4]z/{,*|Y&育}q#Y~u ǁ}BC {= |s9H|4(}s/d}*~{'~#Fg!B€=ـ8Å*4̀|/Q`*܁I'!+7#+!If$BSÅa=P鄑8G3/Hm*>'!>#ԀF!vr5VNd +ZS1u]Xf=a\Wif!aHjfr:oOkP-Yt:p,!yu 0PYlT].rY;`d]dV)bhoGgl4:mNp -rs#x#wgKAd]PfpU%ibZsl>U_nGLeq:Vkt.+qw@$ wYyFn|L-pQoQqaWsS]u8Fcv:'jBx.xpzV$v{sC$xzHyWm\Ny`+U/zS[{&Fbf{9i0|.p}%v+}R@&xFX kL^SR!R)Z*Ea8c9hW.ol& u=wjD1ijJ]Q͇`QcXE'`N9g/n&yuhH;!v"B|]iIo]$P)PXD_>9g./.nf&u$B:0uA1hHW\zOcPJWLD\_r9QfՈ/)ne'tT]kNzR`pSwlcX>^g$]Q)jaCnf6sk+w{p!{uWY^w[B]j_(`]JcFdP"gh_C/l@lF6qpD+utP"-zxMRlcuVfMh[6h[_kNdnBtjq6o^t|+tw|#yz_NmsRo3fWpZs]rNbtAh;vs6mxh,4sz[#x|.~Jw$qOwe^U,xwY7ZyGM8`z#Aef{6{l|,vr|$sxX}|G\pM0dRXXLi_(pAe[6gkI,rT.$wzE(GnKbQ#W6XkJ,,qЁ%Zwr$yC8mIbZaOVV:K4]@3c65jƄ,qn%w"xZAlHBa0NUUPJ\D?cc6jh,q,%v側}drOpfSd&iXWls]SK4ob4>sg-3vlK(z|q [~v{^Y*na\b=e>`VhdcJlhS>Tpl\3htp)fxt!^|xxYc l]oe`aXhmTeukLI5inH=nRq[3qrt)ww"7{zvUlnjYn%^^oSbqHGgs=Vlv3Fqx5* vzh"z|ttRuwhVv@][xw!Rw`qx"Gey5\Ia@f'7l[0%q)vx#zeQf3\VXR[lIw`@pf.x7k[0q`)%v'#z7$hlrP^tTSuYOIw+^%?yc 6 {6hE-E}um%MsxMfemY\0o\RIq`Hsd>v+h5xl-?{wqY%~(u |zdiaZkddPmgGhpj> sn57vqf-6yt&"|xa N{bej6Ygl=OjnbF~n p=qhs4tu-BxMx&~{z!c~S|a1arXWdsNhMtEkv9=%o~w4sTy[-lw z&z|!}~_^zV~bzbMf0zDj{ln(~7q~0t+x)H%{2!}T{c7,LfW>Esii>Ql7Yp0t-+ w%z"8}%ASaL3e"l .7)oƄ0s*wo& zNq"i|πTUPLxUpD]Z3=]_&5ԁdJ.i(!;o"qty3y}R|XK}-\C}`|9cs}Z3au}-xl~K(z~$|>!d~Kko/Ecm?5oځN91rO3Mt-w(zX$|c7!~,K;jyDlfE>nɅ*8qa*3%t(>-vd(y${!}ҀKXPDU>AZ7a_1d+pj?&o!UuڅyIXCU\=7i`7",e+1-i+JUnG&?r!փw`#{KHZ_B46clv7z9wE{E4x| /z|*{}'}~]#w~l CsA>utE9duS4ewcj/y*z'|W#}!"C3rF> swo9&t˂4Vv_O/x-+zX'&{π#}o!O~\A Pe: h5l 1Ko&,ǂarS(Qu$Tx!n{Qo}=Ղl9hCn5p0ۀsv,u(xX% z"Y|݁~W=q8s4~u0~w_,ky$(|z%4|u"It} 7~?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ +  !""#$$%&&'())*+,--./01223456789:;<=>?@BCDEFHIJLMOPRSUWXZ\^`bdfhjmoqtvy|~ +  !""#$$%&&'())*+,--./01223456789:;<=>?@BCDEFHIJLMOPRSUWXZ\^`bdfhjmoqtvy|~1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWn]ccdiӼsι}ʷƶĵ󾵡1?6LTWm]a``clu|żº򻽊1?6LTVl]^^]\ckppu򴽙1?6LTVl]}\[YXZen޿yÈ𮿗1?5LTUj\|YWUW]kվwߺƅБ񡿙1?5LTUiYzVTZWbʿrֺʀ޷ǍōÎ1?5LTUhVwSXZYi˺yնʇݱȉƊċΓ““““““““““““““““1?5LTTeStOZ[_n˷Ա̅۫ɅߥȇƉŌĐĐĐĐĐĐĐĐĐĐĐĐĐĐĐĐĐ1?5LTTcOoWxZ]dtɲ~Ҭ́ئ˂ܠɄߛȆljƍƍƍƍƍƍƍƍƍƍƍƍƍƍƍƍƍ1?4LRQ_JhX{\aiuǫyϥ}Ԡ̀כ̂ږ˄ݑɇߍɋɋɋɋɋɋɋɋɋɋɋɋɋɋɋɋɋ1?4KOLXT_Y_flpģuʝxϘ{Ҕ~ԑ΁׍ͅى̈ډ̈ډ̈ډ̈ډ̈ډ̈ډ̈ډ̈ډ̈ډ̈ډ̈ډ̈ډ̈ډ̈ډ̈ډ̈ډ̈1@3KHGMTd[cihlpĕtȑwˍz͊~χсфЅ҄Ѕ҄Ѕ҄Ѕ҄Ѕ҄Ѕ҄Ѕ҄Ѕ҄Ѕ҄Ѕ҄Ѕ҄Ѕ҄Ѕ҄Ѕ҄Ѕ҄Ѕ҄Ѕ1@2E>NGVh_gdehmqt†wăzƁ}~Ձ~Ձ~Ձ~Ձ~Ձ~Ձ~Ձ~Ձ~Ձ~Ձ~Ձ~Ձ~Ձ~Ձ~Ձ~Ձ~Ձ0@0E,OMYkcaabejnqt}w{zy}y}y}y}y}y}y}y}y}y}y}y}y}y}y}y}y}09 H1QQ]k\\]`cg}k{nyqwtuvsysysysysysysysysysysysysysysysysy/@K7SRUhVxWZ^bzevhtkrnqposnununununununununununununununununu2DI9LPNbPoTzX}\x`tcqfoimklnjpiririririririririririririririririr,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Yr_dhmݰsث|ԦТΞ̚ʖȑǏ缒缒缒缒缒缒缒缒缒缒缒缒缒缒缒,:-GIR`Xq^cgk޶pٱxԬѨΣ̞əǓ鶕궕궕궕궕궕궕궕궕궕궕궕궕궕궕,:-GIQ_Xp^cfi߻lڸtմ|ѯΫ̥ɝƕ鷖쯙쯙쯙쯙쯙쯙쯙쯙쯙쯙쯙쯙쯙쯙쯙,:-GIQ^Wo]bdfh۾n׻uӸ}еͭţ亜ꭜ,:-GIQ^Wn]`acdgnuоxƴܺ䭥뢤,:-GIP]Wm\}^^`adgmtӽ|ܱ䢯뗯,:-GIP\Vl\|\\]_mkmqӵxۨ㘼ꌿ,:-GIO[VkZzYY[ijovȹ|үڡȂĐé슻슻슻슻슻슻슻슻슻슻슻슻슻슻슻,:-GIOZUiXwWWefhowʳҩ̂ٝɅƎĠijijijijijijijijijijijijijijij,:,GINYUgUtT_cehpôz̫}ӣ́ٙʅޏǍƚũũũũũũũũũũũũũũũ,:,GINWUdRpUy`ceitĭx̥|ӝ̀ؕ˄܍ɋǖǡǡǡǡǡǡǡǡǡǡǡǡǡǡǡ,:,FHMURaOj]s`cgmrťv̞zј~Ց̃يˉ݄ɒ߁ɛɛɛɛɛɛɛɛɛɛɛɛɛɛɛ+:,EFMRN[Ta\w`ejlpĞtʘyϒ}ҍ΂Ո͈؂̏˕˕˕˕˕˕˕˕˕˕˕˕˕˕˕+:+ECMLHSW`\{bhijnsǑwˍ{ΈрЄЅӀϋ}Α}Α}Α}Α}Α}Α}Α}Α}Α}Α}Α}Α}Α}Α}Α+:+E?IDQFXe^egegmq‹uŇyȃ}ʀӂ|҇zҌzҌzҌzҌzҌzҌzҌzҌzҌzҌzҌzҌzҌzҌzҌ+:*D7C7RLYjaebcekptw~{{xքvևvևvևvևvևvևvևvևvևvևvևvևvևvևvև+;)@+J3SR\ma__adin~r|uyxw|u܀s܃s܃s܃s܃s܃s܃s܃s܃s܃s܃s܃s܃s܃s܃s܃*8AL9TV[mZ[]`c~g{kxovrturxp|ooooooooooooooo) 0E!O>RWTjUyW[_}bxftirmponrmukxjzjzjzjzjzjzjzjzjzjzjzjzjzjzjz$; H&I?KTMeQqT{X{]vardohmkkmjoirgtfvfvfvfvfvfvfvfvfvfvfvfvfvfvfv:@(@=DNH\LgQoyVut[zo_}lbjehhfjeldncpbrbrbrbrbrbrbrbrbrbrbrbrbrbrbr'6%B>NTUe[uafkqzݗڒ؎ՊԇӅ҂сƄÆÆÆÆÆÆÆÆÆÆÆÆÆ'6%B>NTUe[uafkqzݗڒ؎ՊԇӅ҂сƄÆÆÆÆÆÆÆÆÆÆÆÆÆ'6%B>NTUe[uafkqzݗڒ؎ՊԇӅ҂сƄÆÆÆÆÆÆÆÆÆÆÆÆÆ'6%B>NTUe[uafkqzݗڒ؎ՊԇӅ҂сƄÆÆÆÆÆÆÆÆÆÆÆÆÆ'6%B>NTUe[uafkqzݗڒ؎ՊԇӅ҂сƄÆÆÆÆÆÆÆÆÆÆÆÆÆ'6%B>NTUe[uafkqzݗڒ؎ՊԇӅ҂сƄÆÆÆÆÆÆÆÆÆÆÆÆÆ'6%B>NTUe[uafkqzݗڒ؎ՊԇӅ҂сƄÆÆÆÆÆÆÆÆÆÆÆÆÆ'6%B>NTUe[uafkqzݗڒ؎ՊԇӅ҂сƄÆÆÆÆÆÆÆÆÆÆÆÆÆ'6%B>NTUe[uafkqzݗڒ؎ՊԇӅ҂сƄÆÆÆÆÆÆÆÆÆÆÆÆÆ'6%B>NTUe[uafkqzݗڒ؎ՊԇӅ҂сƄÆÆÆÆÆÆÆÆÆÆÆÆÆ'6%B>NTTdZt`ejowݛڕ֑ԍӉ҆Є̃־־־־־־־־־־־־־'6%B>MSScYs_dhmrݠ|ښ֕ԐҌЈυćٹٷٷٷٷٷٷٷٷٷٷٷٷٷ'6%B>LRSbXr^bfjoާwڠ֚Ӕяϊ̇ڼ۳ܰܰܰܰܰܰܰܰܰܰܰܰܰ'6%B>LRRaXp]aehl߮qۧyנЙ˓ŏܴެުݪݪݪݪݪݪݪݪݪݪݪݪ&6%B>KQQ`Wo\~adgj߷mرvЧȟ™ջڴެওߥߥߥߥߥߥߥߥߥߥߥߥߥ&6%B>KPQ_Wn\|`begmҶsɬ|Ϲֲ۫ߤ᠗ࠗࠗࠗࠗࠗࠗࠗࠗࠗࠗࠗࠗࠗ&5%B>JPP^Vl\z^`beiͻqñyǺϲ֪ۢ⚛᚛᚛᚛᚛᚛᚛᚛᚛᚛᚛᚛᚛᚛&5$B>JOP]Vk[x\^aagnvǴ~ϫ֢ۙ┟╞ᕞᕞᕞᕞᕞᕞᕞᕞᕞᕞᕞᕞ&5$B>INP\ViZvZ\`^dlsƮ|Ϥ՛ے⎤⏣ᏣᏣᏣᏣᏣᏣᏣᏣᏣᏣᏣᏣ&5$B>IMPZVgXsX}[gabiqŨyΞՔڊ߃∫ቩቩቩቩቩቩቩቩቩቩቩቩቩ&5$B>ILPYVeUoVwf{kgbgnġv͗~Ӎق{ž&5$B>HJOVTaRj]og|jliejÚrˏ{ц͇}˘wʱ{|||||||||||||&5$A=HHOSP\RbalehjjintɌ|΄υ}͒x̤v̾vvvvvvvvvvvvv& 5$A;HFONLU[Y`qdgjginuLj|ˁф|Ўwϛuίvζvζvζvζvζvζvζvζvζvζvζvζvζ& 5#@9GAKHQI[^`vdheeiouĄ{ԂzҊvєsѢrѧrѧrѧrѧrѧrѧrѧrѧrѧrѧrѧrѧrѧ% 5#?5F;C=TI[d`zfdcdiotz|xֆtՎqԙpԜpԜpԜpԜpԜpԜpԜpԜpԜpԜpԜpԜpԜ% 5#>/D1M3UO[ib}a`adint|xx}uڃrىoؑnؔnؔnؔnؔnؔnؔnؔnؔnؔnؔnؔnؔnؔ% 5"<&@"N9VU]l^]^`ch~mzrwvu{roބm݋lݍlݍlݍlݍlݍlݍlݍlݍlݍlݍlݍlݍlݍ$ +47F#P?XXXmX}Y\_c|gxlupstpxn|l〮jⅯi⇰i⇰i⇰i⇰i⇰i⇰i⇰i⇰i⇰i⇰i⇰i⇰i⇰# -<I)QCQYRkTyWZ_{cvfrjpnnqlujxh|g耣f聤f聤f聤f聤f聤f聤f聤f聤f聤f聤f聤f聤f聤!$AH-HDJWMfQrT{Yy]tapemikljohrguexc{c|c|c|c|c|c|c|c|c|c|c|c|c| +=@/@BERI_Mh~RpwWvr\zm`}jchgfjeldnbqas_v_w_w_w_w_w_w_w_w_w_w_w_w_w+68-:=?JEU|J]uOdoUhkYlg]oeapcdrafs`ht^ju]lv\nv[qwZrxZrxZrxZrxZrxZrxZrxZrxZrxZrxZrxZrxZrx" +1>5JJQYWh^wdjqy厃≌ށ~{ywvy||||||||||||" +1>5JJQYWh^wdjqy厃≌ށ~{ywvy||||||||||||" +1>5JJQYWh^wdjqy厃≌ށ~{ywvy||||||||||||" +1>5JJQYWh^wdjqy厃≌ށ~{ywvy||||||||||||" +1>5JJQYWh^wdjqy厃≌ށ~{ywvy||||||||||||" +1>5JJQYWh^wdjqy厃≌ށ~{ywvy||||||||||||" +1>5JJQYWh^wdjqy厃≌ށ~{ywvy||||||||||||" +1>5JJQYWh^wdjqy厃≌ށ~{ywvy||||||||||||! +1>5IIPXVg\vbhov呀⌉߇݃|zxx|~~~~~~~~~~~~! +1>5HHOWUf[u`flr{ᐅދ܆ځ~{y|ɼʼʼʼʼʼʼʼʼʼʼʼ! +1=5GGNVTdZs_dinuᕀޏ܉ل||Ā̵̺͵͵͵͵͵͵͵͵͵͵͵! +1=5GGMUScXq]bfkq{۔֎ш̈́ʁǀλϳϯϯϯϯϯϯϯϯϯϯϯϯ! +1=5FFLTSbXo]|aeinۢxԚΓɍĉμдѬѩѩѩѩѩѩѩѩѩѩѩѩ! 1=5FELSR`Xn\z`dgݱmըvΟǘǼ̷гҬӧӤҤҤҤҤҤҤҤҤҤҤҤ! 1=5EDLRR_Wl\x`cfٷlЬtȤ|ȴͯѫӥաԟӟӟӟӟӟӟӟӟӟӟӟ! 1=5EDLQR]Wj\v_beԻi̱qèyȮͨѣԟ֜՛ԛԛԛԛԛԛԛԛԛԛԛ! 1=5ECKOR\Wh[s^}`aпhǵowȧΡҜ՘ח֖ՖՖՖՖՖՖՖՖՖՖՖ! 1=5EBKNQZWeZp[y^^fùmu|ȡΚҕՐב֑ՑՑՑՑՑՑՑՑՑՑՑ! 1=5EAKMQXVcXlYsY}\ckrzȚΓҍՈ׊׌ՌՌՌՌՌՌՌՌՌՌՌ 1=5D@KKQVU_UgYk[|ZahpwǓ͌хՀ׃ֆՆՆՆՆՆՆՆՆՆՆՆ 1=4D?JIPRRZR_bd`{[_fmt|ƌ̄}w| 1<3C=JFPNNS\Uedfzc]biqyĄă}Ïušouxxxxxxxxxxxx 0<1C:IBLGPI^Ucig{idafmv}рuэoҞkѷnqqqqqqqqqqqq 0;/B6HWD][coffbbemuzt׉oՖlԨjjjjjjjjjjjjj 0;,A1E4O1WJ]`btd``bfn}ux}sڅoُk؜i׮h׾h׾h׾h׾h׾h׾h׾h׾h׾h׾h׾h׾0:'?*@'P7XO^e`x^]_bg~nytu{q݂n܉kۓh۠fڪfڪfڪfڪfڪfڪfڪfڪfڪfڪfڪfڪ07!;H#RA3AEETI`Ni|SpvXup\yl`|id~ghekcnbq`t^w]{[~[~[~[~[~[~[~[~[~[~[~[~07 91;@@MFWzK^sQdnUiiZlf^odbqaer`hs^jt]mu[ovZrwYuxWxyWxyWxyWxyWxyWxyWxyWxyWxyWxyWxyWxy*/1,59KLRZXh_uelt~鄈{wtrpĶoѷrշwշxոxոxոxոxոxոxոxոxոxոxո-9,D=JKPYVf\tbipy鉄惎~yvsqɹrӺvӺyӻ{ӻ{ӻ{ӻ{ӻ{ӻ{ӻ{ӻ{ӻ{ӻ{ӻ{ӻ,9,CKGPOSVU[Sn[bipxČȇʄˆʈɈɈɈɈɈɈɈɈɈɈ,8*?3E;KDOJPOQVQlY`gnu}ąǀ|ʂɂɂɂɂɂɂɂɂɂɂ,8)>1D9J?MDMFVUSkV]dkrz}xsx{{{{{{{{{{{,7'>/C5H:H"A5BFDTI_NgzSntXsn\wja{gf}djbn`r^u\y[~XWWWWWWWWWWWտ!28#:4=B@NFWxL^rQdlVhh[ke_nbcp`gr^js\mtZpuYtvWwxU|ySzSzSzSzSzSzSzSzSzSzSz ,1!4/7;}=EvCMoISjNWeS[aX^_\`\`bZccXfdWheUkfTngRqhQuiOxjOxjOxjOxjOxjOxjOxjOxjOxjOxjOxj %)-(|12s8:l?AgEFbKJ^OM[TOXWQV[RT^SR`TQcUPeVNhWMjXKnYJqZJqZJqZJqZJqZJqZJqZJqZJqZJqZJqZ)6$C5IBQPX]`ihtp~z{vrnligfàe͡d٢fݢjmmmmmmmmmm)6$C5IBQPX]`ihtp~z{vrnligfàe͡d٢fݢjmmmmmmmmmm)6$C5IBQPX]`ihtp~z{vrnligfàe͡d٢fݢjmmmmmmmmmm)6$C5IBQPX]`ihtp~z{vrnligfàe͡d٢fݢjmmmmmmmmmm)6$C5IBQPX]`ihtp~z{vrnligfàe͡d٢fݢjmmmmmmmmmm)6$B4HBPOW\^iftn~w|xspmjhfĢeϣeڣhݤloooooooooo)6$@4GANNU[\gcsk}s~{vrnkigǥfզhۧlާpߧrިrިrިrިrިrިrިrިrިrި(6$?3F?MLTYZfaqh|pzzuqnljƨiԩlܪqݩsݫtܫtܫtܫtܫtܫtܫtܫtܫtܫtܫ(6$?2F>LKSWYd_pf{mw腁zvronëmҬpܬsۭuۮwۮwۮwۮwۮwۮwۮwۮwۮwۮwۮ(6$>1E=LIRUXb^ndykt~߄zvsqqίrگvڰxٰyٱyٱyٱyٱyٱyٱyٱyٱyٱyٱ(6$>0E;KGQSW_\kbvhqݐ{؉Ӄ~zwuuɲuزxسzس{س{س{س{س{س{س{س{س{س{س(6$=/D:JEPQU][h`sf~ݜoוyю͈ȃ|zxĴxֵ{ֵ}ֵ~ֵ~ֵ~ֵ~ֵ~ֵ~ֵ~ֵ~ֵ~ֵ~ֵ(6$=.C9IDOOTZYe^pީdzآmњv˒~ƍ~||ѷ~շշշշշշշշշշշշ(5#<-C7IBNLSWXa\k۰cvӧk̞sƗ{ιԹԹԸԸԸԸԸԸԸԸԸԸ(5#<,B6H?MIRSV]޺Zf״`uϫhǢpxʻӻӺԹԹԹԹԹԹԹԹԹԹ(5";+B4G=LFQOUXWbӷ^t˯fçnv~ǼҼӻӺӺӺӺӺӺӺӺӺӺ(4!;*A3F;KCOKSRTaϻ]tdzdlt{ŽѾҼӻӻӻӻӻӻӻӻӻӻ'4!;)@1F8J@NFRLR`̿[s÷bjqy¾ѾҽҼҼҼҼҼҼҼҼҼҼ'3 :'@/E5I;M@KIQ_Yrahov~ѿҽҼҼҼҼҼҼҼҼҼҼ'39&?,D1G6J8FGO]Wq_fmt{{yѾ|ҽҼҼҼҼҼҼҼҼҼҼ'29$>)B-E.F.FFM\Uo\cjqx}xsqѾuҽxӻxӻxӻxӻxӻxӻxӻxӻxӻxӻ'17!<$@&A%L,LDLZRmY}`gnu~|upliӻnӻqӺqӺqӺqӺqӺqӺqӺqӺqӺqӺ'06:<HR*TBSXQkW{]dkr|{t…n‘i dôaԸfոiշiշiշiշiշiշiշiշiշiշ'/467JS/YB[UXhVx[ah|ouxnЂhЏbџ^ҳZԲ`زbسbسbسbسbسbسbسbسbسbس&-0/?L"T5WHXZXiYw[_~fwnovic፦_✨[㮪Xʫ[۪]ܬ]ܬ]ܬ]ܬ]ܬ]ܬ]ܬ]ܬ]ܬ]ܬ% ) ( +/CN(R;SNT^UlWwZ^wdpkjte}a눞]ꓡZ頢X豣VʤXڣXڣXڣXڣXڣXڣXڣXڣXڣXڣ!"4DK-M@OQP`RlUvY~x]qckjgrcz`]Z픚WU챜SSSSSSSSSS6 BG2ICKRM_OiSrxXxr]}lchidpav^}[YVSRRRRRRRRRRܿ"6>"B4DDFQI\~MdwRkqWpl]tgbxdhzam}^r[xY}WTRPPPPPPPPPPڱ%39$<4?ABL}FUvK\pQbjVff[jb`l_eo]jqZnrXstVwuT|vRxOyMzMzMzMzMzMzMzMzMzMzλ$.3#70:<{>EtCLmJRhOWcTZ`Y]]^_ZbaXecVidTmfRqgPuhNziLjJkJkJkJkJkJkJkJkJkJk(-1*z53q:;j@AeFF`LJ\QMYUOVYQT]SR`TPdUNgVMkXKnYIrZHw[F{\F{\F{\F{\F{\F{\F{\F{\F{\F{\ &x+"o0)g60a<5\B9XG
    RP@PTBMWCLZDJ]EH`FGcGEfHDjIBnJAqKAqKAqKAqKAqKAqKAqKAqKAqKAqK% 4?+F7NDVP^\gfzpou{vp|lhdb`^]ǎ\ҏ[ߏ\_cfffffffff% 4?+F7NDVP^\gfzpou{vp|lhdb`^]ǎ\ҏ[ߏ\_cfffffffff% 4?+F7NDVP^\gfzpou{vp|lhdb`^]ǎ\ҏ[ߏ\_cfffffffff% 4?+F7NDVP^\gfzpou{vp|lhdb`^]ǎ\ҏ[ߏ\_cfffffffff% 4>*F7MCUP][ef}noxyws}nifca_^Ȑ\ԑ\_bfhhhhhhhhh% 3=*E6LBSN[Zceko|tww~rmifdbaǓ`Ӕ_bfjkkkkkkkkk% 3<)D5KARMYYadinqw{|~vrnjhfdĖcЗcߗfjlmmmmmmmmm% 3;(C3J?QKWW_bfmnvy~{vrnkiggΙgޚjmoppppppppp$ 3;'B2I=OIVU]`dkluv~倀{vrolkj̜jܝmo䞾q㟺r㟺r㟺r㟺r㟺r㟺r㟺r㟺r㟺r$ 3:&A1H,D5J?OITSZ^ڥciӜkw͕tǎ|‰}{zyɪyܪ{ݪ|ݩ}ީ}ީ}ީ}ީ}ީ}ީ}ީ}ީ}ީ$ 07">*C3IӼRSʴ[e­cujryаڰڮۮۮۮۮۮۮۮۮۮ# .5:"?(C-G1G=ϿPRǸYdathpwͱٱگۮۮۮۮۮۮۮۮۮ# -49 =$A(D*E"?$D:MOUb]rdkry{xȱxٱzڰ|گ|گ|گ|گ|گ|گ|گ|گ|گ# ,169;7"B8KMS`[pb}iow}wspưpٰsگuۮuۮuۮuۮuۮuۮuۮuۮuۮ# +03557 @6IKQ^Xn_{fmt|{uplhĮhڮlۮnۭnۭnۭnۭnۭnۭnۭnۭnۭ" )-/. 8 @@4FIN[Uk\ycjq{yunida«`ܫeݫgݫgݫgݫgݫgݫgݫgݫgݫgݫ! +& ) (%= IK0JELXRhYu`g|nuvnhȋcȘ^ɪ[Yߦ^ߦ`ߦ`ߦ`ߦ`ߦ`ߦ`ߦ`ߦ`ߦ`ߦ#",?I!N3PDSTTcXp^{}duknth~b؉]ٗY٨VTXZZZZZZZZZ1@G'K8NIPWScWn~\vvb~ojird{_熏Z璒V颔S궕QЕTUUUUUUUUU 4 ?E,H=KKNXRc~Vkw[ro`xig|do_wZVRPNLҎMMMMMMMMM ߱"5= A0E?HKLV~P_vUfoYli_pdet_lw[szW{|T~QNLJI…I…I…I…I…I…I…I…I…Ҹ%39">1A>EI|IRuNYnS_hXcc]g^cj[ilXooUuqR|sOtLvJwHyGyGyGyGyGyGyGyGyGy԰%/5"9/=:{BCsFJlKPfPUaUY][\Y`^Ve`TjbQpdNufL{gJhHjEkDlDlDlDlDlDlDlDlDlɹ!*0 5*y:3q?;jCAdHF^MIZRLWWOT\QQ`SOeTLiVJnWHsYFyZD[B\@]@]@]@]@]@]@]@]@]$*w0#o5*g:0a@5\D9WI_7=b8;f99j:7p;6s<6s<6s<6s<6s<6s<6s<6s<6s<|x$ +t2yUI\Td^mg{xovuq{njhfedɉd؉efhjkkkkkkkk}" /7>'E1KӽD1ʷNE±WV_efrn}u|ģڤᣅ⡅⠅⠅⠅⠅⠅⠅⠅ & ,1478B0ǻLCUU]ddql|sz~}ؤ}% +/135A.ÿKBSS[cbpi{pw~zwuդvyyyyyyyyy$ +) , - , 3?,H@QRYa`ngynu||wspnӣorssssssss"& '&"1=*F=OOV_]ldwkrz{uplhfѡgkllllllll! /:'D:LLT\[iath}o{wuoiea_О`cdddddddd"08$A7IIQXXe_pey{mttn}hc^[XЙY\]]]]]]]]  )9A D3HDNSU`\j{csujznrh{cυ]ϑYСUѵSБSVWWWWWWWW߲.;B$G4KBOOTZ}Zdualohripwdy|^߃ZߏVR᱇PɇOQRRRRRRRRӷ1 :@)E7IDNO|SXuX`n^fhekcmp^usZ~wUyR|N}L~JKL~L~L~L~L~L~L~L~ծ˾"19>,C8HC|LLtQTnWZh\_ccc^igZqjUylQoMqIsGtDuBvAvAvAvAvAvAvAvAvڥ̶$/6<+@6zE?sJGlOMgTRaZV]`YYf\Ul_QsaM{cIeEgBh@i>k>k>k>k>k>k>k>k>kήþ",38(x=1qC9jH?eMD_RH[WKW\NSaPOgRLmTHsVD{XAY?[<\:]:^:^:^:^:^:^:^:^Ÿ'~.v4#n:*h?0bD5]I9XNPWAM\CJaDFfFCkH@rI=xK;L9M6O5O5O5O5O5O5O5O5O{! s)k/e5 _;%Y@)UE,QI/MN1JR3FV4CZ6A^7>c8;h:8n;6t<4z=1>0?0?0?0?0?0?0?0? wng! `(Z/U4P:L>HC EG"BJ$?N%=R&:V'8Z(5^)2c*0h+-m,+t.*v.*v.*v.*v.*v.*v.*v.*v.pk$ +d1m:tC#vL.tU8p^BkhJfsQa~W\\X_UbRdQeOgNhMiLiLjKjKjKjOjTiTiTiTiTiTiTiTipk$ +d1m:tC#vL.tU8p^BkhJfsQa~W\\X_UbRdQeOgNhMiLiLjKjKjKjOjTiTiTiTiTiTiTiTiql$ +e1p9vB#xK.wS8s]BnfJiqRd|X_\Z`WcUeSgRhPiOjOkNkMlMlNkRkVkVkVkVkVkVkVkVkrm$ +g/s8zA"|I-{R7w[ArdJmoRhyXc^_b[eYgWiUkTlSmRmQnQnQnRnWmYoYoYoYoYoYoYoYosn# +j.v7}?"H,P6{Y@vaJqlRlvYg_cc_f\iZkYmWnVoVpUpUpUpWpZq\r\r\r\r\r\r\r\rto# +m-z6>!F+N5V?{_IuhRpsYk~_gdch`k^m\o[qZrYrYsYsZr[s]u_v`v`v`v`v`v`v`vtp# q,}4<D)L4T>]HzeQtpYpz`kehiembp`r_s^t]u]u]u_u^w`yczczczczczczczczuq" t+ 3;B'J2R!D)ޢJ2מT?З^Oʐg\ċogwov~|{xvutsʍsݎt퍠u퍝vvvvvvvvzw $ + 17<A$ۨH,ӢR>˛[Nŕd[mfuo|w}}zyxwǐwڐx됙y쏗y펗y펗y펗y펗y펗y펗y펗y{x #* /59߭>׬E+ϥP=ȟYMbZjfrozw}}|{Ē{ג|꒓|둒}쐒}쏒}쏒}쏒}쏒}쏒}쏒}{z"( .27ݲ;ԯD)˩N;ģWL`Yhepoww}Ԕ蓍꒍둍둍둍둍둍둍둍||!' +, 04ڷ8вB(ȬL:VJ^Xfdnnuv|}ҕ畈꓈ꒈꒈꒈꒈꒈꒈꒈ}~ %) +- 0 ֺ5͵A&ŰK9TI\Wdcknsvz}Ж喂锂꓂ꒂꒂꒂꒂꒂꒂ}#')ݼ+ӽ3ʹ?%I7RH[Vbbimpux}}{͖z|}}}}}}}}~!#$#2Ǽ>#H5PFYT`agkntu|}~zvt˖suwwwwwwww/RMYZ`dfmmuzu{t}ojea_Ő]ߐ_bbbbbbbb ٱӿ' 4>*G:OIVV]`dizkptrwnz|ic_[XËWߋX[[[[[[[[ ܨӵ $1;&D6LDSPZZzacthjnpphxucȁz^Ȍ~YȚUȬRÄQ߄RTTTTTTTT ԭ̻*6>!C0J>QIzWSt^[mebhmhbum]qY׋tTؙwQثyNzMzMzN|N|N|N|N|N|N|N|٤ͳ- 7>$D1I[<\:]:]:]:]:]:]:]:]ɭ *}1u8!n>(hD.cI3]N7YS:UY=Q^@NdBJjDGqFCyH@Jp:;w<7=4>1@/A/A/A/A/A/A/A/A~ umg' a.[5V:R@ND JI"GM$DR%AV'>[(;`*8f+5l,2s./z/-0)1)1)1)1)1)1)1)1{rib[ U& +P- L2H8E<AA>EsG#rP,nY5jc=enD`xJ\NXRUUSWRYPZO[N\N\M]M]M]M\O\O]Q^Q^Q^Q^Q^Q^Q^ga% c, m3t<wE"vN+sW4n`=ikDevK`P]SYVWYU[T\S]R^Q_Q_Q_Q_R^R_SaUbUbUbUbUbUbUbhc$ g+ q1x:{C!{L*xT3s^F&O0~W9y`BtkJpuQlWh[e_cbad`f^g^h]i]j^j^k^m_nananananananankf" r' +}, 4<D#L-T6]@zhIvrQq{Wn]jahefhdjclbmanaobobpbqcrdrdrdrdrdrdrdrlg" v% + 2:A H)P3Z=܁dF|nPwwXs_odmhjkingpfresetetfufugvhvhvhvhvhvhvhvmk y$) +07>E%L.܍W8ՇaDЁkP|sYx|`ufrjonmqktjviwixiyiyjykylylylylylylylynn|"'. 4;A ݗI)֒T6Ќ^DʆgOŁpY}xaygvltpqtownym{l|l|m|m|o|o|o|o|o|o|o|o|op!%+ 28>ٜG$җQ4ˑ[CŋdOmYua~}h{mxrvvtyr{q~ppqqr~s~s~s~s~s~s~s~os #) / 4ݣ:ՠD#ΛO3ǕYBbNjYrazhn|szwx{v~uttЂt䂘uvvvvvvvvpu"', +1 ۨ7ҤB!ʞM2ÙWA`MhXpawh~ns~x||zyxẍ́xℑyyyyyyyyyqw $(- ׫4ΧA ƢK0U?^LfWm`uh|nty}~}||ˆ|}}}}}}}}}qy!%ݮ(Ԯ2˪?åJ/S>\KcVk`rhynty}ɇއ򅅀򄅀򄅀򄅀򄅀򄅀򄅀r| ڲ!ѱ1 Ȯ=H-Q=ZJbUi_pgwn~ty~Lj܈񆀃򅀃򅀃򅀃򅀃򅀃򅀃s~׶δ/ ű<F,P;XI`Tg^nfum|ty~|zĉxډxyzzzzzzzt޳ӹʸ- +:E*N9VG^Se]leslzsx}}yus‰r؉rstttttttu߬ +ַϼƻ+ 8C(L7TE[Qb[idpkwqw{|vroljֈklnnnnnnnv ֯ѹ(6@%I5QBYN`Yganiuoz|uuzp~lhecԆcegggggggx اѲ̽%3>"G1O?VK]Ud^keyrltzrowj{ea^\҃\^_______} ܟҫ̶ !0;D-L;TG[QbYyhaspgnwmhrcv_y[|X}V~V}V~X~X~X~X~X~X~X~ գͰƻ, 7A)I6QAXKx_Srf[mmahufc~k^oYrUtRvPvPvPwQxQxQxQxQxQxQxۚϩƵ(4=#F0N;xUDr\LlcRgjXbr]]{bXφeTϓhPϢkMзlKmKlJnKoKoKoKoKoKoKoҡȯ* 5=D*xK3rSNnAKvDGFCH@J>L;:=8?6@4A2B2B2B2B2B2B2B{tm$g, a4\:W@SEOJ LO"IU$FZ&B`(?f*GCCH@L>Q;V8\5b2i/q ,y!)"&$$$$$$$$$$$$$$$uld\VPK&G, C1 +@6 <: 9> 6B4F1K/P,U)['b$i!pw~~~~~~~WP) N1 V6[?^I]T"[_)Vj0Rt5M9JF>F>E>E?E@D@E@E@E@E@E@EXQ) Q0 Z5 _=bHaR"^\*Zh0Ur6Q}:M=J@HBGCEEDFDFCGBGBGAHAGAGAGCFCGCHCHCHCHCHCHYR) T. ]4 c<eFdP"aZ*^e0Yp6Uz;Q?NAKCJEIFHGGHFIEIEIEIDIEIEHGHFJFKFKFKFKFKFKZS( W, a2 g:iDiN"eX)ac1]n7Yx_HfQmYt_{ejosvy~z}{|z|y}w}w}w}w}w}w}wi{ +بЬȬ*8C"M0U<]GdPkXr_yejos~v{yx{v{v{vywxwwwwwwwwwwwwl~ آӪͯİ(6A K.S:[EbOiWp^wd~in{rxvtyr{p{o{pyqxqxqxqxqxqxqxo +ۛԥϭȳ%4?I,Q8YC`MgUm\tb~|hzmuqqunxkziziziykxkwkwkwkwkwkws ֞ϨʰĶ #1 =F)O5VA]JdSkZ}r`yyftkooksgvdxbybxbxcwdvdvdvdvdvdvw ۖѢˬĴ. :D&L2T=[GbO}iVxo]swbngilepas^u[u[u[u\t]t]t]t]t]t]t| ՚̦Ű+7A"J.Q9XB|_KwfRrmXmt]h|bcg_k[nWoUpTpTpTpUpUpUpUpUpUpܒПǫ&3>G)N4|V=v]EqcKljQgrWbz\]`YcUfRhOiNiNiMjNjNjNjNjNjNjԘʥ !/ :C#|K-vS6pZ=kaCfhIaoN\xSXȂWTȍZPț]Mȭ^K_I_I_GaGbGbGbGbGbGb܏͟ì*6|?uH%oO-jW4e^:`e?\mDWuHSKO֋NLؙQIثSGSESESCVBVBVBVBVBVBVҘƦ +z5s=mE gL&bS,^Z1Za5Vi9Rq=Oz@KCHEEGCHAH@H?H?I?I?I?I?I?Iɡ}v*p4j<eC`I [O%WV)S],Pd/Mk2Is5F}7B:?<==:>9?7?7?7?7?7?7?7?yrl(f1 a8\?XETKPQMW"J]$Fd&Ck)@t+<~-9/61422304040404040404}unhb$\,W3 S9 O?LEHJEPBU?[B *:/73471< .@ +E +(J %P "V ^ f nvJ!B-F0 M5 R=SGSSQ^Mi$It(E~+B.?0>2=3<3;4;5:595959585858594:4:5:5:5:5:5:5K C-H. Q4 U< VEVQT\Pg$Lr)H|,E/C1A3@4?5>6>6=7<7<7<7;7;6;6=5=6<8<8<8<8<8<8L D,K, T2 Y: ZDZOXZTe%Pp*Lz-I0F3E4C6B7B7A8@8@9?9?9?8?8?8A8@:?;?;?;?;?;?;MF+P* Y1 +^9 _B_L\WYb%Um*Qw.N2K4I6H7G9F9E:D:D;C;C;C;C:E9DH@HBHCHCHCHCHCHCON%Z&c, h4 j<jFgPcZ%`e+\p0Xz4V8T:RO?N@N@M@M@N?N@MCMEMGMHMHMHMHMHMHPR"_$h*n1 +p9pBnLiV$ea+bl0^v5\9YV@UATBSCRDRERERESFRIRKQLQMQMQMQMQMQMRVd"m(s. v6 v?tHpR"l])hh0er6b{:_>]A[DZFYGXIWJVKVKVLWLVNVPVQVQVQVQVQVQVQS[i r%x+{2 +|;zDwMsY'od/km6gvjzChHfKdNbPaR`T_V^W^W^X_X_Y_Y_Y_Y_Y_Y_Y_YUcqz %*1 ߇:لFR${\.vf8sn?pvEm~JjNhQgTeVdXcZc[b\b\c]c]c]c]c]c]c]c]c]Vgt~!&,ی6 ӉC̅O#ǀY.|b7xk?trFrzKoPmSkWjYh\g^f_f`fafagag`g`g`g`g`g`g`Yjw!ߑ'֑3 ύ@ȉL!V-_7|h?yoFvvLt~QqUpXn\l^kajbjdjdjdkckckbkbkbkbkbkb\mzە ҕ0ˑ>ÍI T,]6e?}mFztLx{RvVtZr]p`ocnenfngngnfoeodododododod^o|ؘϘ.Ǖ<GQ+Z5b>jF~qL|xRzVx[v^tbsergrhqirirhrgsfsfsfsfsfsf`rߗ ԛ˛,ę:EO*X4`>hEoLuR~|W|[z_xcwfvhujukukvjvhvgvgvgvgvgvgbt ߓؚўȞ*8CM(V3^=eElLsQzV[~`|d{gzjykylylykzjziziziziziziev ٖԜ͠š(6AK'T2\H#P/X9_AfImOtU{[~_zdvhskpmnnmnmmnknjnjnjnjnjnjn ~ދԖ͞ǥ + 0 <E!N,V7]?dGjNqT|xYx^tcpgmjjlhmfmglgkhjhjhjhjhjhjrڎЙɡè-9CL*S4[=aEhL{oRwvWs~\najefhcjak`k`k`jaiaiaiaiaiaivՒ̝ĥ)6@I&Q1X9_A{fHvlNqtTm{Yh]da`d]gZhYhYhYgYgYgYgYgYgYgz܊Зǡ%3 =F"N,V5z]=ucCpjIkqOgyTbX^\Z_WbTcScScRcRcRcRcRcRcRc֏ʜ / :CL'yS/tZ7oa=jhCfoHawM]QXUTXQZN\M\M[L]K]K]K]K]K]K]އϖĢ)6?yH sP(nW/i^5de;`l@\tDW}HSˆLOOLQJ¹RHRHRFSEUEUEUEUEUEU֎Ȝ#}0 w;rDlL gS&c[,^b1Zi5Vq9R{=Nφ@KϓCGУEEзFCGCFBH@J@J@J@J@J@J͗} yt+o6 j@eH`P\W"X^&Uf*Qn.Mw1Jނ4Gߎ6Dߞ8B9@:?9>:<<<<<<<<<<<<Ġ{upk*e4 a<\DXJTQQYM`!Jh$Gp&Dz)A+>-;/907161515151515151zpkfa(\1X8 +S? PELLIRFYC`@h=q:{ 7"4#2%0&.&-'-'-'-'-'-'ynfa[V$R,N3J9G? +CD @J >P;V8]5e2o/y,)'&$$$$$$ymbZU +PKG%C+@1<69;6@3E 0K -Q +*X '` $j !tyl`UNID ?;8"4'1,-0*5'9$>"DJQYbk u ~ + + + + + + +<$6/<.C4 G= IG GQE]Bh>s;}9!7"6#5$4%4%3&3&2&2&2&1&1%1%1$3$2&2&2&2&2&2&=$8-?,G2K; +LE KPI[FfBq?{ <";#9%8%8&7'6'6'5'5'5'5'4'4&5&6'5(5)5)5)5)5)>$;+C*K0P9 +QC PMMYJdGoDy!A#?%=&<'<(;(:):)9)9)9)9)9(9(:(9*9,9,9,9,9,9,?#?(H'Q.U7 +V@ UJSVPaLlIv"F%D'B(A)@*@*?+?+>+>+>+>+>*?*>,>.=0=0=0=0=0=0A"C%N%V,[4 \= [GXRU]RhOr#L|&J(H*G+F,E-E-D.D.C.C.C-D-D/C1C3C4C5C5C5C5C5B!H!T#\*a1b: aC^M[YXd Un$Rx'P*N,M-L.K/J0J0I0I0I0I0J1I4H7H8H9H:H:H:H:H:D!MY!b'g.i6 +h?eIaT__[j$Yt)V},T.S0R1P2P4O5N6N6M7M7N7N:MR>R@RBRCRCRDRDRDRDRDIWdl!r'u.u6 s?pKmWia$ek+bt0`|4^8\:[Y@XAWCWCVDVDWEVGVHVHVHVHVHVHVHL[hqw#z)z1y: wGsSo]%lg,ho2fw7d~;b>`@_C]E\F\H[I[JZJ[K[L[L[L[L[L[L[L[LP`lu{~$+ۀ6}CyOuZ%qc-nk3ks9iz=g@eDcFbHaJ`L_N_O_O_O_P_P_P_P_P_P_P_PScpyޅ$Յ2΂@~LzV$v_-sh4po:nw>k~BjFhIfKeNdPcRcScScTcTcScSdSdSdSdSdSVgs|ىщ/Ɇ=ÃIS#{\,xe4ul:rs?pzDnGlKkNiPhSgUgVfWgWgWgVhUhUhUhUhUhUXjv~߉Ռ͍,Ŋ; FQ"Z,|b3yi:vp@twDr~HpLoOmRlUkWkYjZjZkYkYkXkWkWkWkWkW[ lx +߇ٌяɐ*8 DN!W+_3}g:zn@xuDv{ItMsQqTpWoYo[n\n\n[oZoYoYoYoYoYoY^ o z يԏΒƓ'6 BL U*]2e9~l?|rDzyIxMwQuUtXs[r]r^r^r]r\s[sZsZsZsZsZa q +|܅ՍВʕ–%4 +@JS)[1b8i?pD~vI}}M{RyVxYw\v^~v_|v_|v_|v]|v\|v\|v\|v\|v\|v\c +s~وҏ͔ǘ"2>HQ'Y0`7g>nDtI{MR~V|Z|{]zz_xz`wz`vz`wz^wz]wz\wz\wz\wz\wz\fu߁ՋΒɗÛ 0<FO&W/^6e=lCsHyMR}VzZw]t_r~aq~aq~`q~_q~]q~]q~]q~]q~]q~]ix܄ҍ˕Ś-:DM$U-\5cylDusIqzNmRiVeZb\`^^^^^^]^\^\^\^\^\^\t܃ϏƘ$1 <FN%U-}\4xc;ti@opFkxJgOcS_V\YY[W[W[WZWZWZWZWZWZWZxևʓ +.9CK!|S)wZ0r`6ngNAKDHEFFFEEFDHCHCHCHCHCHЍÚ|w*r6 m@iHdP`W\^$Xf(Tn,Qv0MɁ3Iɍ6Fɜ8Cɮ:B:A:@;>=>=>=>=>=>=ǖwpm!i/e:`C \KYSUZRbNj!Ks$G}'D؊)Aؙ+?٫-=-<-<-:09090909090vme b_*[4W=SD PLMTJ\GdDlAv>; 9"7#5#4#3#3#3#3#3#3#ukb]YU'R0N8J?GF DL BS ?[>;D8J5P 2X +/` ,j )u &$"!uh]SLGC?<"9)6.23/9,>*D'K#R [ep|   + + + + + + +uh\PF@;7 30-*$&(#- 17<CKT ]hs}/(.-3,91=;=F +;Q 8\ 5h3r0|..-,+++**)))(((*))))))0(0+6)=0A9BD +@O =Z:f7p5z3210//...----,--------1'4(:'B.F7GB FL CW@c=n:w87654433222222322111112&8$@%H,L5M> LI ITF_Cj@t>}<;;:99888877887 7"7#7#7#7#7#4&=!G#O)S1S;RE PPL[JfGqEzCBA@???>>>>>> =#=%='=(=(=(=(=(7#AM U'Y.[7YA +VKSWPbNlKvJ~HG G!F!E"E"E"D#D#C#D$D&C)C+C,B-B-B-B-B-<FT[#`+a3`< ]F ZQW]UhSrQzO!N#M$L&K'J(J(I)I*I*I*I,I.H0H1H2H2H2H2H2@MYa f&h.g7dA bM_Y\cYmWu"U}%T(R)Q+Q,P.O/O0N0N1N1N2N4M5M6M7M7M7M7M7ER_fk"m)m1k;iH fTc_`h!]q%[x)Z+X.W0V1U3T4S5S6R7R8S8R:R;R;R;R;R;R;R;IWckpr#s+r6pD lPiZfd"cl'at+_{/^1\4[6Z8Y9X;WW?W?W@W@W@W@W@W@L\gotww#x2v@ rLoWl`#ih(gp-dw1c~4a7`9_;]=]?\A[B[B[C[C[C[C[C[C[C[C[CO`krwz|}.{= +xItSq]#ne)ll.is2hz6f9dbAaC`E_F_G_G_G`G`G`F`F`F`F`FR c n u z } Ӏˁ+: |FyPvY"sb)pi/np3lw7j};i>gAfCeFdHdIcJcKcJdJdIdIdIdIdIdIV +f px}ՁσDž(7C}MzW"w_)uf/rm4pt8ozIR Z'}a.zh3xo8wuGO W(^.d4{k9xr>tyBpGmKiNfQdSbSbSbRbQcQcQcQcQcQm|·Ő"0;EMT%[,zb1vh7ro.>.<0;2;2;2;2;2•{qhda'^3[=XF UN QUN]KeHnExBЄ?ђ <ѣ!:Ҹ"9"9!7$6%6%6%6%6%{qg^V +TR)P4M>KFHNFV +C_ Ah>r;}864211/////|qf\SM KI%F.C7@>>E;'9/653<1B.I+Q(Z%d"p }    + + + + +~qdYND=95 20-%**'0$6!<CKT_k x  +rdXLA82.*& #!#(.4 ; CMXdp}"-%+)*.02:1D.O+[ )g +&q +${ +# " " ! !          #,(),'3/787B4M1Y .d +,o )y ( ' ' & & %%%$$$$ # # # $ ######%*,%1$9,<5=@;K8V 5a 2l 0v . --,,+++***)))*))))))))'0!8"@)C2D<BG?R <^ 9h 7r 5{433221111000100000000-#5? F'J/J8ICGN CZ Ad >n=x;;:9988888778777666662:FN#Q+R4P>NI KU H` FjDsC|BAA@??>>>>=>>== =!_?`?`>`>`=`=`=`=`=Sajrwy{}#|3z? xJuSr\pc$nj)lp-kw0i}3h6g9f;e>d@dAcBcBdAd@d?d?d?d?d?Vdmv{} 0~= +|GyQvYt`$rg)pm-ot0m{4l7k:j=i@hBhCgDgDgChBhAhAhAhAhAYfpy~Ɓ .: E}NzWx^#ve(tk,sq0qx4p8o;n>mAlC~kE|kF{kF{kE{kD{kC{kB{kB{kB{kB[hs|ȁ„+8CL~T|\#zb(xi,wo0uv4t}8s<r?|qBzpDxoFwoGvnGunFuoEvoDvoCvoCvoCvoC^kv~ń)6AJRZ"~`'|g+{m0zt4x{8}w HPX!_&e+l/~~r4{}y8x{gAdDbF`G_G_G_F`E`E`E`E`EkyɄ+6@IQ{X!w^&se+pl/ls4i{8eK>K>K>K>|Ɖ{*w6r@ +nHjPfVc]_d![k%Xt)T}-P0M3J5H6F6F6E7E8E8E8E8E8̃{vr#o0k;gD +cL`S\ZYaUiRq!Nz%K(H+E,B.A.A-@/?0>0>0>0>0ŋsl he)b5_?[GXO UVR]OeLnHwEB ?"=#;#;#:$9&8&8&8&8&vka[XV+T6R@OHLPJX +G` DiAs>~;ʋ9˛7ˮ55422222wlbXOIGF*D4C>AG?P=X;b8l6x 4م 1ڕ /ۨ .ۿ - , *****xlaWNE=;9 8*634<3D1M/W-a+l(y&$"! ylaVLB:42/-"+*)1'8%@"I R]jwzm`TI?6.*'$"%+2:B L +Xes|naTH=3*#  #*2:EQ^lz-)(#/%8#C NZepy* &"%)-+6*@'L$W!bmw'$"("/*242=/I,T)_&j$t#|#""!!      + + + + +##(06'90::7E4P1\/f-p+y**)))(((''''''' +( ( (((((-7>#@,A6@A>>>>======6BLRUU$T.R9QGPSN^ +Lg KoJwI}HHGFFEEDDDDDDC C C C C : H R WZZY$Y3YBWNVY TbRjQrPyONMLKKJJ J!I!J"I#I$I%I%I%I%I%?MW\ ^ ^^`/`=_J]T [^YfWmVtT{SSR!Q"P#P%O&O&N'O'N(N)N)N)N)N)N)DR[`bbeg*g9eEcP aY_b]i[pZwY}!X#W$V&U(T)T*S+S,S,S-S-S-S-S-S-S-HV^dhijl&l5jBhM fVd^be`l_s ^y#]%\'[)Z+Y-X.X0X0X1X1X0X0X0X0X0X0LYbimnoq"q2o>mI kSi[gbeido"bv$a|'`)_,^.]0]2\3\4\4\4\3\3\2\2\2\2P\fmrss uu/t;rF oPmXk_jfhl"gs%fy(d+c-b0a2a4`6`6`7`6`6`5`4`4`4`4R^iquwwxy,x9vD tMqUo]nclj"kp&jw)h~,g/f1e4e6d8d9~c9}d8|d7|d7|d6|d6|d6|d6Uamtyzz||){6zA +xKuStZrapg"on%nt)l{,k/j2i5}h8{h9yg:xg;wg:wg9wg8wg7wg7wg7wg7Xepw|~~&4}? {HyQxXv_te!sk%rr)qy,~o0|n3zm6wl9ul:tkoG lNhUe\bc^j [r$W{(T+Q.N0K1J2I2I2I2I2I2I2I2{}wt#p0m:iCeK bR_Y[`XgUoRx!N%K'H*E+D+C+C,B,B-B-B-B-ǂtn +jg*d5a?^G[N +XV U]RdOlKuHEB!@#>#=#=#<%;%;%;%;%znd_\!Z-X8UASIPQMX +K` HiErB}?<:87755555|qf\SOM#K.J8HAFJDRBZ?c=m :x 7ą 5Ĕ3Ŧ1Ż0/.----~sg]SIA=< :+958>7G5Q3Z2e/q-~+Ӎ)Ӡ'Զ&%$$$$$th]RH?7/*)(%'/&9%B$M#X!d rui\QG=4,$! $,5>HTa p + wi\PE:1(  +  &/8BO]l}yk]PC8.$  '0;HWfv)%%,6@L X +cnw&"!*4>IU`kt}      + +    + + + +"%''1%;"FR]hqz'-#/-.7+B(N%Y#d!m v~!%/46(624>1I.U,_*i)r)z(('''&&&&&%%&''' ' +' +' +' +&-7<>#=,<89C7O5Z4e3n2v2}111000000//00 / / ////+5 >CDD%B0@<>I>U=`?>>>>>>>5BJNO NMO/P>PJOUM_ Lg Kn JuI{HHGFFEEEDDDDDDDDD;GOSTRUW*X9WFVQTZ +Sb QjPqOwN}NMLLKKJJJJJJJJJJ@LSY\[[^&_5^B\M[V Y^WfVlUsTySRRQPP O!O"O"O#O#O#O#O#O#O#DPX_bbad!d1d>bI`R ^Z]b[iZoYuX{WVV!U#T$T%T&T'T'T&T&T&T&T&T&HS^dhhg +hi-i:gEeO cWb^`e_l^r]x\[!Z#Z%Y'X(X)X*X*X)X)X(X(X(X(KWbilmlmn*m7lBjL hTf\ebdicoau`|!`#_%^(])]+\,\-\-~\,~\+~\*~\*~\*~\*N[fmpqpqr'q4p?nI lQkYi`hfglfsey!d$c'b)a+}a-{`.z`/y`/y`.x`-x`,x`,x`,x`,Q_iptustu$u2t=rG +pOoVm]lckjjpiw"h%}g({f*ye-wd.vd0td0sc0sd/sd.sc-sc-sc-sc-Tbmswxwxx!y/w:vD tM sTq[paognn}mu"{l|%yk(vj+ti.rh0ph1og1ng1ng0ng/ng.ng.ng.ng.Wfpwz|z{ ||,{8zBxJ wRuYt_~sf{rlyqs"vp{%to(qn+om.ml0kl2jk2ik2ik1ik0jj/jj/jj/jj/[isz~} )5~@|H {PzW}x^zwdwvjtuq"rty%os(lr+jq.hq0fp2ep2do2do1do0en/en/en/en/_mw}&3=F +N|~Ux}\u|bs{hpzo!myw$jx(gw+ev.bv0`u1_t2^t2^t1_s0_s/_s/_s/_s/dqz#0:~C {K wStYq`nfkm hu#e~}'b}*_|-]{/[{0Yz1Xz1Yy0Yx0Yx/Yx/Yx/Yx/hu~,~7zAvI rPoWl]idfkcs!`{$](Z+W-U.S/R/S/S.S~.S~.S~.S~.nz|(x3t=pF mM jTg[db`i]pZy!W$T'Q*O+M,L,L,L,L+L+L+L+t~xt"q/n9jBgJ dQ aX^_[fXnTvQ N#K%I&G'F'F'F(F(F(F(F(zvp li)f4c>`F]N ZU W\TcQkNtK~HEC A!@!@!?"?"?#?#?#zmgb_"].Z8XAUISQPX M_ KhHqE{B?<;9988888~ti]W SQ%O0N:LCJKGSE[Cc@l =w ; 8642210000xmaVKF DB&@0?9>B+H*R(]'i%v#̅!͗ͫ}pdXNC:1)!#-7BN[iy܋ ݟ ޷ + + + + +reXMB8/&  +(2=JXgysfYL@6,#  +#-8ETdwvgYL?4) &1?N`q%! )3>JValu| "  '0 ;GS^irz%-8CO [ enw~"!#* 4?KVaksz &*+%*/':#F!Q\fov} & .221(/3,?)K(W'a'j'r'y'''''''''&&'''(('''#.6 +9974+272E3Q3\3e3m3t2z2222111100000 0 +0 0 0 0 (5<?> <9!;1=?>L>W=`=hUITRSZRb +Qh PoOuN{MMLLKKKJJKJJJJJ?JT[]\Z +[\,\:[EZNYV W^ VeUkTqTwS~RQQPPPOOOOOOOOCPZ`cb_`a(a6aA_K^S ][ [aZhYnXtXzWVUUTT T!T!T T TTTTFT^ehgdef%f3e>dHcP aX `^_e^k]q\x[[ZY Y!~X#|X#{X#zX#zX"zX!zX!zX!zX!JYcilkhij!j/j;hEgM fU d\cbbhan`u`|_}^{]!y]#x\$v\%u\%u\%t\$t\#t\"t\"t\"N\floolm nn-n8lBkKjR hYg_ffel~ds|dzzcxb va#ta%r`&q`'p`'o`&o`%o_$o_$o_$o_$R`jpsspq +qr*q6p@oHnP lWk]}jc{ijyiqwhxugsf!pe#oe%md'kd(jc(jc'jc&kc%kc%kc%kc%Vdmsvvstuu'u3t=sFrN +qU |o[ynbwnhumorlvpk~nj!li$ii&hh'fh(eg(eg(eg'ff&ff%ff%ff%Zgpvzywxyy#y0x;wD~vL {uS xtYus`srfpqmnptkp}io!gn$dm&cl(al(`l)`k(`k'ak&aj&aj&aj&^ktz}|{|}} }-|8}|Az{IwzQ tyWqx^nwdlvkiurgu{dt!as#_r&]q'\q([q([p([o'[o&[o&[o&[o&cox} *}5y?uGrN +o~U l}\j}bg|id{qbzy_y\x"Zx$Xw&Vv'Uv'Uu'Uu&Vt%Vt%Vt%Vt%gs|{&w2t<pDmLjS gYe`bg_n\wYW T~"R}$P}%O|%O|%O{$Oz$Oz$Oz$Oz$mx}xt!q.n8kAgIeP bW _]\dZlWuT~QNL!J"I"I"I"I"I"I"I"s}}vq mi(g3d=aE^L\S YZ VbTiQrN|KHEDCBBBBBByynhda"^.\8YAWHUPRWP^ +Mf JoGyDB?=<<;;;;;~tg_Z VT'R1P;NCLKJRHZEbCk @u = ;865543333xncXOJHF)D2C;BD@L>T<]:g8q5}31 / - - , ++ + + + |qg\QF>:86(514:2C1L0U._,k*w(&$#"!!   vj_SI>4,'%$##,!6 ?IT`m|Ǝơǹyl`TI>5+# $ . +9 ER`oӀӓӨԿ{naTI=3)    *5AO^o~pbUH<1'  %0=L\nrdVH;/$ +*8HYk| &0;HT_iqy$-8DP[fov}  ! *4@LXbksz  %0 <HS^gov}  + *6BNX b k r y  $ +&%##.;GS]fmtz&,-,)%%$3&A'M(X)a)i)p)v)|))(((((((((((((((#-331, -0,3;4G4R4\4d4k4q3w3}3322222111111111*48==88;'=5>B>M>W=_=fMW\^\XYZ#Z1Z=YGXOWVV]Uc +Ti Tp SvR}RQQPPP~O}O|O|O{O{O{ODR[aca]]^ _._9^C]L\S[Z Z` +Yg XmXsWzVV}U{UzTxTwTvTvTvTuTuTuTHV`egeab cc*c6b@aI`P_W ^^ +]d ]j\q}[x{[yZwYuYtXrXqXpXpXpXpWpWpWMZcikiefgg'g3f=eFdNcUb[ +}aa {ahy`nx_vv_~t^r]p]n\m\l\k\k[k[k[k[k[Q^glnlijjk$k0j;iDhK~gR{fY +ye_ weeudlsdtqc|obmakai`h`g`f_f_f_f_f_f_Ubjoqolmnn!n-n8mA|lIzkPwkW tj] ridpijnhrlgzjfhffeddcdbd acacacbbbbbbYemssspqrrr*r5{q?xqGvpNsoU pn[ nnblmijlpglxekcjai_i]h\h \g\g\g]f]f]f]iqvvvtuv +v~v'zv3wv<tuEquLotSlsY js` grgeqncqv`p^o\nZnXmWmVlWlWkWkWkWkbmuzyyxyz}zy{$u{/r{9o{BmzIjzPgyW ex^ cxe`wl^vt[u}XuVtTsRsQrQrQqQpRpRpRpgqy}}||}|~wsp,m6j?gGeNbU`~\ +]~c [}jX|rV|{S{PzNzLyKyKxKwKvKvKvKvlv~|vp li'g2d;aC_K\RZYX` +Uh RpPyMJHFEEE~E}E|E|E|r|uoiea"_-]7Z?XGVNTVQ]Oe Lm IwGDB@?>>>>>>x|rga\ XV'T1R:PBNJLQJYHaEjCt @ = ;98776666wmaYRNKI*G3F<DDCLAT?]=f;p8{63 1 0 / / +. . . . {qg]RIB?=!;+948<7E5M4V2`1k.w,*('%%%$$$ukaVLA81 ., +)*2(;'D%M$W"c!o~zodZOD9/'$-7ALXe t sh\PD:0&  +(2>JXgwˉ˜˲xk]PD9.$ + +%/;HWgy܌ܟܳzm_QD8," *6EUgy}oaRD7+  $2ASew"-9EQ\fov} *6AMXcksz &1=IT_hov|  !,8DPZckrx~   +&1>JU^gntz + +) 6 C O Yaipv{"! /=IS\dkqw|    %(+(""&((7)C*N*W*_*f*m*s*x*~******)))******#+4871.2#314>5I5R5[5b4h4n4t4z433333322333322)5>BB>9 ;=,>9>D>N>V=]=d=jWGVOUUT\TbShSo ~Rv |R} zQyQwPuPtPsOrOqOqOqOqOqOGT]aa_Z[[\%\1\;[DZLZSYY}X_|XfzWl +xWs vV{ tVsUqUoTnTmTlSlSlSlSlSlSLX`edb^__`!`.`8_A_I}^P{]Vx\]v\cu[j +s[q qZyoZmYlYjXhXgXgWfWgWgWgWgWP\dhgebccdd+d5~c>{cFxbMvaTs`Zr`ap`h +n_o l_wj^h]f]e\c\b\b[b[b[bZbZbZT`gjjiefg gh'|h2yg<vgDtfKqeRoeYmd_kdf +icm hcufb~dbba``^`]`]_]_]^]^]^]^Xckmllijkk{k$xk0uk9rkBpkImjPkjWii]gid +ehk cgsag}_f]e[eYdXdWdXcXcXbXbXb\gnooomnozovp!sp-pp7np?koGioNgoUen[bnb `mi ^lr \l{ZkWjVjTiSiRiRhSgSgSgSgakrrrrqrzsutqtnu)ku3iu<fuDduLbtR`tY]s`[sg +Yrp WqyTqRpPoNoMnLnMmMlMlMlMlfouuuvv{wtxoy kzhz%e{0c{9a{A_zI\zPZzWXy^Vye Sxm Qxw OwLvJvHuGuFtFsGrGrGqGqktyyyy~zu|n~ida ^+\5Z>XEVMTTR[PcNkK~t +H~ F}D}B|A|@{@z@y@x@x@xqz||}}znga\ YW&T0R9QAOIMPKXI`GhDrB| ? = ; : 9 9 9999wukaYTPM K*I3H<FDELCSA\?e=n:y8642 11 1 1 +1 +1 +~zpf[SJE B@#>,=5;=:E8N7V5`4j1u/-+*((((''~tjaVLD;632#0,.5-=,F*O)Y'd&p$}" yndZPF<3*$ "!!*3<EP[hv }rh]SI>4+"  % /9DP]l{wlaVK@5+!$-8DQ_oŀŒŦŻ|qeYL@4)  *5BQarԄ՗ժּvi[M@4(  %1?Patzl]OA3' +,<Nat*6BNYcksy '2>KV`hpv| +".:FQ[dlrx} (4ALW`hnty~ !-;GQ[cjpuz   %3@KU]ekqv{   +9EOX`flrw}"%"$3? I S [ b h n s y ~ !!""""'031+% (*-+9+D+M,V,]+c+i+o+u+z+++++++++,,+++#2:>=7124'545?5I5Q5Y5_5e5k5q4w4}4444444444433-;CGEA<;="=/=:>D=M=T=[=a=gm`Fk`Mi_Sg_Zf_ad_hb^pa^y +_] ]] [\Z\Y[X[X[XZXZXYXYWaefeebc}dxetepe)me3ke<ieDgdKedRcdXad_`cg^co\bx +Zb Xa VaU`T`S`S_S^S^S^S^[ehhhhf~gxhsi oiki&ii0fj9djAbjI`iP_iV]i][heYhmWgv Ug Sf QfOeNeMdMdNcNbNbNb_ikkkkkylsmmm infn#co-ao6_o>]oF[oMZoTXn[VncTmkQmtOl~ +Ml Kk JkIjHjHiHhHhHg Hg dmnnoo|ospmrgsct`t]t)[u3Yu;WuCVuJTuQRtYPt`NtiLsrJs|Gr +Eq Dq Bp Bp Ao Bn Bn Bm Bm iqqrrswsmvfway\z YzV{%T{/R{7P{?O{GM{NK{VJ{^HzfEzoCzzAy?x =x +l/G.O,Y+c)o'|%#"!     wmcZPF=5-*(&%%.#6"? HR\hv|qg]SI?6-%"+4>H T ` n}vkaVLB8.%   )3>IVds{peZOD:0& (2=JXgxui^RG<0% %/;IYj|ϏУϵzocWI</$  !,:I[muhZK=/" )8I\o '3@KV`hov{ #/<HR\elrx} *7CNXahnty~$2>IS\djpuz+8CNW_elqv{#1=GQY`glrw{  (5AKT[bhmrw} +    .:ENV]cinsy$,.*%  (!5"?"I"Q"X"^"d"j"o"u"{"#######$$$$$"/7851+)+#,/,:-D-L-S-Z-`-f-l-q-x-------------,8@@>:5345*555?5H5O5V5\5b5h5n5t5|55555~5}5{5z4z4z4z44@FFEA>;<<&=1=;=C=K=RpQEnQLlQRkPYiP`hPggPoePxcPbP`O_O ^O +]N +\N +\N \M\M\MNWYYYXTUUzVvVsV)pV3mU;kUBiUIgUPfUWdU^cUebUm`Uv^T]T[T ZS +YS +XS +WR +WR XQ XQXQQZ[\\[WYzYuZqZnZ&kZ0hZ8fZ@dZGcZNaZU`Y\^Yc]Yk[YtZY~XXVX UW +TW +SW RV +SV +SU SU SU U]^__^[{]u^p^ l^i^#f^-c^6a^>`^E^^L]^S[^ZZ^aX^jV^sU]}S]Q\ P\ +O\ +N[ +M[ +NZ +NY NY NY Y`aaba~_wapbkbgcdc ac*^c3\c;[dCYdJXdQVcXUc_SchQcqOb{MbLaJa Ia +H` +H` +H_ H^ I] I] ^cddeeydqekffgah^h[h'Yi0Wi8Ui@TiGRiOQiVOi]MifLhoJhyHgFgEfCf Bf Be BdBcCcCcbfghh~htiljek`l[m WnUn#So,Qo5Oo=NoDLoLKoSIo[GocFnlDnwBn@m>m=l}<=}D;}L:}T8}]7|g5|q3|}1|/{.{-z,z,x,w-v-vqqrrzsqtgv\zT|LE?;97&5.463>1F0O.X-b+m)z(&$#"####uuvvuwlyb|XNF>60 -+*'(/'8&@$I"R!]huzzzz{p}f\SI@7/' +&/8AKUao ~ +~~uj`VLB80'  %.7BMYguzodZOE;1'  %.8CO]l|sh]RH=3(  +#-7CQaqymbVK?4* + *5CSdvʉʜʯʾ~sg[OC7+ '4CUgzߍߟ߭ߺߺxmaUG9+ $2CVi|  $1=IS]elrw| +,9EOYahnty}(4@KT]dkpuz~"/;EOX_flqvz (5@JSZaglqv{!.9DMU\bhmrv{ +%2=GOW]chmrw}   + +6 A I Q X ^ d i n t z !'&#$0;DLSY_ejpv} ,11.+% "#*$5$?$G$N$U$[$a$f$l$r$y%%%%%%%~%}&|&|%{%*699740++,%-0.:-B-J-Q-W-]-c-i-o-v.~~.|.{.y.x.w.v.u.t.t-t-2=??>;8434 5,555>5F5M5S~5Y}5_|5ez5ly5sw5{v5u5s5r5q5p5o5n5m4m4m49BDDD@>;:;;'<1<:}uAFsALqASpAYnA_mAflAnjAwiAgAfAeAcAc@b@a@a?a?a?DJLLLJGFF}FyF vF*sF3qF;oFBmFIkEPjFVhF]gFdfFldFucF~bF`F_F^E]E\E\D\D\D\CHMOPONKJ|JxJtKpK'nJ0kJ8iJ?gJFeJMdJScJZbKb`Kj_Ks^K|\K[JYJXJWJWIWIWHWHWHLPRRSQN}NwOsO oOkO#hO-fO5dN<bNC`NJ_OQ^OX\O`[OhZOqYO{WOVOTNSNRNRMRMRLRLRLPSTUUUQyRsSnS jSfS cS*aS2_S:]SA[SHZSOYTVXT^VTfUToTTyRSQSOSNRMRMRMQMPMPMPTVWXXX{UtVnWiXeXaX^X'\X0ZX8XX?VXFUXMTYTSY\QYdPYmNXwMXKXJWIWHWGVHUHUHTHTWYZ[[~[vYoZi[d\_\\]Y]$W]-U]5S]<Q]DP^KO^RM^ZL^bK^kI]vG]F]E\C\B\B[BZBYCYCYZ\]^^z^q^j_d`^aZb +VbSb Qc*Oc2Mc:LcAJcHIcPHcXFc`EciCctBc@b?b=aDiEBiMAiU@i^>ig=iq;i}9h8h7h6g5g5f6e6d6dabdd{erehg^iWkQlLmHo EoBo"Ap*?p2=p:4*! (2<IVeuwlaVK@6+!'1=KZj|}qfZOC8-"  +$0=M^płŖũƹwk_TG;0$  !.=Obuڈښ۪۶ۻqeYM@4' ,>Qdx !.:FPYahnty}*6AKU]dkpuz~ %1<GPY`flqvz~+7BKT[bglqvz %1<FNV]chmqv{*6@IQX^chmqv|".9CKRX^chmrx~ '2=EMSY_dintz  + +6?GNTZ`ekqw~~~(**(% %0:BIPV[agmt|~}{zyxwvvu(0220.*$#$ %+%5&=&E&K%R%W~%]}%c|&jz&qy&yw&v&t's'r'q'p&o'n'n&n&1688752., ,-&-0-9}.@{-Gz-Nx-Tw-Zu-`t-fr.nq.vp.n.m/l/k/i/i.h.g.g.g.7;=>=;8533~4"{4,x45v4<t4Cs4Jq4Po4Vn4]m4ck4kj5si5}g5f5e5d5c5b5a5a4a4a4<?ABB?=;:{9x:t:(r:1p:9n:@l:Gj:Mi:Sg:Zf:ae:id:qb;{a;`;_;];\;\:[:[:[9[9@CEFFDA~?z?v? r?o?$l?-j?5h?=f?Cd?Jc?Pa?W`?^_?f^@o]@y[@Z@Y@X@W@V?V?V>V>V>CFHIIHEzCuDpD +mDiD!fD*dC2bC9`C@^CG]CN[DUZD\YDdXEmWEwVEUESEREQDQDPCPCPBQBFIKLLK|HvGpHkHgHdHaH'^H/\H6ZH=XGDWHKVHRUIZTIbSIkRJuQJOINIMILILHKHLGLGLFILNOO}NxKqKkLfMbM_M\M$YM,WM4UL;SMBRMIQMPPMXON`NNjMNtLNJNINHMGMFMFLGKGKGJLOQRRzQtNlPfQaQ]Q YRVR!TR*RR2PR9NR@MRGLRNKSVJS^IShGSrFS}ESDRCRBRAQAQAPBOBOPRST~UvUoRgTaU\VXVTVQWNW'LW/KW6IW>HWEGXLEXTDX\CXfBXp@X{?X>W=W^Z=^c;^n:^y9]8]6]6\5\5[5Z6Y6YVXZZw[n[e\\^V_P`KaGb DcBc @c(>c0'rG&rP$rZ#re!rq q~qqpponmlbd~dtekfbgYiOmGo@q9s1v*x&y$y"y! y)z1z9zAzKzUzazmz{yyxx wvutghyhpigj]lToJrBu:x2z+|#!*2; D O +[hu~~~llullmboXrNuEy;|3+# "+4=HTaopzpqqfs\vRyH}>5,# + #,5@LYgwuvukw`zV~KA7-#  #,6BO^n{zp|eZOD9.$ +!+6DScuuj^SG;0% *6FWi|ocXK@3((7I[nԂԕզճսi]QE8, '8L`s+6ALU^ekpuy} &2=HQY`glquz~!-8CLU\bhmqvz'3=GPW^chmqvz!-8BJRX^chmqv{'1;DLSY^chlqv|*5>FNTY^chmrx +  #.8@HOTZ_diou|  '1:BIOUZ`ekr y ~ } { z y +x +x x !##" +5=DKQV\b~h}o{vzxwutsrppoo$)+,*)%  &/8?}F{LzRxXw^udtkrsq|pnmkjihhhg+/121/-)%$~%!{%+y&3w&;u&Bs&Hr&Np&To&Zm&al&hk'pi'yh'f'e(d(c(b'a'a'a'a'04677530~-z,w,t,&r-/o-7n->l-Dj-Ki-Qg-Wf-^e-ec.nb.wa._.^/]/\/[.[.Z.Z.Z-58;<<:8{5x3t2 q2n3"k3+i33g3:e3Ac3Gb3N`3T_3[^3c]4k[4uZ4Y5X5W5V5U4U4T4T3T39<>@@>{<v:r8n8k8h8e8(c80`87_8>]8D[8KZ8QY8YX9aW9iU9sT:~S:R:Q:P:O:O9O9O8O8<?BCC|Bw?r=m=i=e=b=_=$]=,Z=4X<:W^Q>gP?qO?|N?L?K?K?J>J>J=J=J<?BEFFyEtBnAiBdB`B \BYB!WA)UA1RA7PA>OAENBMMBTLC]KCfJCpID{HDGDFCECECDBEBEAE@BEGI}IuHoFjEdF_F[F WFTFQF&OF.MF5KF<JFCIGJHGRGH[FHdEHnDHyCHBHAH@H?G?G?F@E@EEHJKzLrKkJeI_JZKUKRKOKLK$JK+HK3FL:ELADLHCLPBMYAMb?Ml>Mw=MRF=RNW%a8b4c 1d/d-d&+d-*e5(e='eE&eN$eX#eb!en e{dddcba``WY{Zp[g[_\W]M`Fb?d8f2h+j'k%l#l "l( l0l8l@lIlTl_lklxllkjjihg\]v^l^c_[`RbIeAh:j3l,o$qsttt"t*t2t;tDtN tZ tf tttssrqqpo`}aqbhb_cVeMhDk;n4q,s%uxz| +| ||$|,|5|>|H|T|`|n|}|{zzyxxewemfdfZhQkHo?r5u-x%{} %.7BMZhw}jrjij_lUoKsAv8z.}&  '/9ER`oxnnncpYsNwD{:0&  &0;HWgxtshu]xR|G<1'  %0=L\nmzb}WK?4)#0?Pbug[PD7+  "1BUh|ϐϢϱϽaUI=0# +"2FZn&2=HQY`glquy~ +".9CMU\bhmqvz~)4>HPX^chmqvz #/9BKRY_dhmqvz)3=EMTZ_chlqv{ #-7?GNTZ^chlqw~&09AIOTY^chmsz*3<CIOUZ_diov~~}||{{ +  "-6=DJPUZ`fl~s|{{yxvutsrrr & +0 8 ? E~ K| Q{ Wy \x bv iu qs yr p o m l k j iii"%&%#  |*z2x:wAuGtMrSqYo_nflnkvihfedcbaaa$)+,,*(~$}{wt%r.p5n<mCkIjOhUg\ecdkb ta ~` ^!]!\![ Z Z Z Z *.0220|.x+v's% +p%m%!k%)i%1g&8e&?d&Eb&Ka&R_&X^&`\'h['qZ'|X(W(V(U(T'S'S'S'S&.2566|5w2s0p-m,j+g+d+%b,-`,5^,;\,B[,HY,OX,VW-]U-fT-oS.zR.Q.O.N.N.M-M-M-M,268:~:w9s6n4k2g2d1`1^1"[1*Y11W18V1>T1ES1LQ2SP2[O3dN3mM3xL4K4I4I4H3G3G2H2H259<={=t<n:j8f7a7^6 +[6X6U6&S6.Q64O6;N6BL6IK7QJ7YI8bH8kG8vF9E9D9C9B8B8B7B7B69<?@x@p@j>f;a;\;X;U;R;O;#M;+K;1H:8H;?G;GF?>>=>===<<=<=;=;<?A~BuCmCgAb?\?W@S@O@L@J@ G@(E@/C@6B@=AAE@AL?AU>B^=BhE4=F;KP:P 7Q5Q4Q'2Q.0Q6/R=.RE-RN+RW*Rb)Rm(Rz&R%R%Q$Q#P$O%O&NIK{MpNgN_OXOOPGRAS_G_Q`\`h_u__^^]\[[QSsThT`UXUPVHX?[9]2_,a%deffg"g*g1g:gCgMgX gd gq ffeedccbUzWnWdX\XTYL[C^;a4c-e&hjln + o o +o$ o,o5o>nHnSn_nln{nmmlkjjZt[i[a[X\O^Ga>d6g.j&loqsuvvvw&w/w8wBwMvYvgvuvuuttss{^o_e_]`SbJdAh8k/n'qtvy{|} ~~!(1;FS`o~~}||uckcbcXeNhDl:p1s(wz| !*3>KYhypggg\iRmGq=u3y)}   !*4AO_pllanVqKv@z5*    *6EUgzfsZvO{C8,!  )8I[o_{TH<0# *<ObvɊʝʭʹYMA4(,@Th| +".9CMU\bglquz~)4?HPW^chmqvz %/:CKSY_dhmqv{*4>FNTZ_chlqv{ $/8@HNTY^cglqw})2:BIOTY^cglrx ",5<CIOTY^chnt|%/7>DJOTY^djpx~|{yxwvvuu  (18?EJ~P}U{Zz`xfwmuut~sqponmllk + "}+{3y:x@vFuKtQrWq]pcnjmsk|jhgfedccb! }}{ x v %s -r 5p ;oBmHlMjSiZgafhdqc{a`^]\[ZZZ"&''}%y#vts +qn k(i0h7f=eCcJbP`V_]]e\nZxYWVUTSSSS#(+,~,x+s)p&m#lifd$b,`3^9]@[FZLXSWZU cT lS!vQ!P!O!N!M!L L L L (,/0z1s0n.k+h(e&b% `$]$ [%(Y%/W%6U%<T%BR%IQ%PP&XN&`M'jL'tJ'I(H(G(F'E'E'F&F&,034v4o4j2f/c-_+\+Y*V*T*$R*+P*2N*9M*?K+FJ+MI,UH,^F-hE-rD-~C-B-A-@-?,?,@,@+/36{7r8k7f6b3^1Z0V0S0P0N/ K/(I//G/5F/<E0CD0KC1SA1\@2f?2q>3}=3<3;2:2:2:1:1;0269x:o:h:b9]7Y5U5Q5M5 J5G4E4%C4,A42@59?5A>6I=6Q<7Z;7d97o87{786757574646555569;u=l=e=^<Y;U9O9K:G:D:B:?9"=9);:0::79:?8;F7;O6r?i@b@[?U>O=J>F>B?>?<?zAoBfB^BWBQBJBEC@CO7Q1R+T%V XYYZ Z(Z0Z8ZAZKZV Zb Zo +Z} YYXXWV UKvMjN`NXNQNIOBQ:S3V,X&Z \_a aa a# a+ a4a=aGaQa]ajax``__^]]~OqPfQ]QURMRET=V5Y.\'^ ace +ghiii'i/i8iAhLhXhehshggffedxSlTbUYUQUIW@Z8]0`(c ehj +lno ppq!q)q2q;qFqRq_qnp~poonmmrXgY^XVYL[C];a2d)g!jmp rtvv wxyy#z+z5z@zLzYzhzxzyxxwwm\c\Z\P^Gb=e4i+l"psvxz|~ $-7DQ`qha_aUcJf@j6n,r#vy|$.;HXi{deYgNkDo9t.x#| +#/=M_q^lSpGtFNTZ_chlqv{%/9AHOUZ^cglqv} + *3;CIOTY^bglrx$-5=DJOTY]bgms{ '07>DJOTX]chow~|{{zzz !*18?DJOT~Y}^|dzkysw{vtsrqpppo $~,|3{:y?xEwJvOtUsZrapgoomxljihgfffe }| +zxv&t.r4p;o@nFlKkQjWi]gdfmdvca`_^]]\\{wut t qn l(j/h6g<fBdGcMbT`Z_b]k\ tZ Y W V U TT S S !"z"t!pmlkjge#c*a1_8^>\D[JZQXXV`UiSsR~PONMLKLL"%~'u'o&j$g!ecb _][&Y-W4V:T@SGQNPUN]MfKqJ|IGFEDDDE"'*z+q,j+e)b&_$]![XVS"Q)P0N6M=KCJKHRG [F dD!oC!zB!@!?!>!> = > >&*-v/m/g/a-]+Z(W&T%R$ O#L#J#%I#,G$3E$:D$@C%HA%P@&X?&b>'m<'y;':'9'8'7&7&8%8%*.}0s2j2c2]1Y/V,R*N*K) I)F)D)"B))@)0>)6=*><*E;+M:+V8,`7,k6,w5-4-3,2,1+1+2+3*-1z3p4g5`5Z4U2Q0M/I/E/B.@.=.;.&9.,8.47/;6/C50K40T21^11i02u/2.2-1,1,0+0,/-/03w6m7d7]7V7Q6L4H3C3@3<3 :37353#33*24114905@/5I-6R,6\+6h*7t)7(6'6&6&5%5'4'336t8j:a:Y:S9M9H8B8>8:8784919/9!-9(,9/+:6):>(;G';P&;Z%-? +?)?'?%&@,$@4#@<"@D ANAXAdApA~AA@@?>>9z<n>c?[?S?L?F?@?7A3B.C*D'E +$E"F F"F)F1F9GBGKGVGaGnG|GFFEEDC=v?jA`BWBPBIBCBM7O0R(T!WZ\ ^`a bbc!c)c1c;cFcQc^clb{ba``__pMdNZNRNJNBP:S2U*X"\^a cegh ijjk$l,l5l@lLkXkgkvkjihhgjR_RVRNRET=W4Z,]#`cg ikmopq rstu&u/u9uEuRuaupttsrqqdV[VSVIX@[6^-b$fil +ortvwyz{ |}~'1=JYi{~}|`ZXZM\C_9c/g%kosvy{} +(4AQat]^R`GdGNTZ_cglqv{&09AIOUZ^cglqv} !*4<CJOTY^bglrx%.6>DJOTX]bglsz (08>DJNSX]bgnu~"+29?DINSX]c~i}q{yzxwvuuttt +%,3}9|?zDyIxNwSvYu_sermqvonmlkjjii~{ zxv'u.t4r:q?pDnJmOlTk[ibhifre|dcaa``__ z vusqon!l(k/i5h;f@eEdKbQaW`^_f]p\zZYXWWVVV xrnlk j hfd#b*a0_6^<]A[GZMYTW\VdTnSxRPONMMMMzrlhecbb _][%Y,W2V8U>S DR KP +RO +ZN cL mK xI H G F E D +D +D +!u"m"g"b ^\ZZXVT R(P.O4M;LAJHIPGXFaDkCwA@?>=<<=!|%q&i&b&]$Y"VTRQ NLJ$H*G1E7D>BEAM?U>_=i;u:9866556!%x(m)e*^)X(T&Q$O!LJGEC A'?->4<;;B:J8S7 ]6 g4!s3!2!1!0!/ ./0$(u+j,b-[,U+P*L(J%F$C#A# >"<":"#8"*6#15#84$?3$H2%Q0%Z/&e.&q-&~,&+&*&)%(%)$*$(~+r-g/^/W/Q.L-H,D)A(=(:( 8(5(3' 1'&0(./)5-)=,*E+*N*+X)+d(,p',}%,$+#+#*"*#)$)*{.o0d1\2T2N1H0D/@.;-8-4-1-/---+-$).+(.3'/;&/C%0L$0V#0b!1n 1{100//..-x1l3a4Y4Q4K3E3@2;26222/2+3 )3'3%3"#4)"40!48 5A5J5T6`6l6z66554330u4i5^6V7N6H6B5=57507,7)8%8"9 9::&:.:6;>;H;R;^;j;x;;:: 9884q6e8[9R9K9D9?89839,;(<#=?? @@@#@+A3A<AEAP A[ Ag +AuAA@??>={7n:b;X<O<H<B;<;6;0=)?$@BDFGG G G' +G0G8GAGLGWGcGqGFFEEDCw;i=^>T>L>E>?>9>2?,A%D EGJLN NNN$N,N4N>NHNSN`NmM|MLLKJJr?e@ZAPAIABAM6O-S%VY] `bdghikl mno q(q2q>qKpYpipzonmlk\PSOLOBQ9T0W'[_b fikmoqrtuv xy{"|+|7|D|R{c{tzyyxwXSPSFUEJOTY]bglsz  )18?EJOSX\bgnu~#+39?DINSW\bipy~|{zzyyy &-39?D~I}M{RzXy]wdvluts~rqponnnn~|{z y'x.w4u:t?rDqHpNoSnYl`kgjphzgfedcccczwus +qpn"m)l/k4j:h?gDfIeOcUb\ad_l^w][ZZYYXX ~ +v +qnljh ged#c*b0`5_:]@\E[KZQXXW`ViTtSRQPOOOO woiec +ba_]\Z%Y+W1V6U;SARGQNOUN^MgKqJ}IHGFFFF|qic_\ZY +X WUS Q&O,N2M8K>JDHKGSF[DeCpB|@?>====wmd^YUSQPP + NKJ "H (F /E 5C +;B +BA +I? Q> Z< e; p9 }8 7 6 5 4 4 4 si!`!Y!T PMKIHGECA%?+>2<8;?9G8P6Y5c3o2|1/.-,,-| o#e$\$U$P#K!G ECB? +=;9!7(6.453<2D0M/W.a,m+z*('&%&&y#l&b'Y'R'L&G%C#@!>;86420$.+-2,:+B)K(U' `& l$ y# " !  "v&i(_)V*O*I)C(?&;%8#5"2"0" -!+!(!!'"(&"/%#7$$@#$I"%S %^&j&w&%%%$#"%r)f+\,S,L,E+@*;)7(3'0',')'''$'"'!(% (-)5)=*F*Q+\+h+v++**)((}(o+c-Y.P.I.B.=-8,4+/+*,',#, - -..#.*/2/;/D0N0Z0f0t0 0 / / . - -z+l.`0V1M1F1@0:/5/0.+/$1!223 444 4(50585B 5L 6W 6c6p6554332v.i1]2S3J3C3=27221-1(2"5679: : : +:% :-;5;>;H;S;`;m;|;:9987r1e4Y5O6G6@5:55404*5$79:<>A AAA"A)A1A;ADAPA\AjAxA@?>>=n5a7V8L8D8=88727,8&: <>@B DF +GGHH&H.H7HAHLHXHfHuGFFEDCi9\;R;H;A;;:5:.;(="?BDF HKL MNOO"O*O3O=PHPTObOqNNMLKJd=X>N>E>?=8=1?*@#CFHK MORST UVWX%X.X8XCXPX]WmW~VUTSR^ASBJACA<@4B,D%GJMPSUWYZ\ ] ^`a a)a3a>aKaXah`y_^]\[YEOEGD@D7F/H'LORVY[^`bcef gijl"l,l7lDlRkbksjihgfTILHDH;J2M)P TX\_begiklnoq stvx%x0x=wLv\wmvutsrPMIL?N5Q+U!Z^cfjmoqsuwy{|~ '4BSeyNQCS9V.[#`e inruxz} +)8I[oHX<\1`&fkqvz~->Qf|Aa5f)lrx~ 2EZp:l-r!x$8NdyЍϞ'1:BIPUZ_chmrw~ ",5=DKPUZ^cgmry&/7?EKPUY^bgmt{ !*29@EJOTX]bhnv~$,3:@EJNSX]bipy &-4:?DIMRW~]}d|kzty~wvutssss~ }(}.{4z9x>wCvHuMtRrXq_ofnomykjihgggg{xvt srr"q)p/n4m9k>jCiHhNgSeZdbbkau`^]\\\\\}vqnljihff#e)d/b4a9`>_C]I\O[VY^XgWqU|TSRRRRRumhdca_ ^]\[$Z*Y/W5V:U?SERKQROZNcMnKyJIHHHHHy o f a \ +ZXWV USR Q%O+N0M6K;JAIHGOFWEaCkBwA@????? siaZVRP ONM KJI!G'F,D2C8B>@E?L>U<^;i:u9876666{nd\UPLIGG +FECA?#>)<.;4:;8B7J6S4]3h2t1/..---wj`WQKGCA@?> + +< : 8 7 %5 +4 +22 +91 @0 I. R- ]+ i*u('& % $ $ $ +sg\TMGB>;9875 310".(,/+7*?(G'Q%\$h"t! ~pc Y!P"I"C!> :7420. ,*(&%%,$4"<!E OZfs{m!a#V$M$F$@#;"6!3 /-*'% " "*1:CMX d q  x j#^%S&K'C&=&8%3$/#+"(!$!!!! !!""'#/#7$A$K%V%b %o %} % +% $#""t#g&[(P(H)@(:(5'0&,%(%$%&&''((($), )5 )> +*H *R*^+l*z**)(''q&c)X*M+E+>+7*2)-()(%' (*+,- . +. .".)/1/:/D0O0[0h0w//.-,,m)`+T-J-B-;-5,0++*'*"+,./1 3 4444&4.575A5L5X5e5t543221j,\.Q/G0?08/2..-)-$./134 +68 9::;#;+;4;=;H;U;b;q;:9877e/X1M2D2<26100+0&1 2468 +:<>? @AB B(B0B:BEBQB_BnA~A@?==`3T5I5@59443.3(4"68:< +?ACEF +GHJJ$J,J6JAJMJ[JjI{HGFED[7O8E8=77616*7$9<>A DFHJLMO PRSS(S1S=SISVRfQwQONMLV;K;B;;:59-;&=@CF ILNPRTUW YZ\]"],]7]C]Q\a[rZYXWVQ?G??>9=1?(A DHKORTWY[]_`b dfgh&h1h=gLg[gledcb`LCDB=A4C+F"IMQUY\^acegijln prtt)t6tDtTseryqpnmIFBE8G.J$OSX\`dfiknprtvwy|~!-<L^r~|{FJSi2e%ls y 1G]s·˚ ",5>EKQV[_dhmsz'08?FKQUZ^chnu| !*3:@FKPTY^ciow$-4:@EJOSX]cjqz '.5:@DINSX^dlt~}|{zzzy!(/5:~?}C|HzMyRxXw_uftoryqonmmmmm{yx wvv"v)u/s4r9q>oCnHmMlSjZiagjftdcbaa``a~wromlkjjj#i)g/f4d9c>bCaH`N^U]][fZpX{WVUUUUUumheca` +_^^^$\)[/Z4Y9W>VCUJSQRYPbOlNwMLKJJJKwme_[YXVU TTSR$Q*O/N4M9L?JEIMGUF^EhDtCBAAAAA|pf ^ XSPOMLKJII G%F*E0C5B;AB?I>Q=[<e:q9~888778w j `XQL I +FEDC +BA@?!=&<,;1978>7F6N4X3c2o1|0///// +rf[SLGC@ > <<; 9875#4(3.140;/C.L,V+a*m)z(''&&'|nbWOHB>:75 4 43 1/.,%++*2)9'A&J%U#`"m!z xj^TKD>9520.- , * ( ' % "$ +(# +0! 7 @ J Uan|    +ug[PHA;61.+(&%# +" '.6?IT`m{    rdXME=72.*&#!$,4=GR ^ j +x oaU J!B!;!5 /+'#  ! ( 1 +9 CNZ f tl^ R"H#?#8#2"-!( $   ! +!!""%#-#6$?$J$V%d%r$$#"! h [#O$E%<%5%/$*#&""!  !" $ &'''("(*)3)<)G*S*a*o))('&%d#W&L'B'9'3'-&(%$$ ##$%' +)+, -.. .'/0/9/D/P/^/m/}.-,+*a&S)H)?*7)0)+(&'"&&')* +,.02 3455$5-566A6M6[5j5z43210\*O+E,;,4,.+))$))+,. +02468 9 ;<=J=WACEGHJ LNN!N+N6NBNOM_LpKJIHFM5C5:443.2&469; +?BDGIKMOQS UWYY%Y0X<XJWZWkV~TSQPH9?88726*8":=A +DHKMPRUWY[]_ acdd*d7cEcTbeay`^][D<<;6:-<$?BF +JNRUWZ]_acegil nqr"q/q=pLo^nrmljhA?:>1@'CHL QUZ]`cfhkmoqsuxz }'5~E}X}j|zyx?C5E*I MS X]bfimoruxz|~*;Maw9J.N#SY _ejosvy|/BVk2T&Y_ fmsx}$6K`v*_flsz+@Vĺɕ'19@GLQV[_diov "+3;AGLQVZ_djqy%.5;AFKPUY_eks| '/5;AEJOSY_emv}")/5;?DINSY`}g{pz{xwvuttsq~ ~~~#}){/y5x:w>vCtHsMrSpZobmklujiggffgfzvsqpoooo#n)m/k4j9i=hCfHeNcUb]`f_p^|\[ZYYZZvoifdcc cbbb$`)_.]3\8[=ZCXIWPVXTaSlQwPONNNNNvld_[YXWV VVVU$T)R.Q3P8O>MDLKJSI]HgFsEDCCCCDznd\VRONMLK KKKI$H)F.E4D9C@AG@O>Y=c<o;}:9999:sg]UNJFECBB +AAA@>%=*;/:59<8C6L5U4`3l2z100001|naW O +H C?=;:98 8765 3&2+1108.@-H,R+]*i)w((((((xi ] RJC> 9 6 4210/ /.,+"*().'5&=%E$O#Z"g!t  s e YNF?941. + +*)( '&%#"$!+ 2:CMYeso aUKB;50,(&# " +!  +!(/8ALXdrl^RH?82-($!   +  + + + +& . 7 B M X +d r   +i[OE<5/)%!    $ +, 4>HTao~fXLB92,'"   !(1;EQ^m|cUI?6/)$   &.8CO\kz_RF<4-'"   + !!"#"+#5#@$L$Z$i#y#" \N C!9"1!*!%    "$ & (((!)))2)=)I*W)f)w('&%#X!K#?$6$.#("#! ! +"$&(*, .///&0/0:0F0T0c/t.-,*)S$G&<&3&,%&$"#""#$ +&(*,/13 5 777#7,777C7P7`6q54310O(C)8)0(*'%& %%'( +*-/1468:= +?@@@(@3@?@L?\>m=<:98J+>,5+.*()#()+- +/2479<>@BEG IJJ$I/I:IHHWHiF|ECB@D/:/2.,,'+ -/1 47:=?BEGIKNPRUUU)T5SCSRRdQwOMLJ@27200+/#036 :=@DFILNQSUWZ\ _a`$`0_>_M^^]q\ZXV<654/3&58; ?CHKNQTWZ\^acehk non(n6mFlXkjihfd9937*9 <A EJOSWZ]`cfhjmoqtwz +~~ }.|>|O{byxxut7<->#BG LRW\`dgjnqsvx{} +$4F[p1C'GMSY_ejnqux| );Oe|*MSY`gmsx{ /CYo"Y_gnu|#7Mcx΋ +  !"$%&()*+-./02346789;<=>@ABDEFGIJKMNOPRSTUWXY[\]^`abcefgijklnopqstuwxyz|}~ +  !"$%&()*+-./02346789;<=>@ABDEFGIJKMNOPRSTUWXY[\]^`abcefgijklnopqstuwxyz|}~ +  !"$%&()*+-./02346789;<=>@ABDEFGIJKMNOPRSTUWXY[\]^`abcefgijklnopqstuwxyz|}~ +  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~mft1! +  !"#$%&'()*++,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ +  !""#$$%&&'())*+,--./01223456789:;<=>?@BCDEFHIJLMOPRSUWXZ\^`bdfhjmoqtvy|~ +  !""#$$%&&'())*+,--./01223456789:;<=>?@BCDEFHIJLMOPRSUWXZ\^`bdfhjmoqtvy|~:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ:F9MjF˻hྵ;F:MkFʻi᾵;F:MlFɺj⾵;F;MmFɺk㾵;FMqFǸn辵<G?NrFƸo꾵=GANtGŷp뾶=HBNvGķq>HEOyHöq𾶔 ?IHP|Iµq򾶈#@JLQKZ⽶@'A"LQSTfϸǂ򷼞+B'NVW`hý̭קʄޢȆƉŋōďđēÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ/C,Q\\|gggmsǒx̍|ωЀчσӅφԃΉՁΌ͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏2 F2SV^n__`ciou|yz}wڀvلt؇r؋r؋r؋r؋r؋r؋r؋r؋r؋r؋r؋r؋r؋r؋r؋r؋r؋,?/IYR[ʳή,?/IYR[ʳή,?/IYR[ʳή,?/IYR[ʳή,?/IYR[ʳή,?/IYR[ʳή,?/IYR[ʳή,?/IYR[ʳή,?/IYR[ʳή,?/IYR[ʳή,?/IYR[ʳή,?/IYR[ʳή,?/HYR[ʳή+>.HYQZɳ㽵+ >.GYPYȳ併+ =.FXOXȳ彵+ =-FXNWdz罵+ <-EXNVdz轵* ;-EXMUƳ龵* ;,DWLTų뾵* :,CWKSŲ쾵* ;+DVJQIJ) <+EVHOòᄉ) +=*FUGMij, +?)HTHJĵ{쾵0 A'JRKBƺh龵4B(KUL?Rή>6 C+KZMNhոņ񴾘8 D0M`S]oŲ~ҭ˄ܨȆƈŊČĎÏÑÒԖ––––––––––––––:E6Oe\iimsțxΗ|ғՐ͂׍ً̇ͅډ̉ۇˋۅˎ܃ʐ݃ʐ݃ʐ݃ʐ݃ʐ݃ʐ݃ʐ݃ʐ݃ʐ݃ʐ݃ʐ݃ʐ݃ʐ݃ʐ݃ʐ<GJ@X^Zs[\_bfl{rxvvzt}rހq݃o݆n݊n݊n݊n݊n݊n݊n݊n݊n݊n݊n݊n݊n݊n݊n݊@HHBTk`geglptŊwdžzɄ}ʂˀӂ~҄}҇{ыzэzэzэzэzэzэzэzэzэzэzэzэzэ(@KGZi`__adinr}v{yy|w~vځtڄrوqًqًqًqًqًqًqًqًqًqًqًqًqً.B%OGVaVtXZ]aeziwntrrvqyo|nl₰jᇱiቲiቲiቲiቲiቲiቲiቲiቲiቲiቲiቲiቲiቲ4 +A'GAJUNeQrU}Y}^wcrgollqjtiwgzf~dꁠc酡b鈢b鈢b鈢b鈢b鈢b鈢b鈢b鈢b鈢b鈢b鈢b鈢b鈢. 5#;6@GFVJcPm{Uuu[|o`kfhkeocsbv`y_}]\[[[[[[[[[[[[[ڱ3B?Ra_irۣ}ӡΡʟǞŞÝ󼞴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴ڱ3B?Ra_irۣ}ӡΡʟǞŞÝ󼞴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴ڱ3B?Ra_irۣ}ӡΡʟǞŞÝ󼞴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴ڱ3B?Ra_irۣ}ӡΡʟǞŞÝ󼞴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴ڱ3B?Ra_irۣ}ӡΡʟǞŞÝ󼞴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴ڱ3B?Ra_irۣ}ӡΡʟǞŞÝ󼞴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴ڱ3B?Ra_irۣ}ӡΡʟǞŞÝ󼞴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴ڱ3B?Ra_iqۣ}ӡΡʟǞŞÝ󼞴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴󺟴ٲ3B>Ra_ipڧ|Ҧ˥Ǥãٲ3B>Ra_io٫{ЪɨĨٳ3B>Ra_hnخ{ϮǬ¬򾰤س3B>Ra_gnزzαƯش3C>Ra_gm׵yͲIJ쾵ش3C=Ra_fl׶w̲òش3C=Ra_fk׷t̳ò𽶦״3C=Ra_ei׹p̴²񽵥׵3C=Ra^ef׻m̵򽵣ֵ3C=Ra^ccؽh̶z󾵠ֵ3C=Ra^a_b͹t򾵜ֵ3CG|DRuKZnQaiWfd]jabm^go\kqZosXrtWuuVxvT|wRyQzQzQzQzQzQzQzQzQzQzQzQzި-;3LQZkels|ߒې؍֋ԈӇ҅фуЃςȄ†††††††††††ި-;3LQZkels|ߒې؍֋ԈӇ҅фуЃςȄ†††††††††††ި-;3LQZkels|ߒې؍֋ԈӇ҅фуЃςȄ†††††††††††ި-;3LQZkels|ߒې؍֋ԈӇ҅фуЃςȄ†††††††††††ި-;3LQZkels|ߒې؍֋ԈӇ҅фуЃςȄ†††††††††††ި-;3LQZkels|ߒې؍֋ԈӇ҅фуЃςȄ†††††††††††ݨ-;3LQZldkr{ޕڒ׏ԍӋщЈІφυ˅Ňؿؿؿؿؿؿؿؿؿؿؿݩ,;3LQYlcjpyݙؖԓґЏύ΋͉̈ˈŊ޿ݹݹݹݹݹݹݹݹݹݹݹܩ,;3KQYmbhovܝ֚ӘЕΓ̐ˎʌʋŌ⿎⺏ⵐᵐᵐᵐᵐᵐᵐᵐᵐᵐᵐܪ,;2KQYmagmtۡ~՞ќΙ̖ʓɑȏǏ纒浓汓屓屓屓屓屓屓屓屓屓屓ܪ,;2KQXm`flrڥ|ԢР̝ʙȖǔƒ“껕궖겖鮖讖讖讖讖讖讖讖讖讖讖۫,<2KQXl_ekpک{ӦϤˠȝƙŗĖ쬙꬙꬙꬙꬙꬙꬙꬙꬙꬙꬙۫,<2KQWl^djoڮyӫΨʤǠĝÚ񸝵񳝵𰝶𭜶쪛쪛쪛쪛쪛쪛쪛쪛쪛쪛۫,<2KQVk^dinڳwӰͭɩťá󼠳󭡴򫟵𨞷۬,<2KQVj]~chlڷsӴͲȮĪ󿥩󩢵񦠶ڬ,<2KQUi\}bfhۼmԸxδȲIJ򤡶嵐嵐嵐嵐嵐嵐嵐嵐嵐嵐ڬ,<1KQUh\|bbceվoϺzɷĵ򢣶ڭ,<1KQTg[z^^^^dmvz껾񟤶ڭ,<1KQTe[x[ZYXXcp߻Ą򦽝󝩵𜥷٭+<1JQScXuVUUX[lӻ~ߵŎ򘿦󗵴򗯵񘫶엧엧엧엧엧엧엧엧엧엧ٮ+<1JORaTqQVZZcƻuӶʈݭljȓ쒪꒪꒪꒪꒪꒪꒪꒪꒪꒪꒪د+<0ILR]OkSwY[^kƶ}Ѯ̃٥ɅljŏĘäñ뇾ꉵ鋯苯苯苯苯苯苯苯苯苯苯د+<0HIMWLbWu[_esĭyͥ}՝́ڕʅގȋǓƝƩƶ偿僶䃶䃶䃶䃶䃶䃶䃶䃶䃶䃶ְ+,MEVd_~fdcekpuz}րyՆvԌtӒqӚpӥnӵnӵnӵnӵnӵnӵnӵnӵnӵnӵnӵӴ )8E(OIYfa|__`cgmr{wx|tہrۆoڌmٓkٛi٧i٧i٧i٧i٧i٧i٧i٧i٧i٧i٧Ҷ( :H-QLXeYwZ[^ae|ixotsrxo}mⁱkᆲifdߜdߜdߜdߜdߜdߜdߜdߜdߜdߜdߜй?J1MKP_RoT{W[_yctgqknpltixg|f逢d酣b苤`瓥`瓥`瓥`瓥`瓥`瓥`瓥`瓥`瓥`瓥`瓥ͼ":?0CEHVKcOmSu|W{w\r`ndkhhlfpdtbwa{_][[[[[[[[[[["14+:@gEFbLL]RPZWSV\VTaXReYPi[Nm\Mp^Kt_Jx`H~aFcFcFcFcFcFcFcFcFcFcFc'6)GBVX`jhzpx톂ꂊ|ywutrqĹp͹qӺtԺwԹwԹwԹwԹwԹwԹwԹwԹwԹwԹ'6)GBVX`jhzpx톂ꂊ|ywutrqĹp͹qӺtԺwԹwԹwԹwԹwԹwԹwԹwԹwԹwԹ'6)GBVX`jhzpx톂ꂊ|ywutrqĹp͹qӺtԺwԹwԹwԹwԹwԹwԹwԹwԹwԹwԹ'6)GBVX`jhzpx톂ꂊ|ywutrqĹp͹qӺtԺwԹwԹwԹwԹwԹwԹwԹwԹwԹwԹ'6)GBVX`jhzpx톂ꂊ|ywutrqĹp͹qӺtԺwԹwԹwԹwԹwԹwԹwԹwԹwԹwԹ'6)GBVY^kf{nu膈傐|zxvtsƽrоuѾxѽzҽzҽzҽzҽzҽzҽzҽzҽzҽzҽ'6)GBTY\kd{ls|犅䆍႕}zxvuvy|¿}¿}¿}¿}¿}¿}¿}¿}¿}¿}'6(FBSX[kb{jqx捂⊋݂|zxw{~ƺƺƺƺƺƺƺƺƺƺ'6(FCRXZja{hnuፈމ܅ځ~|z{ʻʵʵʵʵʵʵʵʵʵʵ&6(FCQWXi_{fls|ݍڈ؄ր~|ɀλζαͱͱͱͱͱͱͱͱͱ&6(FCPVWi^zdjpxܐًևԃӀ̀„ѻѵѱѭϭϭϭϭϭϭϭϭϭ&6(FCNUVg]ybhntߚ~۔؏Ԋ҅тƅռյհԬөҩҩҩҩҩҩҩҩҩ&6(ECMTUf[wafkqߠzۙ֔ӍЇτؾصٯثר֥ԥԥԥԥԥԥԥԥԥߢ &6(DBLSTeZu`dimt۠~֙Ғϊƈ۶ܮܪۧ٤آբբբբբբբբբޣ &6(DAKRScYs^cfjoܩx֡Ҙ͌ۺ߭ߨޥݣٟۡ֟֟֟֟֟֟֟֟֟ޣ &6(C@KPRaXq]behk޷nծzɠһެ㥖⡖ࠖޞܝڜלללללללללޤ &6'B>JOQ_Wn\}^`bfjʸtĻӪߝ囜㛛ᚚߚݙڙؙؙؙؙؙؙؙؙؙݤ &6'A=IMQ\WkYxZ\`_foį|қތ呣㓠ᔝߕݕڕؕؕؕؕؕؕؕؕؕݤ %6'A;IKQYUfUrV{clhck£wю}Žㆮ⋦ޏܐڑבבבבבבבבבݥ %6'@9IHPUQ`Qibnfikllu·̈zɨ}߂ކ݈ۊٌ֌֌֌֌֌֌֌֌֌ܥ %6'@7HCNOLX\]asdgjimw˄φz̜w̼z~ځل׆ՆՆՆՆՆՆՆՆՆܦ +% 6'?3G>HFUJ[b`ydhgfmwȁ҃yϔuϫsvy|ۧ % 5%>.F6J:UO[h`}fedemv~ՁvӎrҟpҶnqtwwwwwwwwwwڨ$ 4 <'=*N9VT\lbcabemuz~t׉o՗lէkջiloooooooooo٩$ 29F"P>WY^o_^_adk|sw|q܅mڐjڜg٪fٽeggggggggggث# +-8H'QCX[ZoZ[]`d|jwqrynၲjgߓeޞcޫa޽aӸaӸaӸaӸaӸaӸaӸaӸaӸaӸ֭ܵ" !>K,QFR[TmU{W[_|cvhronvj}g愩d匪b䔬`㞭]㫮\㾮\㾮\㾮\㾮\㾮\㾮\㾮\㾮\㾮\㾮ԯڸ"?G/HFKXNgQsU|Y|]vbqgmmisfyda셝_댞]ꔟZꞡX髡X髡X髡X髡X髡X髡X髡X髡X髡X髡Ҳ׻&:?/@BERI_MiRqzVwt[|o`kegjdobt_y][YVTTTTTTTTTT϶$15+8;>HCS~I[wNbqSglXkg]odbraft_kv\owZsyXxzV}|T}R~OOOOOOOOOO̺'+#/06;z=DsCKmIQhOVcTY`X\]]_Za`XebVidTmeRqfPuhNyiLjIlIlIlIlIlIlIlIlIlIl!~&$u.-n64h=:cC@^IDZOHWTKTXMR]OPaQNeSLiTJmVHrWFvXD|ZB[B[B[B[B[B[B[B[B[B[ zrk& d/'_8-Z?2UE6RK:NQuI<{J:L:L:L:L:L:L:L:L:L:L# 3 D4RF[Vddmq|v{yuqnljhfed˞c՟dݟfߟilllllllll# 3 D4RF[Vddmq|v{yuqnljhfed˞c՟dݟfߟilllllllll# 3 D4RF[Vddmq|v{yuqnljhfed˞c՟dݟfߟilllllllll# 3 D4RF[Vddmq|v{yuqnljhfed˞c՟dݟfߟilllllllll# 3 D4PFYVaejrs}|}yuqnljhg¢eͣdڣgݤjߤnooooooooo" 3 C5NFWV_ehrp~y|xtqnljhĦgЧhڨkݨnާqިrިrިrިrިrިrިrިrިrި" 2 C5LFUV]eesnv󀁑{wtqnljƪiӫkڬoܫrܫsܬtܬtܬtܬtܬtܬtܬtܬtܬtܬ" 2B5KESU[ecsks}zwspmkȮk֯oگsگtگvڰwڰwڰwڰwڰwڰwڰwڰwڰwڰ" 2A4IDQTYdarhpy~zurom̲nֳsسvسwشxشyسyسyسyسyسyسyسyسyس" 2?3GCPSWc^qemu퇀邊}xtpnѶsնwշyշzշ{շ|ն|ն|ն|ն|ն|ն|ն|ն|ն! 2>2FBNRUa\pc}jq{釆倒{vqrӺxԺzӻ|ӻ}ӻ~ӺԹԹԹԹԹԹԹԹԹ! 2<1E@MPS_Zn`|fmu苁兎~xsżwѽ{Ѿ}ѿѿѾҽҼҼҼҼҼҼҼҼҼ! 1<0D?LNR]Xk^ycip{ወ܃|w{°«¨пѾѾѾѾѾѾѾѾѾ ! 1;/D=KLRZWh]vagmޛwדЊɂ~ĹƯƩťĢàппппппппп ! +1;-C;JIQWVe[r`~dޮjեt͚~őǮɦɢǟƝěÚ ! +1:,B9JGPTUaZm^x߾a׷gͬpġzèɡ̝˚əǘƗĖ  +1:*B7IDOPT\Yf\o\}оcƳluĜ˕Δ̓ʓȓƓĒ’’’’’’’’  +09)A4H@NKSUU]WfX|`hr}ĐˈΊ͌ˍɍǎώŽŽŽŽŽŽŽ  +08&@1G(C.D2V7]Ka`av[]fp~~qǕg˿mrvz|~~~~~~~~~ + -5;!?$N'V=]Rbedwb`cmv{jړcٷfjnruxѿxѿxѿxѿxѿxѿxѿxѿxѿߞ  +27CO-WC]X`j^{]^b}kszjތeݥbȺcҽgѾjѾmҽpҼpҼpҼpҼpҼpҼpҼpҼpҼޟ(-2 FP2XI[]ZnY}Y]bxkpxi⇯dᙳ`ఴ^д`ֶcշfոhշhշhշhշhշhշhշhշhշݡ"": I R7UMU_UoU|X]|cskmvg炧b吪^䡬\㶭Zҭ]ڮ_گaٰaٰaٰaٰaٰaٰaٰaٰaٰܢ<I%M;OOO`PnSyW~\vcojjte~aꉠ]関Z襣W踤VФYܤZߦZߦZߦZߦZߦZߦZߦZߦZߦڤ";D)G=HNJ]MiRsV{w\pbkifqby^[XUSR͚TݚTݚTݚTݚTݚTݚTݚTݚTݚاܭ%7>*@h?-F;MHTV[cboizs݀ztqo̩rݩuݪwݪyݪzݩ{ި{ާ{ާ{ާ{ާ{ާ{ާ{ާ{ާ,5=+E8LERRY__kfwߖpُ{Ӈ΀zvtƭvۮyۮ{ۮ|ۭ}ܬ~ݫ~ݩ~ݩ~ݩ~ݩ~ݩ~ݩ~ݩ~ݩ+4<)D5JBPNV[\gޥcr؞mѕwʎć|zzٲ}ٱٰگۮܬܫܫܫܫܫܫܫܫ+3;'B2I>NITUY`ٮ`nѤiɜs”}ֵ״سٱڰۮܭܭܭܭܭܭܭܭ*2:$A/G9MDQNܼVYӳ]m˪f~¢oyԷֶ״سٱگۮۮۮۮۮۮۮۮ)19!@+E4J=OERWι[kŰc}luйոֶشٲڰۮۮۮۮۮۮۮۮ (07>&C.H5H>OVȾXja|ir|̺Թն״زڰگگگگگگگگ '/6 KO5NLN`Ur\dmyyoÈfÞ_±cٱgٱkڰnگqۮsܬsܬsܬsܬsܬsܬsܬsܬ +  ,AM#S6VIU\UnZ}a}jrvhӆ`ԝYª\ݪ`ܫcܬfܫiݫkݪkݪkݪkݪkݪkݪkݪkݪ  1CL)Pk=l=l=l=l=l=l=l=lЪü ")|/#t5,l:3e@9_E>ZKBVQFRXHN^KJdMGkODsQA{S>U;p@8xB5C3E0F/G/G/G/G/G/G/G/G|rib\&U-P3K9G> CC#?H%=M&:R(7W)5]+2c,0j.-q/+y0)2'3'3'3'3'3'3'3'3ynd\ UN +H# D) @.<4895=2B/G-L*R(X&^$e"lu!{"{"{"{"{"{"{"{"vrm" +e1d@iJ'iT3g^>djH_uP[VV\S_PcNeLgKhJjHjGkFlFlIlMlPkUkVkVkVkVkVkVkVkvrm" +e1d@iJ'iT3g^>djH_uP[VV\S_PcNeLgKhJjHjGkFlFlIlMlPkUkVkVkVkVkVkVkVkwtn" f0h>mG'nQ3k\?hgIcrQ_~XZ^VbRePhOjMlLmJnIoHoJpMpQoUoYoYoYoYoYoYoYoYoxuo! h0l<qE'rO4pY?ldJhoSc{Z^`YeUhSkQmOoNpLrKrJsMsQsUsZr\s\t\t\t\t\t\t\tyvp! i/p:uC'vM4uW@paJllTgx\ab]gXkUnSpQrPtNuMvMvQwUvZv]w_x`x`x`x`x`x`x`xzwr k/u8zB'{K3zU@v^KpiUkt]fdaj\nXqVtTvRxPyOzQzUz[z^z`|b|c}c}c}c}c}c}c}{xs n-y7@&I2S?|\KveUqp^l|fflaq]uZxXzV|T}T~U~[~`~bdffffffff|yu s+~5>%G1P>YJ}bUwl_rwgmnhscx`{]~[ŹYZadfhijjjjjjj}{vw*4=#F0N%E0L0wC:oIAhOHbUM\\RVdVQmYKw]F_@b=d;f9g7z@2B/D-F,G+H*I*I*I*I*I*I*Iz qj c&]-W4R:N@IE"EK$AP&=V(9]*5d,1l.-v0)1&3#4"6"6"6"6"6"6"6"6vld ]VP$ +K+ G1C7?<;A7F4K1Q-W*^&f"oy "########rh_VO IC>!:' 6, +30 /5 ,9 )= %B"HNU\dlvzzzzzzzg b[' R5 S=XGYR$W^-Sj6MvLSBRGRGRGRGRGRGRGRh c\& S5 W;\E]P%\\.Wg7Rs>MDHHDLAN?Q>R=SVBVGUKVKVKVKVKVKVKVi d]& U4 [9aCbN%`Y/\e8Wq?R|FMJINFQDSBUAV@X>X>Y=ZZBYHYLYNZNZNZNZNZNZNZj e_% Y1 `7fBgL%dW/ac9\nAWzGRLNPJTHVFXEYD[B\B\A]A]B]G\M\P]R^R^R^R^R^R^R^k +g`$ ]/ e5k@lJ%jU0f`9bkB]vIXOSSOVMYK[J]H^G_F`F`E`G`N_QaTbVcVcVcVcVcVcVcl ha$ b, j4p>rH%pR0l\:hgCcsK^~QZVUZS]Q_OaNbLcLdKdKdNdSeVfYg[h[h[h[h[h[h[hmic# g* p1v;xF$wO/sY:ncCjoLezS`X\]Y`VcUeSfRhQhQiQhUiXk[l]m_m_m_m_m_m_m_mokd" l( u/{9~C#}L.zV9u`CpjLkvTgZc`_d\gZiYkXlWmWmYlZo^q`rarcrcrcrcrcrcrcrplf" q& +z- 7@!J,S7}\BwfLrqUm|\ibegbj`m^o]q]q^q^s`ubvdwfwgwgwgwgwgwgwgwqmh v$ + 4>G)O5X@~bKymTux]pdlihnfqdtbvawbxcyd{g|h|j|k{k{k{k{k{k{k{rnlz") +2;C&L1T=^H߁iS|t\w~erlnrkvizg|f~f~giklmnnnnnnnsop}!&/8@"H-P9ގ[DىfPӃp\}ygxotuqzn~lkkԄl넯mopqqqqqqqqtpt$- 5=E(ߚL3ٖX@яbP̉l]ƃuh~pzwv}sqpoψp舦qsttuuuuuuutqw"* +2:A"ۡJ,ӛU?̕_OŎi]rh{qy|yvutˌt匞vwwxxxxxxxxury'/ 6ީ=զG*ΠR=ƚ\Nf\ohxrz~{zyǏy⏖z펔{팒{{{{{{{{{vs|$+ 2گ9ѫE)ɥP<ŸZMc[lhtr}z~Ñ~ߒ됍~쎍~파~~~~~~~~wt &޲, ִ6ͯC'ũN:WLaZigrrzzݓ뒇쏇펇xu ۸%ҷ4ɳA%L8UJ^Ygfoqwz۔꓁됂쎂팃xv׽λ2Ÿ?#J6SH\Wddlpuy~~zwؕxz|}~~~~~~~yw ߯ +ٻ /=!G4QFYUbbjnrw{|vroՔpsuwxxxxxxxzy  ڦղӾ, :E1NCWR_`gkoux}{tnjgӒhknprrrrrrr|}  ޝժж) 7B.K?TN\\dglq{uytmgb_ҏ`dgikkkkkkk}آЮ˺ %4?)H:QJYWab|iltrtm|{f`[WщX\_adddddddݘҦʳĿ 0;$E5MCUP}][ufenomgzs`ƇyZŗ}UƮQсRTWZ\\\\\\\̬֞ĸ"2:B-J<~RHvZRoc[glcawiZԅnUՖrP֮uLvLvNyP{R|T|T|T|T|T|T|T|ݔϤŲ%2;B+~I7vOAoWJh`RbiX\t^VbQfMiJjHiHlJoKqMsMsMsMsMsMsMsԜǬ&19}@)vG3nN;gTBa\H[eNVoRQ{VLZG]C_A`@`D`EcFeFeFeFeFeFeFeܓ˥$.{7s>$mD,fK2`Q8[Y=UaAPjEKtIFLAO>Q:S7T7Uc*:l,6v.11-3*4'6%7#8#8#8#8#8#8#8|sk +d]X%R, M2 I9E?AE=K:Q6X3_/h+s&!"#$&'''''''{nf^W PKF#A*=/ 95 5: 2? /D +J(Q$Y!bkw{m`XPIC +=940$-))-%1"6; A H +O W ` j t        YRJ+E6 H: KDLPK\Gh&Cu,>0:477694:3<2=1=1>0>0?/?/?.>/>1=7=9>9>9>9>9>9>YSK+H3 L8 OBQNOZ Lf'Gr-C~2?6;9:;8=7>6?5@5A4A3A3A3A3A3@7@;A=B=B=B=B=B=BZTL*L1 Q7 TAULTX!Qd(Lp/H{4D8@;>==?;A:B9C9C8D7D7D7D7C8CF=G=GFAHEIFJFJFJFJFJFJ]WO)U, +\3 _<aG_R"]^*Xj1Tu8PuH rS*m]3ih;esBa~H]M[PYSWUVWUXTXTXVWU[U]W_Y_[`\`\`\`\`\`\`b ]_l"t) x1 |;|EyO(uY2pc;loChyJdOaS_W]Y\[Z]Z^Y_[_ZbZc\d^e`e`e`e`e`e`e`ec ^dq y&~- +7AK%}T0x_:tkCouKkQhWe[c_aa`d_e^f_f_h_ibjcjdieieieieieieid +`hu~$*3=F!O,݀\7{gAvqLrzTnZk`idggejdkcmcmdndnfngnhmimimimimimime +aly!'0 9B݌L'ևX4ЂcB}mMxvVt]qcnhlkjniqhrhshsiskrlrlqmpmpmpmpmpmpf bp}#+4ߖ=ؓI#ЍU3ʈ_AłiM~rWz{_weskqoormulwlwmwnwovoupspspspspspspsgcs'/ +ڜ9ҘF"˒R2č\AfMoWw`|gymvqturxqzq{q{rzsxswsususususususuhev!ޠ)֡6ΜD ƗO1Z@cMlWt`}h~n{syxw{v}u~v~v|wzwywwwvwvwvwvwvwvihyۦ#ҥ4ʡBœM/W?`LiWr`zhot}y|}zzˀz怊{~{|zzzyzxzxzxzxzxzxjj|֪Ω2 ƥ?K.U=^KgVo`whouz~Ȃ䂄~~~|}z}y}y}y}y}y}yjm ~  ۠٨ҭʬ/ =I,S<\IdUl_th}ou{~ƃ|}~~}{zzzzzzkp  +֢ۙԫαư- ;G*Q:ZHbTj^rgznuz~zwÄuvwy}z{zzzzzzzzzzzzlt לҦϯʴ*9E(N7WE_Rg\oewms|yw~rom߃nqr}t{uzuzuzuzuzuzmw۔ӟͩɲĹ'6B%L4TB]OdYlbuj{~quwp|kgeށfi~l}n{nznznznznznzo{֘ΣȭĶ $3?!I1R?ZKbVi_zrgt{nnthxc|`~^~^}b|d{fzhyhyhyhyhyhypݐѝɨñ0<F,O:WF_PzgYtoanxhgnbs\wYyVyVyZy\x_w`w`w`w`w`w`wr֕ˢĭ+ +8B&K4T?{\JtdRmlZgvaaf[kVoRqPqOrRsTsWsXsXsXsXsXsXsxߋЛƧ%3>G,{P7tXAm`IgiQasW[~\VɌaQɞdMʷfKgJhKjMkOlPlPlPlPlPlPl֒ɡ / :{D#tL-mU6g]>afE[pKV|PQيTLڜWI۵YGYEZD^F`HbIbIbIbIbIbIbΚ©"/ y8rAkI&eP._Y4Zb:Ul?QwCLGHJDLBM@M>O?R@TAUAUAUAUAUAUԓţ{!u, +o6i>cF]M%XU*S].Of2Kp6F|9B<>?;A8B6B7B:D:E:E:E:E:E:Eɝ|vpj(d1 _9ZAUHPOLW"H_%Dh(?r+;.704214.5,6,6.6.6.6.6.6.6ypj d^#Y+T3 +O: KAGGCN?V<^8g4r/!+#)$&&$'"(!(!(!(!(!(!(wkc]WQL$H+D2@8 <> 8D 5J 1Q.Z*c&n#{vi]VPJ +D@;!7(4.02,7(=$C !J S +\ g s + vh[PHB<62.*&!"%*.4:A +IR\gr IB#80;4 =9 +@D >O<[9g6s3 /#.%-',(+)****)+(+(+(+'+'+'*()))(+(+(+(+(+(+JC"90>2 A7 +DB CMAY>e;q7}"4%2'1)0*/+.,-,--,-,-,-+-+-+,-+---.-.-.-.-.-.KD"<.B/F5 +I? IJGWDcAo=z#9'7)6+5-4.3.2/20101000000/1/2/11222222222222ME!@+F,L3 +O= OHNTK`Gl!Cw&@)=,<.:0918282737363636363827466:7:7:7:7:7:7NG E(L(S0 V: VDUPR\Oh#Ks(G~,D/B1A3@4?5>6=7=7=7<7<7>6>8=:=L?K?K@J@K@L@KCJFJGLHNINININININIRLT`!g(k0 l9 lDiOeZ%af,^q2[{7X;V>U@SBSCRDQDQEQEQGQKPMPNRNTOTOTOTOTOTOTMZfn%r,s5 s?qJmU$ia,fl3cw9`>]A[EZGXIWKWMVMVNWOVQVSWTXTZTZTZTZTZTZTUR_ks!x(z1 z;yEuQ!r]*nh3jr;f{AdFaJ`M^P]R\T[U[V\V[X[Y\Y^Y_X_X_X_X_X_XVVdpx}$,6 @}MyY)ud4qn=mwDjJhOeRdVbXaZ`\`\`\`^`^a^b]c\c\c\c\c\c\WYht| '0݇;ՄIπU){`4wj>ssFp{MmRkViZg]f_eadbebebebfagah_h_h_h_h_h_X\lx!ߎ*؎8 ЊFɅR(Á]4}f?yoHvwOsTpYn]lakdifigigigjfkekdkbkbkbkbkbkbY_o{ۓ#Ғ5 +ˏCċO'Z4c?~lH{tPx|Vu[s`qdognimkmknjniogofododododododZ b s ~ ֗Η2 ǔ@L&W3`>iHqP}yWz]xbvftislrmrnrmsksishrfrfrfrfrfrf[ e u ۑٗқʛ0˜>J$T2^>fHnPvW~^|czgykwnvpvpvowmwkvivhvhvhvhvhvh\ hxی֔ԚΞƟ-<H#R0[=dGlPtW|^ch}l|o{q{r{q{ozlzkyiyiyiyiyiyi] kz؏җϝʢ£*:F!P/Y;bFiOqWy^cimp|rzsyrzpz~m{}l||j||j||j||j||j||j^ n}܉ԒΚʡť(7DN-W9_DgNoVw]ch}mypusstrrsptnulvjvjvjvjvjvj_ +q،ЖʝƤ %5AK+U7]BdLlTt[}b{gvlrpnrlskrlpnnolqkqkqkqkqkqkbuԐ̙ơ !2 ?I(R4Z?bIiQqYzz_uepjkngqerdqdognilkjkjkjkjkjkjfyۈϔǝ/ <F$O0W;_EgNyoUsw\nbigdk`m]o\n]m_lakdidididididik}֌˘â+8CL,T6~\@xdHslPmtVh~\ba]eYhViUiUiWiZh\g\g\g\g\g\gp߃ВƝ%4?I%~Q0xY9raAliIgrOa|U\ZW^SaPbOaNcOcRcTcTcTcTcTcTcw؉ʘ. :~DxM(qV1l^9ff?aoF[yKVPQTMVJXIWGYG[J\L]L]L]L]L]L]БÞ'|5 v?pIjR'eZ._c4Zl:Uv?P΃CLΒGHϦIEKDJBM@PBRDSDSDSDSDSDSوș{ ws.m: hDcM^V"Y_'Th,Ps1L5Hގ8Dߡ:B<@;>>:A:DH :O 7X3a0m,z(&#! rf\SNJEA"=):0662<.C+K'S #] +h v  reYNFA<840,%(*$/!5<CLV ao~ rdVJ@93.*& "!&+ +29BLWdq~:1(-001172B 0M -Z *f's%~#"!!  ;2'0.3/658@ 6K 3X 0d-p*{('&%%$$$###"""###"""""<4&3+7+<3>> =I :U 6a4m1y.-,++**))))((())(!("("("("("=5%8'<(B1E; DF BR>^ RIOUMaJmGwE"C$B&A'@(@)?)?)?)>)?)?*>->0>1>2=3=3=3=3=3B?HS Y'\0\: +ZE WPU]RhOs"M}%K(J*I+H,G-G-G.F-F-G-F1F4E6E8D8E9E9E9E9E9DDNZ`#d,d5b@ `K\WZcWn#Ux(S+R-P/O0N2M3M4L5L5M6M9LL>M?M?M?M?M?EIU`g j'k0j; +hFeRc_`j$]t*Z}.X2W5V7T9T;SS>R@RBQDQDRDSDSDSDSDSDGM[flp"r+r5p@ nNkZge&do-bx3_7];\>[@YBYDXEWFWFWGWIWIWIXIYIYIYIYIYIHQ`jqvx%y/x; +vIrVna(kj0hs6f|;d?bC`F_H^J]L\M\M\N\N\N]N]M^M^M^M^M^MIU d ouz}'7|FxRu](qf1no8lw>iCgGfJdMcObQaRaSaSaSaRbRbQcPcPcPcPcPKXh r +y ~؄!Є4ɂB~OzY)wc2tl9qt@o|EmIkMiQgSfVfWeXeXfWfVfUgTgSgSgSgSgSM\ku|ہڅ Ӊˉ1ć?LV(|`2yi:vqAtxGqLpPnSlWkYj[j\j[jZkYkWkVkUkUkUkUkUO_nx܀օԉ΍ǎ.=IT']1~f:{nAyuHv}MtQrUqYo\o^n_n^n]o[oYoXnWnWnWnWnWR cq{؃҉ύʐÒ+:GQ&[1c:kA}sH{zNyRwWu[t^s`raras_s]s[rYrXrXrXrXrXT +fs~ԆΌˑƔ(8 DO%X0a9iApHxN~S|Xz\x_wawc}vb}w`|w^}v\}v[}uZ}uZ}uZ}uZ}uZWhvفЉˏƔ%5 BM#V._8f@nGuM}SX\~}`{|bx{dv{dv{bv{_wz]xy\xy[xy[xy[xy[xy[ZkyՄ͌Ǔ˜ +"3 +@K"T-\6d?lFsM{RW{\w`tcqdpdpbp`q^r}\r}[r}[r}[r}[r}[]n|чɐÖ0=HQ*Z4a=iDqK~yQyVu[q_mbkdidibi`k^l\m\m\m\m\m\`rڀ΋Ŕ-;EO'W1_:fB}nHxvOsToYj]g`dbbbbab_d^f\f[f[f[f[f[dvԄɏ)7BL$T.\6|d>wkErsKm|QhVdZ`]]_[_Z^[]]\_[`Z`Z`Z`Z`Zi{ωŔ$3 +?IQ){Y1va9qh@lqFgzKbQ]UYXVZTZSZSZTYWYXXXXXXXXXXoفʏ/;E{N"uV+p^2jf9en?`wD\IWMSQOSMSMSLTLTNTPTPTPTPTPTvшĕ(6 +yAtJnR#iZ*dc0_k6Zt;V@QDMGJIGIGIEKDMFMGNGNGNGNGNʏ~ +zv/q; lEgNbV]_%Yh*Tq/P}4KŊ7Gś:DưD?D?D?D?D?D҈—}smk%g3b> ^HZQVZQcMm"Iy&Eԇ)BԘ,?ծ.=.<.9275576868686868Ȓ|ri`^[*W6S@PJ MSI]FgBr?<9 6"5"3"1%.(-)-)-)-)-){pf]V SP&M0I9EBBJ?S +<] 9h5t2/-*)('&&&&&{odZPKGDA(>1:87@4H0Q-[)f &s +# {nbVLC?; 741&.-*4&;#CKVbp   +      |n`TI>72.* '# &,3; DN[iz}n`RE:0)%   ")1:EQ`o}+!"-#.%/#5#@ LXe q |    + +           + +      , #-&+(,*3*>'I$V!c n +z + +               - %+*(,)112<0G,S )_ +&k #w " " !!   .)'/#3$8.:89D6P 2\ +/h -s +}*))(((''''&&''&'(((((0.#5;"A*B4B@?L u=~<;::999999988 8"7#7$7$7$7$7$39ALQ#S,S6QBNN LZIfGpFzEDCBBBBAAAA!@%@'?)?*?*?*?*?*?*5>ISX['[1Y<VG +TTR`PkOuM~LK!J"I$I%H&H&G'G'H)G,F.F/F0E0E0E0E0E07COY_b"b+a6_A]O [\YgWpUy!S%R'Q)P+O,O.N/N0N0N1M3M5L5L5L5L5L5L5L5<H U _ehi$h.g<fJ cWab^k!\t&[|*Y-X/W1V3U5T6S7S8S8S:S;R;R;R:R:R:R:R:@LZd +i lnn&o7mF kSh]eg$cp)ax._1^4\7[9Z;Y=Y>X?X?X@X@X@X?X>X>X>X>X>CQ_hmp rt v3tB qOnZlc%il+gt0e{5c8b;`>_@^B]D]E]E]E]D]D]C^B^B^B^B^BG Ubkquwz{/z? wKtVq`&oh-mp2jx7i;g?eBdDcGbHbIaJbIbHbGbFbEbEbEbEbEJ Yfnuz|~Ā,< +|HySw]&te-rm3pt9n|=lAjDiGhJgLfMfMfMfKfJgHfGfGfGfGfGL\iry~̀ƃ)9 F~P{Z&yb-vj4tq9ry>qBoFnJlLkOjPjPjOkNkLkJjIjIjIjIjIO_kv}˂Dއ&6CNW%}`-{h4yo:wv?u~CtHrKqNoQoRnSnRoP~oN~oL~nJ~nJ~nJ~nJ~nJQboỳDžÈ #4ALU$],e3}m:|t?z{DxHvLuP~tR|sTzrTyrSysQysOyrMyrLyrLyrLyrLyrLTer|ʄÉ 1>IS#[+c3j9r?~yD}H{M{zPxxSvwUtwUswTswRswPsvNtuMtuMtuMtuMtuMWguπƇ.<GP!Y*a1h8o>wC}HyLuPr}So}Um|Vl|Um|Sm{Qn{OoyMoyMoyMoyMoyMZky˃Ë+9 DNV(^/f6m<{uBw}GsKoOlRiUgUfUfSgQgOi~Mi~Mi~Mi~Mi~M^o}ȇ(6 BKT%[-~c3zj:vr?q{EmIiMeQbS`T_S_R`PaObMbMbMbMbMbt΂Č#2>HQ!}Y)y`0th6poRBNDLEKEJEIFIFKFKFKFKFKFvˆ |!x0t< +oFjNfVa_"]g'Yp,Tz1P5L8I:F;E;D=B>A?B@B@B@B@B@Ďuqn(j5f@ bI^RZ[VcRl!Nw%J)F,C.@/?/>1<4:59797979797ˈvlda_+\7XBUL +QUN^JhGsC@̎=̡!:ͺ"9"7$5'3)2+2+2+2+2+’wlbYQ +NM*K7IBGLDWAa >l ;y8ۉ5ܛ3ݴ20.,*****wkaWMEB@!>-<7:A7K5V2a/m-| * +( & $ # " !!!!!wj_TJA:752$0--6*?(H%R"^l|wj]QG=4/+(%"!(09BM Z hzxj\OD9/'"  (0:ESbtzk\NA5*!  +&0<JYk|&-,-2>J Wcoz&+(*1<HT` l +w + +   %'!$!%%/%9"EQ]it~    $"#& )".,/6,A(M%Y"epz +      "$'+27(827=3I0U-a+l)v(((' ' ' ' ' & & & && +& '''''''%!-2;@#A-@8>D:P8\6g4r 3{ +3 +2 2 2 2 1 1 1 1 1 1 111000000*2:CHI'H2F>DJAW@b >m >w = =<<;;;:::;::9988888/8 B KOQ"P,N7LDJQJ] Hh GrFzFEDDCCCBBBBA A"@#@#@#@#@#@#3=I Q VWW$V/U=TKSX RcPmOuN}MLKK J!J"I#I#I#H%H'H(G(G(G(G(G(G(8BOW[ ]]\&]8]G\S Z^XhWpUxT S#R%Q&P(P)O*O+N+N,N-N.N.M-M-M-M-M-< +GT\`aac e3eBcO aZ_c^l\t"[{%Y'X*W,V.U/U1T1T2T2T3T3S2S1S1S1S1S1?LY`ehgjl/l>jKhVf_dh bp$aw(_~+^.]1\3[5Z6Y7Y8Y8Y7Y7Y6Y5Y5Y5Y5Y5CP\eknnpr+r;pH nSl\jd!hl&ft*e{.c1b4a7`9_;^<]<]<^;^:^9^8^7^7^7^7FT`jpssuw'w7uD sOqYoa"mi'kp,jx0h3g7e:dc?b@b@b?b=bhAgBfCfCfAf?f>f{j={j={j={j=M]ku{/< +HQ}Z!{b'yi-wp2vw6t:s>~qA{pDyoFwoGunGunEunCunAun?un>un>un>un>Paox,: EOX _'}g,|n1zu6y}:|w>yvBvuEstGqsHosHosForDprBpr@pr?pr?pr?pr?Ter|)7CMU]%d+l0}s5z~{:v|>s{BpzEmyGkxHixHiwFiwDjwBjvAjv@jv@jv@jv@Wivƀ%4@ JS[#b)|i/xq4ux8q=mAjDg~Fe~Hc}Hc}Fc|Dd|Bd{Ad{@d{@d{@d{@[mz„ !1= GPX!{_'wg,sn1ov6k;g?dBaE^F\F\E]C]B^A^@^@^@^@ar-: D~MyUu\#qd)mk.it3e}7a<]?ZBWCVCUBVAV@V?W?W?W?W?gxĄ(5|@ xIsRoYka$gi)cq._z2[7W:S=Q>O?O>N>N>O=O=O=O=O=n~ }!z0u<qE mNhVe^af#]n'Yw,T0Q3M6J7H8H8G8G9G9G9G9G9G9vƅwsp)m6i@eJ aR]ZZbVkRu#N'J*G-D.B/B/@1?2?2>3>3>3>3~zmh eb._:\DYM +UUR^NgKqG|D@">#<#;#9&8(7*6*6*6*6*Ň|qf[VT!S/Q;NELOIXFb Cl?x<Ć9ė7Ŭ5420/////}rg\RHCB@,?8>D5/ .,'+3+?*K(X'e%t#!rfZOD;2*%#!(2<HUct   +sfYLA7.% + # +,6BO_qufXK?4)   $.:HYlvgXJ<0%  %1@Qex +* +) ')/;HUamw *&$ % . +9ER^ju~)"!+6B N [fq{%#("3>JWbmw        + +   !(,#,.):%E"R^is{ %*155)441@-M+Y*d)n(w(((''''''&''( ( +( ( ( ( ( ( $+ 3 :=="<-::8F6S5_4i4s4{3333333 3 2 2 3 22211111*0;B EEC%A2@?@M@Y?d?n?v >~ +> > = ==<<<<<;;::9999. 6BHK +KIG(I8JGJTJ_Ii Hq HyGFFEEDDCCCCBBBAAAA3<HNPPNO S3TCTOSZ +RdQlPtO{NMLLKJJJ J I!I"I"H"H!H!H!H!7BMSXYUX\.]>\K[V Y_XhWpVwU~TS R"Q#P%P&O&O&O'O'O&O&O%O%O%O%:GQZ_`^`c*d:cGaR `\^d]l\s[z Y"X%W'W(V*U+U,T,T,U+T*T*T)T)T)T)=KW`egffi%j6iCgO fXd`chao`v"_}%^(]*\,[.Z/Z0Y0Y0Y/Y.Y-Y,Y,Y,Y,@O\ejmll n"o3n@mK kUj^hegl!es$dz'c*b-a/`1_3^4^4^3^2^0^/^.^.^.^.CR`ioqqqst0s=rI pRn[mblj"jp%ix)h,f/e2d4c6c7~b7}b6|b4|b2|b1|b0|b0|b0|b0FWdmsvvuwx-x;vF uPsXq`pg"on&mu*l}-k0j3~h6|g8zg9xf9wf8vf6vf4vf2vf1vf1vf1vf1J[hqwzzy{|*|8{D yMxVv^te"sl&rs*qz.~o1{n4xm7vl9tk:rk:qj9qj7qj5qj4qj2qj2qj2qj2M_luz}~}&5A +~K|Tz[yc!xj%vq*|ux.yt1vr4sq7pp:no;lo;ko:kn8ln6ln5lm3lm3lm3lm3Qcpx~#2> IQY~a }|h%z{o)wzv-sx1pw4mv7ju:ht;ft"=$<%<&;';';';'~}sg_[Y%W2U=RGPPMXJa GkDv@=;876543333vk`TMJH&G2E=DGBQ?[=f:q7~ +5 2 0/ .,+****ymaVLB965"4.2:1E0P/\-i+w)ˇ'̛%̴##!  + + + +znbVKA7.& '2?LZj{ܐݩ|nbUJ?5+#  # +.;HXi}~pbTH<2( )5DTg}qbTF:.$"/=OczscTE8+  '6H^s*%#$-8ES_ku~'! *6BO\gr{#  +'3>KXdnw%/ :GS_js{ +6BNZ e o w  + + +   +')($%0!<HU`js{ !*0 10-(*4(B'N'Z'e(n(v)~)))))))))**** ) ) +) +) +) +#'289 +741+0:3H4U5`6i6r6y6666555544 4 4 333333(/:>?<89!=3@CAPA[AdAm@t@{ @ +? ? > > >====<<;;;;;,6@EHGADH.J>KKKVJ`Jh Ip Iv H}GGFFEEDDDDCCCCCC0<ENRRMNQ)S9TGSRS[ Rd QkPrOyNNMLLKKJJJJJIIII4AMVZZWVY$[5[CZNZW X`WgWnVuU|TSRRQ P!P!P!P!P OOOOO7ES\`a_] ` a1b?aJ`T _\^d\k[rZyZYX!W#V$V%U&U%U$U#U"T!T!T!T!;KYafgeceg.g<fGeQ dYcabhao`v_}^"]$\&[(Z)Z)Y)~Z'~Y&}Y%}Y#}Y#}Y#}Y#?P]fjljhjl*l9kDjN iWh^geflesc{!b$a&`(~_*|_+z^,y^+x^*x^(w^'w]%w]%w]%w]%CUbjnpomop'q6pBoL nTm\kcjjiqhx"g%}f'ze*xd,vc-tc.sb-rb,rb*rb(ra'ra&ra&ra&FYenrtsqst$u3u?sI rRqZpaohnn}lv"zk~%xj(ui+rh-pg.ng/mf/mf-mf+me)me(me'me'me'K]iqvxwuw y y0y<xG +wOuWt_}sf{rlxqt"up|&ro)pm+ml.kl/ik0gk0gj.gj,hi*hi)hi(hi(hi(Pamuz{{z{ }~-}:|D{M zU|y\yxcvwjsvr"ptz%ms(jr+gq.ep/cp0bo0ao.bn,bn+bm)bm)bm)bm)Ufqy~~~)7A~K zSw~Zt}aq|hn{p kzx$hy'ex*bw-_v/]u/\u/\t.\s,\s+]r)]r)]r)]r)Zju}%3|>yG +uPrWo^lfhmev"b%_~)\}+Y|-W{.U{.Uz,Vy+Vx*Vx)Vw)Vw)Vw)`pz} z/v:sDoL lTi\fcck_s\}"Y%U(R*P+O+O*O)O(O~(O~'O~'O~'gu~yur)o5l@iIfQ cX_`\hYqVzR!O$L&J&H&H&H&H&H%H%H%H%n{vpli"g/d:aD^L[T X\UeRmOwKHEC A A @!@!@!@!@!@!u}rgb^\'Z3X>UGSPPXMa JjGtDA><::988888}vlaVQ OM*L5J?HIFRD[Ae?p <| 9 64320/////zoeZOE?><);49?8I7S5^3j1w/,*)(' & +% % % % ~sh\QF;2, )(%'0&;%F#R"_!m}Đħvj]QF;1((4 A P +_ p҃ҙӵxj]QE:/% %1>N_qzl^PC8," + ,:J]q}n_PB5) + &5FZpp`PA4'/AVl%  )6CP\hqz"&3?MYdnw#/;IU`js{ *7CP\fow~   %1>JVajsz  *7 D P[en v } + + + + +  $$ !"/<IV`iqx     ),+' +" $#5&C(P*[+d,l,t,{,--,,,,,,,,,+++++ (0462) -1/4>6K7V8`8h8o8v8}887777666 6 +5 5 4 4 4 4 $/8@B@99=)@9BFBQB[BcBkBrAxA A @ +@ ? ? ? >>>>=====(5BILKFDG$I4KBKMKWK_JgJn It I{ HHGGFFEEEEDDDDD.<IQUTOM OR0S>SISSR[Rc +Qj PqPwO~NNMLLKKKKJJJJJ2CPX\\WTVY,Z:ZFYPYX X` WgVmVtU{TSRRQQPPPPO~O~O~O7IV]aa^[\^(`7`C_M^U ^] ]d\j[qZxYXXW~V}V{UzUyUyUxTxTxTxT<NZbffc`bd$e3e@dJcR cZ baah`o_v^~~]|\z[ x[!vZ"uZ"tZ!sYsYsYsXsXsXAS_fjjhegh!i0j=iGhP gX f_feel~ds{c{ybwat`!r_#p^#o^#n^"m] m]m]m]m]m]FWcjnmljk mn-n:nDmM lU k\}jc{ijyhqvgytfqe od"mc$kc%ib%hb#hb!ha hah`h`h`K\gnrqpnpqr*r7rBqK~pS {oZynavnhtmoqlwoklj!ii#gh$eg%cg%cf$cf"ce!cecdcdcdP`krutsrtuv'w4v?}vHzuQ wtXts_rrfoqmlpuio~gn dm#bm$_l%^k%]k$]j"^j!^i ^i^i^iUdovxxwwyz{#~{1{{<x{FuzN ryU ox]mwdjvkgvsdu|at^s"\r$Zq%Xq%Wp$Wo"Xo!Xn XnXnXnZisz{{{{} {y-v9sBpKmS j~Zg}ad|ia{q^{zXy Vx"Sw#Rw#Qv"Qu!Rt RsRsRsRs`nx~yur(o4l?jGgOdW a^^f[nXxUROM~ K~ K} K|K{KzKyKyKyft}vqmj"g/e:cC`L]S[[ XcUlRuOKIFEDDCDDDDmz{ohc +`^(\4Z>XGUOSWP_ Mh KrG}DB?>=<<<<<<uvk`YUSQ,O6M@LIJRG[EdBn?z = :865433333}yoeZPIEC!A-@7?A>K1$ .?Rg}|l]M>/" + (:Oe{ &3@MZenw~#0<IVaks{+8EQ]gow} &3?LXbksy  !-9FR]fnu{  %2?LWaiqw}  )8E Q [ d lsy  0?KV_ g n!u!{"""""""""###"""" (//+"!&*)9+F,Q.Z.c/j/q/w/~//////.....----'4;=92/3$547A9L:V:^:f:m:s:z::9998887776666"2>EHE>: =@/B<CHCRCZCbCiCoCvB}BA A +A @ @ ? ? ? > > > > > (:FMPMHDFH*J8KDKNKWK^KeJlJr Iy +I H HGGFFFEEDD D D /AMTWTPLNP&Q5RARKRSR[QbQi Po Pv O~NNMML~K|K{KzKzJyJyJyJ5GSZ\ZVSTV"X1X=XHXPXXW_Wf +Vl UtU{T~S|RzRxQwQuPtPtPsOsOsOsO;MX_`^\YZ \].^:^E]N]U\\ \c [j ~Zq|ZyzYxXvWtVrVpUoUnUnTnTnSnSnSAQ\cdb`^_ ab+c7cBbKbSaZ }aa {`hy_ow^vt]r]p\n[lZjZiYhYhYhXhXhXhXFV`ggfebdef'g5g?gI}fQ{fX xe_ vdetdmrctob}mak`h_f_e^c^c]c]c\c\c\c\KZdkjjighjk$l2~l={kFykNvjVtj] qic ohkmgrjf{heeecdac_c^b^a^a^`^`^`^`O_hnmmmkmno |p.yp:wpDtoLqoSonZ +mna jmihlpekycj`i^iZgXgXfYeYeYdYdYdTclqqpppr}s ztwu+tu7ruAotImtQjsX hs_ erfcqn`pw]pZoXnVmTmSlSkSjSiSiSiSiZhqttttu|wwxtyqz&nz3lz=izFgyNeyUbx\ +`xd ]wlZvuWuUuRtPsNsMrMqMpMoMnMnMn`mvxxxx}zv|q}l~j!g.e9cBaJ^R\~YY~a +W}j T}sQ|}N{K{IzGyFyFxFvFuFtFtFtfr{|||}ynid a_(]3[=YFWNUVR^Pf Mp JzGEB@???~?}?|?|?|mx~tha[WU!S-Q7P@NILQJZHcEmCw @ = ;98776666txodZRL IG$E/D9CBAK@T>^z>z>.@KQOMHEEG!I/J;KEKNKVK]KdKjJqJyI I +~H |G zG yF wF vF uE tE +tD tD tD 5FQUUSOLL NP+Q8QBRKQSQZQaPhPo}Ov {O~ yN wN uMsLrLpKoKnK nJ nI nI nI ;KVZYWUQRTU(V5W?WIWPWW}V^{VeyUl wUt +uT| sSqSoRmQkQjPiPiOhO hN hN hN APZ]]\ZVXYZ%[2\=~\F|\Nz\Ux[\v[ctZj rYq pYz nXkWiWgVfUdUcTcTcScS cR cR EU^``_^[]^_!~`/|a:yaCwaLu`Ss`Zq_ao_h m^o k]x h]f\d[bZ`Z_Y^Y^X^W^W^W^WJYbdccb`bc |dye+we7ueAreIpeQndXld_jcf hcm fbv caa`_`]_[^Y^Y]Y\Y[Y[Y[Y[O]fgfffdf{g +whti(rj4pj>njGkiNiiVgi]ehd cgk agt ^f~\eYdWdUcTcSbSaS`T_T_T_Tajjjjjizkvlrmon$mn0jo;hoDfnLdnSbnZ`ma^mi +[lr Yk|VjTjQiOhNhNgNfNeNdNdNdZfmmmmn{nuppqlris fs,dt7bt@`tH^tP\sWZs_XrgUrp +Sqz PpMpKoInHnGmGlHkHjHiHi_kqqqqrvsnuiwdx ay_y']y2[z<YzDXzLVyTSy\QxdOxmLww +Iw Gv EvCuAuAtArAq Ap Ap Ap eqttuu{vrxg{a}\~YV!T-S7Q@OHNPLXJaGjEuB~ @~ +=} ;} :| 9{ 9y 9x 9w 9w 9w lwxyyywzm}bZSO LJ&H0G9EBDKBTA]?g<(:29;8D6M5W4a2m0z.+*('''&&&{ukaWMD;3/-,'*1);(E&O%Z#f"t {oeZPF<3*!%/:EP]l| + + ti]SH>3)  #.9FSbrzmaVJ?5*  "-9FUfxsfYMB6+   +8FWi}˔˭yl_RD6)(6FYmscTD6( +$3F[qvfVF6' 1F\s-:GS^gov| (6COZclsy~  $1>JU_gnuz,9EPZbjpv| +%3?JT]ekrw|,8DNW_gmsx~#1=HRZbhntz +(6BLU] d j +p +v | !&#  /<GPX_flry#.30+%!)#6%B&K'T([(b)h)o)u)|***)))(((('''.8<:61+*-$/20=2G2P3W3^4e4k4r4y44433322~1}1|0|0|0&7ACB?;6479-:9;CHIHFB?= +?A)B5C@DIDQDXD_DeDl~Ds|C{zCyCwBuBsAr@p@o?n?n>n>n>5DNNNLHFEFH&I2J=JFKN~KU|K\{JbyJiwJqvIytIrHpHnG lG kF jF iEhDhDhChC;JRRRQNKKLN"O/~O:|PCzPKyPRwPYuP`sPgrOnpOwnNlN jM +hL +fL eK dK +cJ cIbIbHbH@OVVVUSPQRS|T,yU7wU@uUItVPrUWpU^nUelTljTuhS~fS +dR bQ aQ _P ^O ]O +]N ]M]M]MESYYYYWTV~W zXwY)tZ4rZ>qZFoZNmZUkZ\iZcgYjeYscX| aW +_V ]V [U ZU XT XS +XR XRXQXQJW\\]\[Y}[y\u]r^%o^1m_;l_Dj_Kh_Sf_Zd^ab^h`]q^]z \\ +Z[ XZ VZ TY SX SX SW +SV SUSUO[_```_~^x`sapbmb"jc.hc8gdAedIccPacW_c_]cf[boYaxWa +T` R_ P_ O^ N] N\ N[ +N[ NZ NZ T`bccccybsdnfjgggeh*ch5ah>_iF^hM\hUZh\XhdVgmSgvQf Oe +Le Jd Ic Hc Hb +H` H` H_ H_ Yeffgg|gshmihkdl am^m&\m0Zn:YnBWnJVnRTmZRmbPmjMltKlHk Fj +Dj +Ci +Bi +Ag Af BeBeBe_iijjkxknmfoap]rYsWs!Ts,Ss5Qt>PtFNtNMtVKs_IshFsrDr}Ar?q=pzo5-% +#! *3=GR_l{ sh^SI?5-$  ( +2=IVdsymaVLA7,# +(3?LZi{rfZNC8.# (3?N^oxk^RF:/$%1?PbvŋţƽqdWJ>1%  "/?Rf{ۓ۬xk]PA2$ +-?TjrcSB2# +@Vm *7DP[dkrx~  &3@LV_gnuz!.;GQ[cjpv{ )5ALU^elqw|"/;FPX`glrw} (4@JS[ahmsx~!-9DMU\cintz   %2=GPW^djpv} + +7 A KSZ`gmsz!++)%$1<FNV\c i o v!~!!!  ~~~,5530+&!$&,(8)A*J*R+Y+_,f,l,s,{,,,~,}+{+y+x*w*v)v)v(&5<<;951- .0(233=4F4N5U5\5b5i~6p}6x{5z5x5v5u4s4r3p3o2o1n1n0.=BBB@<9679$:0;:?@ A,}B7{C@yCHwDOvDVtD]sDdqDkpDsnC|lCjBiBgAeAd@c?b?b>b=b=;HKKKJHEDE }FzG)wH4uI=sIErJMpJToJ[mJblIijIqhIzfHdHcGaG_F^E]E\D\C\B\B@MNOOOMJJ{K xLuM&rN1pN:nNCmOJkOQjOXhO`fOgeNocNxaM_M]L[LYKXJWJWIWHWGWGEPRSSRQN{OvPsQpR#mS.kS8iS@hTHfTOeTVcT]aTe`Sm^Sw[RYRWQVPTPSORNRMRLRLRKJTUVVVU|RvTqUmVjWhX+fX5dX>cXFaYM`YT^Y[\XcZXkXWuVWTVRVPUOTMTMSMRMQMPMPNWXYYY}YwWqYlZh[e\c\(a]2_];]]C\]KZ]RY]YW]aU]iS\sQ\~O[M[KZIYHYGXGVGVGUGUSZ[\]]y]q\k^f_b` _a]a$[b.Yb7Wb@VbGTbOSbWQb_ObgMbqKa|IaG`E_C_B^A]A\A[AZAZX^_``}`ualaec`d\fXgVg Tg*Rh3Ph<OhDNhLLhTKh\IheGgoEgzBf@f>e=e;d;c;a;`;_;_^bbcdydqeff_iYjUkQm NmLm%Jm/In8Gn@FnHDnPCnYAnb?nl=mw;m9l7l5k4k4i3h3g4f4fdffg~guhmickZnSpLrHsEtCtAt)?t2>t;z:{ 7{6{"4{,3|51|=0|F.|O-|Y+|d*{p({~&{${"z!z!x!w!u!u!tnooovompcrZuOxG{?}7/*('#%-$6"?!IS_ky~}}sst|trtgv]xS{I~@8/'#,6@K W e +syyxwxlza|WLB8/& ",7BO\k|~~~}r~fZOE:0& +#-8ESbsxk_SG<1&"-9GWhz~qdWJ>3'  +9I[nwj\OB5))9K_tՋդֽ~pcUH:- '8Md{xj]O?/%9Pg + '4ALV_gnuz#0<GR[cjpv{+7BMV^flqw| +%1=GQY`gmrw|+7AKT[bhmrw} +%0;ENV\bhmsx~*5?HPW^cintz".9CKRY_ejpw~ '3=FMT[agmt {  + + $%# + ,7AIPW]cjqx}{zxxww+-.-*&  +'2 <!E"L"S#Y#`$f$m~$u}$~{$y$x$v#t#s"q"p"p"o!o!&35552/,&&("*.+8,A,H}-O|-V{-]y.cx.kv.ru.{s.r.p-n-m,k,j,i+h*h*h).9;<;:740/12*|34z4=x5Ew5Lu5St6Zr6aq6hp6pn6yl6k6i5g5f4d4c3b2a2a1a15>@AA?<:87 {9x:'v;1t;:ry>v?s@#pA.nB7lB?kBGiCNhCUgC\eCddClbCu`B^B\B[AY@W@V?V>V=U<U<@FHIIHF}DxCtDqEmF kG+iG4gH=eHDdHKcHSaIZ`Ia^Hj\Hs[H}YGWGUFSFREQDPCPBPAPADIKLML}KyHsIoJkJhKfL(dL2bM:`MB_MI]MP\NXZN_YMhWMqUM|SLQLOKNJLJKIKHKGKFKFIMNOPPyOtLnMjOfP cP`Q%^Q/\R7[R?YRGXRNWRUUR]TRfRRoPRzNQLPJPHOGOFNFLFKFKFJNPQSS|SuSoQiSdTaU]U[V"YV,WW5UW=TWDSWLQWSPW[NWdLWmJWxHVFVDUBTAT@S@Q@P@O@OQSUVVyVqVjVdX_Y[ZW[U[S\(Q\1O\9N\AL\IK\QI\YH\aF\kD\vB[@[>ZEbEDbMBbVAb_?bi=bt;a9a7`6`4_3^3\3[4Z4ZY[\]z]q^i^_`WbQdMeIfEgCgAh)@h1>h9=hA3)   '2>K[k}}}|p}dWK@5*  '2@Pasvi\OC7+  %2BTg{}obUG:.! + $2EYmτϜϷvh[M?2% !3H^tpbTG8* 4Kc{$0<HS\cjpv{,8CNW_flrw| '3>HRZagmrw|!-8CLT\bhmrw|'2=FOV]chmrx}!,7@IQW]chmsy &1:CKRX^cint{*4>FMTY_ekqx + +#.8AHOU[agmu}}|{zzz  ( 2 +; C K Q X^dkr{}{zxvu srqqq $'('$!"-7?GM}T|Zzayhxovxtsqonljiihh&+.//-*&! ")|#2z$;x$Cw%Ju%Qt&Ws&^q&ep&mn&um&k&i&g%f%d$c$b$a#a"a".245641/+~) +{*x+%u,/s-8q-?p.Gn.Mm.Tl.[j/bi/jg/se/}d/b.`._-]-\,[,Z+Z*Z*379:;:7}5z2x1u1r3!o3+m44k5<i5Dh5Kg6Qe6Xd6`b6ha6q_6{]6\5Z5X4V4U3T2T1T1T08;=??>}<y:u8r8o8l9i:(g;1e;9d;Abq=m>i> f?d@%b@/`A7^A>\AF[BMZBTXB\WBdUBmTBwRAPAN@L@K?I>I=I<I;I;?BEFF{FuEqBlBgCdD aE^E"\F,ZF4YF<WGCVGJTGRSGYQGbPGkNGvLFJFHEGEEDDCDBDAD@D@CFHIJxJqIlFgGbH^I[JYJWK)UK2SK9RLAPLHOLOMLWLL`JLiILtGKEKCJAJ?I>H>G>F>E?DFIKL}MuMmMhKbL]NYNVOSPQP&OP/MP7LQ>JQFIQMHQUFQ^DQgCQrAP~?P=O;O9N8M8L8K9J9IJLOPzPqPjPcP\QWSSTOT MUJU"IV+GV3EV;DVCCVJAVR@V[>Ve\7=\?;\G:\P8\Y6\b5\n3\z1[/[-Z,Z*Y+W+V,U,TRTV}WsWjWbXZYQ\K]E_A`=a ;b9b"7b+6b34b;3bC1bL0bU.b_,bk*bw(b&a$a#`!_"^#\#[$[VXZyZo[f[^[V]L`Fb@d9f4h1i/i-i%+i.*i6(i?'iH%iQ$i\"ig itihhgfeccb[]^u^k^b_Z`QbHeAg:i3l+n%p +#p!pq'q0q9qBqLqWpcpppp o o +n m k jj`a|bqbgb^cUeLgCj:m3p+r$twx yyy( y1 y; +yFyQx]xkxzxwvvutsrefwfmfcfYhOkFn=q3t+v#y{~ +!*4>JWdt~}||k~kskik^lSoIr?u5x,|#~  "+6AN]l}pypoocqWtLwAz7~-# +",8ESdvvuuiv\yP|D9.#!,9HYl|{o|bUH;/$   ,;M`tuhZM@2& ,>Rg}ʕʰnaSE7*-BWnhZL>0" +/F]u-8DNW_flrw| (4?IS[bhmsw| #.:DMU\chmsx})4>HPW]chmsx} +#.8BJQX^chmsx(2<DLRX^chmsz +",6>FMSY^ciou}&09AHNTZ_ekry~~~ +*3<CJPV[ahnv}|zxwvutts #-6>ELR}X|^{eylxtv}tsqonlkjjj "" + (~1|:zAxHwNuUt[rbqjorn|ljhgedbbbb %(*)(%" {x#v-t6r=pDoKmQlXj_iggpfydb`^][ZZZZ'+.00/~,{*x&w"t"q#o$)l%2k&:i&Ag'Hf'Ne'Uc']b(d`(m^(w]'['Y'W&U%T%S$S$S#S",03554y2u0r-q*n*k+h,&f-/d.7b.>a.E_/L^/S]/Z[/bY/kX/uV/T.R.P-O-M,M+L+L*M)15799{9u8q4m3k1g2 +e2b3"`4,^44\5;[5BY5IX5PV5XU5`S5iR5sP5~N5L4J4H3G2G2G1G0G/58;==w=p<l:i7e7b8_8\9Z:)X:1W:9U;@T;GR;NQ;VO;^M;gL;qJ;}H:F:D9C9A8A7A6A5A58<?@|As@m@h>e<`=\>Y>W?U?&S?.Q@6O@=N@DM@LK@SJ@\H@eF@pD@{B@A???=>;=;<;;<:<9<?BCyDpDiCdB`A[BWCTD QDOD#ME,KE4JE;HEBGEIEFQDFZBFc@En?Ez=E;D9D7C6B6A6@6?7>?CEFuGmGfG`FZFUGQHNI KIIJ GJ)EJ1DJ8BK@AKG?KO>KXL\nxonnaoUrIv=z1~' &3ARdxttguZxM|@4(%4EXmn{`~SE8+ &8LawŏƨgYK=/!';Qhހߙ߲`RC5' +)@Xp(4@JS[bhnsx} #0;ENV]cinsx~*5@IQX^dinsx~ %0:CKRY^dinsy*4=ELSY^chnsz #-7?GMSY^chnt|(19AHNSY^dipw "+4<CIOTZ_els|}|{zyxxx%.6>DJPV}[|b{hypxyvusrponnmm   )~1|9z@yFwLvRuXs_rfqnowmljhgfedcc  |y#v,t4s <q +Bp +In Om Ul \j di lg ue c a ` ^ +\ [ +[ +[ +[ "$%#|!ywwuro(m0k8j?hEgLeSdZba`j_s]~[YWUTSSSS %)*+{*v(s%p"om jh$f,d4b;aB_ I^ P\ W[ _Y gW qU |S R PNLKKKK%*-/0w/q.m+j(h&f$ d$a% _&)]'1['8Z'?X(FW(MU(TT(\R(eP(oN(zM(K'I'G&E%E%E$E#E#*.23z4r4l2h1e.c,`+]+[,Y-&W-.U.5S.<R.CP/JO/RM/ZL/cJ/mH/xF.D.B-@,?,>+>*?)?).257w8o7h7d5a2^1Z2X2U2S3#Q3+O43M4:L4AK4HI5PG5XF5aD5kB4w@4>4<3:29181809/9.269~:t;k;e:`9\6X6U7R8 +O8M9 K9(I90H:7F:?E:FC:NB:V@:_>:j<:u:989684837263534435:<{=q>h>a>\=W<S<O=L=I>G>E>&C?.B?5@?<??D=?K0>.=-<,;-:.9.89=?xAmAeA^AXAS@NAJBFBCCAD?D#=D+(>=@BtDjDbDZDTDNEHFCG@H0JF.JO-JY+Jd)Jp'J}%I#I!HGF E D!CAD}FqGgG^GWGQHJIBL=M9N5O2O0P.P#-P++P3*P;(PC&PL%PV#Pa!PmP{OONMLKJIEHyImJcK[KTKMKFM>P8Q3S-U)V 'V%W$W'"W/ W7W@WIWSW^WkVyVUU T SRQPJLuMiN_NWNPNIOBQ9T3V-X'Z ]^^^!^)^2^;^E^O^[ ^g ]u]\\[ZYXWN~PqQeR\RTQMRET=V5Y.['^ `ce f f +f$f,e5e?eJeVebepddcbba`_SyUlUaUYUQUHW?Y7\/_'b dgikm mmm&m/m9mDmPm]mkl{lkjjihhYsZgZ^YUYK[B]9`0c(fiknprs tuu v(v2v=vIvVvevuuutsrrq{^n^d^Z]P_Ea;e2h)knq tvxz{| }~!*5AO^o~~}||ucjc`bUdIf>j4m)qtx {} +!+7EUfyphfgZiNlBo6t+x { +!,;K]pmm`oSrFv9z,    .?Qe|fuYxK|>0# 0DYp_~QC5' !5Kb{ڔۭXJ;-$:Rk +$0<FOW^djoty~ +6AJRY_ejoty&1;DLSZ_diotz +5>FMTY_dintz%/8@GNTY^cinu| )2:BHNSY^cipw#,4<CINSY^dkrz~~~~&/6=DIOTZ`~f}n{vzxwutssrrr !*1~8|?{EyJxPwVu\tcrjqso}nlkjihggg  }{y$w,u4s;rApGoLnRlYk`ighpfzeca`_^]]] {xw v +tro'm/k6j=hCgIfOdVc]ae_o^y\ZXWUTTST ytpnnn + k +h "f +d 2c9a@`F^M]T[\ZdXnVxTRPNL K K K K #%{&s%m#j hffda_']/[6Z=XCWJUQSYRbPkNvLJHFDCCDD%(*v*n*h)d'b#`!_]ZX#V +T 3S :Q!@P!GN!OL!WK!_I!iG!tE!C!A ?=<<==$),}.r.j.d-_,])['X%V% T%Q& O'(N'0L'7K(>I(EG(LF(TD(]B(g@(s>(<':'8&6%5$6$6#7"(-0y2o2g2`1[0X.V+S+P,M,K,I-%G--F.4D.;C.BA.J@.R>.[<.f:.q8.~6-4-2,0+/*0*0)1(,03v5l5c5]5W4S3Q0M1J2G2E2C3#A3*@32>49=4@;4H:4P84Y64d44o23|03.2,2*1)0*/+.+-046s8h8`8Y8T7O7K5G6D7A8 ?8=8 ;8(:9/89679>59E39N29W09b.9n,9{*8'8%7$6"5#5$3%337|9p;e;];V;P;K;F;B<><;= 9=7>5>%3>,2>40?;/?C-?L+?U)?`'?l%>y#>!==<;:987;x=l>b>Z>S>M>G>@@;>u@iA_AVAOAIADBXHXTX`XmW|WVUTSSRHuJhK]LTKMKFK>M7O/Q(T!WY[ ^` ```'`/_9_C_O_[_i_x^]]\[ZZMpOdOZOQNJNAP9R1U)X![]` bdf +fgg!h)h3h=hIhVgdgsgfeddcbySkS`SWSNRET;V3Y*\"_be +gilmn oop#q,q7qBqOp^qmpoonmllsXfX\WSWIX>[5^+a"dhkmprtuvx yz{$|.|:|G|V|f{y{zyxwwm]b\Y[N]B`7c-g#jnquwy{} &1?N_rhb_aSbGe;i/m#qu y} &4CUh}efXhLk?o2t%y} '8J^t^nQqDv6{( *=RhWxI};- +.D[uԎԨPB3$ +5Mf ,7BKSZ`fkpu{'2<EMT[`fkpu{ !,6?HOU[`ejou|&09BIOUZ_djov~ + *3;CIOTY^djpw$-5=CINTY^dkr{ +'/7=CINTY_fmu}|zyxxxxx"*18>~D}I|OzTyZxavhuqs{rponmllll }{z%x,w3u:t?sEqKpPnVm]kejmhwgedcbaaaa {ywt sq o'n/l5k;iAhGfMeSdZbaaj_t]\ZYXWWVV ~wro nmkig#e*d1b7a=_C^I]P[WZ_XhVrU~SQPNNMMM xpkhfe e +ca^&]-[4Y:X@WGUNTUR ^P gN qL }JIGEDCCC} s!k ea_^]] ZX!V)T0S7Q>ODNLLTJ\IfGqD}B@><;;;<#x%n%f%`$\"Y WVU +SQO&M-K4J;HBGIEQCZAd?o={;9753445$'t)j)b)\(W'T%R"P NLJH #F *E!1C!8A!?@!G>"O<"X:"b8"m6!y4!2 0 .,-..#(}+q,g-^-X,S+O*M'K%H&F& D&B& @''>'.='5;(=9(D8(L6(V4(`2(k0(x.'+')&'%&$&$'#("'+z.n/d0[0U/O/K.H,E+B+@, +=,;,:-$8-,6-35-:3.B1.J0.T..^,.i)-v'-%,#,!+* )!("'*.w1k2`3X3Q2L2G1C1@0<1:1725232"23)030/38-3@+3H)3R'3\%3h#3u!32110/.--1t4g5]6U6N5H5C5?5:5663717 .8-8+8&)8.(95&9=$9F"9O 9Z9f9s887654331~5p7d8Z9R9K8E8@8;84;0<-<*= '>%>$>#">* ?2?:?C?M?X?d?q>> = < ; +: 9 85{8m:a;W<O;H;B;=;7<0?+@'B"CDEEE'E/E7E@EJEU Ea En D}DCBA@@?9v<i>]?T?L>E>?>:>3@,C'E"FIK LLL" L+ L3 +L<LFKQK]KjJyJIHHGFE>r@eAYBPBIABAM5O,R$UX[ ^acefg +ijkl&l0l<lIkWlfkxjihggfjR^RUQLPBQ8T.W%Z^a +dgilmoqr suvx(x4xAwPw`vrvutsqqeW[VRUGV;Y0]&`dhknqsvwy{|~ +8GXk~~a[XZL\@_4b(gkoswz|~  -=Nav^`QaDe7i+nsw| +!0BVkWhJkDJOUZ_els| (07>DIOTY_fmv~"*28>DINT~Z}a{hzqxzwutsrrrrr ~%},{3y9x?vDuJtOrUq\ocnllvkihgffeff}zwutr q'p.o4m:l@jEiKhQfXe_chaq`}^]\[[ZZZ~wspnl +jih"f)e0c6b;`A_G^M\T[\YdXnVzUSRQPPPP vo j gedb a_^%\,[2Y8X=VCUJTQRYPbOlMwKJIGGFFF zphc_] \\ZXV!U(S.R4P:OAMGLOJWH`GjEvCA@>==<=tkc]YVUT U +RPN $L +K +1I +8H >F EE MC VA _? j= v; 9 +7 +5 4333|p f ^ XSPNMMLIG F(D.B5A<?C=K<T:^7i5u31/-+++,y"l$b$Z$S#O"K IHFD CA?$=,;2:98A6I5R3\0g.t,*(%$#$%"u%i'_'V'P'K&G%D#B!@ > < : 8 "6!)5!03!72"?0"G."P,"Z*"e'"r%!#!! !&r)f*[*S*L*G)C(?'=&:%8&6&4&2'0'&.'--'4+(<)(E'(N%(X#(d!(p''&%$$#"%})n+b-X-P-I-D,?,;+8+5+2+/, -,+,)-#(-*&-2$-:#-B!.L.V-b-o-},,+*)('(y,k._0U0M0F0@/???!?) ?1 +?:?C?N?Y?f>u>=<;:99~4n7a8U9L9D8=88737-9';!=?AD +F FEE%E-E6E?EJEVEcEqDCBBA@?y8j:]<Q<H<A;;:5:/;)=#@BDG +IK +LLL L)L1L;LFLRL_LmK~JIHHGFs=e?X?N?E>?>8=1?*A$CEHK MOQRSTT$T,T6TATMTZTiSzRQPONNnB`CTCKBCAWr #.9BJQX^chmsy)3<DLRX]chmsz #-6>FLRW]bgmt{'08?FLQV[agnu~  )19?EKPU[agox#+29?EJOU[aiq{}|zyyyxw %-39~?}D{IzOxUw\uctlrvponlllklk}zyxw v'u.s4q9p?oDmJlPjWi^ggfqd}ca`____`xtqom lkj"j)h/f5e:c@bEaK_R^Z\cZlYxWVUTTTTTvojgecba`_$^*\0[6Y;XAVGUNSVR_PiOtMLKJIIIJx n +g a^\[Y +XWV U&S,Q2P8O>MDLKJSI\GfFqD~CA@@??@ +~qg`ZV T SRQ ONM"K)J/H4G;EADHBPAY?d=o;|:876666 xlbZTPMKK +KIGFD%B+A2@8>?<F;O9X7c5n3{10.----th^VOJGEDCC +A +? > "< ); /9 67 =6 E4 N2 X0 c- o+ |) ' % $ +###pdZRKFB?>=<;975&4-240;/C-L+V(b&n$|!{m `"V"N"G"B!> ;9864 20/#-*+1*9(A&J$T!`lzx!i#]%S%K%D%?$:#7"4!2 0 - , * (! &!'%!/#"6!"?"H"R"^"k!y!      t$f&Z'P(H(A';'7&3%0%-%*%'&%& #&!''%','4(<(F(P(\(i'w ' &%%$#"#q'c)W*M*E*>*9)4)0(,(()$+!+, +---"-)-1.:.D.N .Y -f-s-,+*)((}'m*`,T-J-B-;,6,1+-+)+$-/123333& 3. +373@3J3U3b3p210//.-y*j-\/Q0G0?/8/3./.+.&/ 1357 9 999#9+939<9F9R9_9m8}765433u.f1X2M3D3<26111,0'1"358: <> ????'?/@8@C@N?[?j>z>=<::9p3a5T6J6A5:544/3)4#68:= ?ACD EFG"G+G4G?GJGXFfFwEDCA@@k7\9P9F9>88727+8$9<>A +CFHJK LNOO&O0O:OFOSNbNsMLKIHGe<X=L=C<<;5:-;&=@BE HKMOQRT VWY!X*X5XAXNX^WoVUTSQP_ASAI@A?9>0?(B DGKNQSVXZ[]_ acd$c.c;cIbXbia}`^][[ZFOEFD>B4D*F!IMQTXZ]_acegik mop'o4oBnSncmwlkihfUJLICG9I.L#OSW[_behjmoqsuwy |~~+~9}J|\{pzxwutQNIM=N1R&VZ_dhknqtvy{~ !/@Rf}ORCT6X)]bglquy{~ +$5H]vHZ;^-ciouz (;Qi@e2j$pw}.D\vˑǯ8q)x + 6Oj*4>FMTZ_ejpv} $.8@GNTY^djpw(1:AHNSX^cipx "+3;AGMRW]ciq{$-4;@FKQV\ckt~|z &-4:@EJPV]~e|mzxywvtsssqo ~'|.z4x:w?uEtJrPpWo_mhlrj~igffeeed|wurq qpo"n)m/k4i:h?gEeKdRbYab_l]x\ZYYYYYYwpligedccc#a*_/^5\:[@ZFXMVUU^ShRtPONMMMMNwmfa^\ZY +YXWV%U+S0R6P<OBMILPJZIdGoF}DCCBBCC|of^YUSQPO NMM!K'J,H2G8F>DECMAV?`>l<y;:98899u i _ W Q +MKIHG FEDC#B)@/?5=;<B:J9S7^5i4v210///0 pdZRLGD B +AA@ >=< :&9,72684@3H1Q/\.g,t*)''&&' zl_UMGB><:: :9753#2)0//6->,F*P([&g$t" vh\QIC=974332 +1 / - , '*.(5'>%G"Q \hv    + sdXNF?:520.-,*('%$#,!3 ;EOZgu  +   +oaUK B <62.+)'%# " ")19BMXe r +|l^!R"H"?"9"3!/ + (%" !!!!&"."7"@ "J +"U"a"n!}! xh"[$O%E%=%6$0$,#("%"""#%&& '' '# '+ (3(<(F(Q(^'k'{&%$#"!t"e%W'L'B':'3'.&*%&%#$%')* , --- -(-0-9-C-N-Z-i,x,+*(''q%a(T*H*?*7*1),(('$' ()+- /12333$3,353?3K3W3f2v20/.-,l)]+P-E-<-4,/+**&*!*,-0 2467 89:!:):2:<:G:T9c9s876432h-Y/L0A09/2.--(,"-/13 57:<= +?@AA%A.A8ACAQA_@p?>=<:9b2T3H3>36200+0$1247 9<>ABDF HIJ J)J4J?JLI[IlHFEDBA]6O7D7;654.3'469; +>ACFHJLNP RTT$T/T:TGSWRhR{POMLJW;K;A:9827*8!;=@ DGJLOQSVXZ\ ^`_(_4^B^Q^b\v[YXVUR@G??=7<-=$?CFJNQTVY[^`bdgill!l-l;kJk\iphfecaMDDB<@2B'EIMQUY\_begjlnqsux{{${3zCxUwivusqpJHBF6H+KOTY^bfiloruwz|(8K_wHL;N/Q"V\agkptvy}.@UlAT4X&]c jpuz"5Jb|9_+dk qx'=VoNjĨ0k!ry/Hb}%0:BIPV\aflry *3<CJPU[`fls{#-5=CIOTZ_fmu~&.6=CHNSY_fnw (/6<AGLRX_gp{~~|wts!(/5;@F}K|RzYx`wiutsqpnmmkig}{zx xxx"v)t/r5q:o@mElLjSiZgcendzba`__^]\zsomkjiihh#f)e/c5b:`@_F]M\UZ^XhWtUTSRRRRQxngc`^]\ [[[Z$X*W/U5T;RAQHOPNYLcKoI}HGFFFFG{oe^XUSQQP PPOM%L+J0I6H=FCEKCTA_@k>y=<;;;<<sg]UPLIHGF FEED!B'A,?2>9<@;G9Q8[6g5t4221123|maWOIDA??>= <<;9#8)7/554<2D1M/X.d,q+*)(())vh +\ Q I C > +: 87665432 0%/+-2,9+A)K'U&a$n#~! r cWMD>952 0 +/// -,+)#()&0%7#?"I S_m|~ m_SIA:51-+)) ) ( &$# !' .6> H S _l{  zj\PE=61-)&$#"! &-6?IT ` m {    wgYLB:3.)&#  #+3 < E P\ixscUI?70+'#  +  +'/8ALYfvp`RF<4.($   !!!$!,!5">"I"V!d!t l\O!C"9"2!+!& " "$% &&'!')'2';'F'S'b'q&%#" h Y#K$@%7$/$)#$" !  !# %')* ,---&-.-8-C-P-_-o,+)(&%d$U&H'='4'-&'%####$& (*,.0 2 344"4+454@4M4\3l310.-,_(P*D*9*1)+(&&!&&') +.02468 +:<<<'<1<<@B DEE#E-E8EEDTDeCxA@><;T0G1<140-.', -/1 47:<?ADFHKM PPP'P3OAOPNaMtKJHFDO5C59422,0#246 9=@CEHKMPRUWZ\\"[.Z<ZJZ[XoWUSQPI9?87705'69< ?CGJMPSVX[]`be hji&i4hCgUfhdb`^\E>=<5:+; >B FJOSVY\_begjmoru xyx,w<uOuasxrpmlBA;?/A$DI NSX\`cgjnqsvy{~"2DYp~|@E4G(KP U[afknruy|&9Nd9M,RW]djpvz} +-BYr1X#^elsz 6MgʁɚƸ(el t|(A[u !,5>ELRX]ciow%/8?FLRW]bipx (18?EKPV\bir{!*18>DIOU[bkt}yv#*17=BHNT[cmx~|zyxtomk #*~0}6{<yAxGvMuUs]qfoqm~kjhggca`zutrqq qrp$n*m0k5i;hAfGeNcVa``j^w\[YYXWUU{qkgdcbb bbb`$_*]/[5Z;XAWHUPTZRePqOMLKKKJJ|of_ZWUTTT TTTR$P*N/M5K<JCHKGTE_DlBzA@????@sf\UOLJIHHH HHFD%C+A0@7>>=F;P:[8g7u6544456yk_ULGB@>>== +==<:!9&7,634:3B1K0V/c-q,+***+,seXNF@;864433 331/#.(-/+6*>)H'S&_$m#}""!!"#n_SIA:51.-,++ **)'&%%,#3";!EP\jzzi[ O D < 5 0 +, +)&%$$# #" ")09BMYgwue +W K@81,' $ !  +   &.6@KW e t +  q +aSG=5.($    +     $ +, +5 +? J V d s + n ^PD:2+%!    +#*3<GTaq + k[MA7/(#    '09EQ_ogWJ>4,%   %-7BO]mcTF;1)#    !"!+!4!?!L![ k ~_PC8.'!  #% ''''((1(<'I'X'i&|%#![L ?!4",!%   "$&)+ - .//$/./9.F.U.f-y+*(&%V"H$;%1$)##"  "#&(*-024 +777!7*757C6Q6b5v320.,Q&C(8(.''%"#"#$ &(*-/257:<? A@A&A1@>@M?^>r<;975L+?+4+,)&'!&&( *-/258;>@CFHKLL!L,K9KHJYHmGEB@?F/;/1.++%*+- /369<?BEHKMPSV YYX'W4WCVTUhS~QOLJA37200). /2 59=@DGJMQSVY\_be +hgf-e<dNca`x^\ZX=755.3$47;@DILPSWZ]`cfilorv wv&u5tFsZppolig;:48(:>BGMRVZ^beilorux{~ +>Sh~{y9>-@!DIPV\aeimquy} 2G^x2G%KQW^elquy}&:Rk*RX _gnu|-E^xȔ´ _gow 7Ql +  !"$%&()*+-./02346789;<=>@ABDEFGIJKMNOPRSTUWXY[\]^`abcefgijklnopqstuwxyz|}~ +  !"$%&()*+-./02346789;<=>@ABDEFGIJKMNOPRSTUWXY[\]^`abcefgijklnopqstuwxyz|}~ +  !"$%&()*+-./02346789;<=>@ABDEFGIJKMNOPRSTUWXY[\]^`abcefgijklnopqstuwxyz|}~ +  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~mft1! +  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ +  !""#$$%&&'())*+,--./01223456789:;<=>?@BCDEFHIJLMOPRSUWXZ\^`bdfhjmoqtvy|~ +  !""#$$%&&'())*+,--./01223456789:;<=>?@BCDEFHIJLMOPRSUWXZ\^`bdfhjmoqtvy|~# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭# 0:$A3HGO^Vv\afkoϹtɲy­𻹭#0:#A3HGN^TvZ^bfiov‚#09#@2GFL^RvWZ^chm׶s}"09"@1FEK]PvTX^bgʵkӪqܝzÇÇÇÇÇÇÇÇÇÇÇÇÇÇÇÇÇ"/8!?0EDJ\OuRX]aeǬiϡpוw߇ƃƃƃƃƃƃƃƃƃƃƃƃƃƃƃƃƃ"/8 >/DCI[NuRX\`dãhʙnҎvقʀ߂ʀ߂ʀ߂ʀ߂ʀ߂ʀ߂ʀ߂ʀ߂ʀ߂ʀ߂ʀ߂ʀ߂ʀ߂ʀ߂ʀ߂ʀ߂ʀ"/7=-CAJYNtQW\_cgœm̉t~~~~~~~~~~~~~~~~~!/6<+C?JZNtPV[_cglńs||||||||||||||||||||||||||||||||||!.5;)E=JZMsPVZ_cglryzyzyzyzyzyzyzyzyzyzyzyzyzyzyzyzyz -3:%E>JZMqOUZ_cgl|qvyvyvyvyvyvyvyvyvyvyvyvyvyvyvyvyvy+1>#E@IZLoNU[_dhlyqswswswswswswswswswswswswswswswswsw ( .>&DAGXJjNyU[`ei{mvrqwqwqwqwqwqwqwqwqwqwqwqwqwqwqwqwqw +"3>)C@ETIdMpTz\af|jxntspwpwpwpwpwpwpwpwpwpwpwpwpwpwpwpwpw5=*@>CNG[MfTo\ubz{g}wktoqrmwmwmwmwmwmwmwmwmwmwmwmwmwmwmwmwmw&59*<9@FFQL[Sb}\gybjugmrkopnqmrskuukuukuukuukuukuukuukuukuukuukuukuukuukuukuukuukuu ) 25'83=>DGKNzRTuZXq`[oe]mj_km`ipbgscgscgscgscgscgscgscgscgscgscgscgscgscgscgscgscgsc( -0"4,;5|BOSXi`howܩ~סҚΓʌ泀㳀㳀㳀㳀㳀㳀㳀㳀㳀㳀㳀㳀㳀㳀!.8?,F>NSVi^elsڰyԧϟʗƒ鴈쩇橇橇橇橇橇橇橇橇橇橇橇橇橇橇!.7?,F=MSUj\bhnعtѯzͩţ亜ꨒ蟎蟎蟎蟎蟎蟎蟎蟎蟎蟎蟎蟎蟎蟎!.7>+E=KRSiY_djoоxƴܺ䭥띞ꕖꕖꕖꕖꕖꕖꕖꕖꕖꕖꕖꕖꕖꕖ!.6>*D3HJLfO}SY^bgmăsz|qЇkΒkΒkΒkΒkΒkΒkΒkΒkΒkΒkΒkΒkΒkΒkΒ+17 A/HKLeN{RX]bglrwzpՄjԍjԍjԍjԍjԍjԍjԍjԍjԍjԍjԍjԍjԍjԍjԍ)/4B0HLKdMxQX^cglzqtxnہjڈjڈjڈjڈjڈjڈjڈjڈjڈjڈjڈjڈjڈjڈjڈ ' +8B2GLIbLsQX^dh}mwrrwl~hᄲhᄲhᄲhᄲhᄲhᄲhᄲhᄲhᄲhᄲhᄲhᄲhᄲhᄲhᄲ "&:A4EKG]KmQyY_e~jynuspxl}h邢h邢h邢h邢h邢h邢h邢h邢h邢h邢h邢h邢h邢h邢h邢, :@4BGEWJdPoYw`~~fykuorsnwk|hhhhhhhhhhhhhhhݻ/ 9!<2?BDOIZOcYj}`oxfrtkuqownrylv{iz}g~~g~~g~~g~~g~~g~~g~~g~~g~~g~~g~~g~~g~~g~~g~~پ05!8.<:BEHNOVzW[u__rebojdlmfjqghtifxje{ke{ke{ke{ke{ke{ke{ke{ke{ke{ke{ke{ke{ke{ke{k#-04)93?;{FCuMHpTLm\PjbRhgTfkUenVcqWbuX`wY`wY`wY`wY`wY`wY`wY`wY`wY`wY`wY`wY`wY`wY`wY"'+/"6*y=1qD7lK;gQ?cWAa]C_bD^fE]iF\mG[pHZrIZrIZrIZrIZrIZrIZrIZrIZrIZrIZrIZrIZrIZrIZrI -7?(G7PI[]eooy闌呕ዝ߇݃}tqqqqqqqqqqqqq -7?(G7PI[]eooy闌呕ዝ߇݃}tqqqqqqqqqqqqq -7?(G7PI[]eooy闌呕ዝ߇݃}tqqqqqqqqqqqqq -7?(G7PI[]eooy闌呕ዝ߇݃}tqqqqqqqqqqqqq -7?(G7PI[]eooy闌呕ዝ߇݃}tqqqqqqqqqqqqq -7?(G7PI[]eooy闌呕ዝ߇݃}tqqqqqqqqqqqqq -7?(G7PI[]eooy闌呕ዝ߇݃}tqqqqqqqqqqqqq -7?(G7PI[]eooy闌呕ዝ߇݃}tqqqqqqqqqqqqq -7?(G7PI[]eooy闌呕ዝ߇݃}tqqqqqqqqqqqqq -7?(G7PI[]eooy闌呕ዝ߇݃}tqqqqqqqqqqqqq -7>(F7OIY]cplv졀暉┒ގ܉لׁ|rsssssssssssss ,6>'E6MIW]`qir{䠅ߘڑ׌ԆтyֹwѷxϷxϷxϷxϷxϷxϷxϷxϷxϷxϷxϷxϷx,5=&D6LIU]^rfoxᦀ۝֕Ҏψ̇ں{۰|ծ}Ү}Ү}Ү}Ү}Ү}Ү}Ү}Ү}Ү}Ү}Ү}Ү},5<%C5KHS]\sckt߭|أљ˓ŏܱާצԦԦԦԦԦԦԦԦԦԦԦԦ,4<%C4JHR]ZsahoٱvЧȟ™ջڵިٞממממממממממממ,4;$B4IGP]Xs^ekҶsɬ{Ϲֲ۫ߟᘋۗؗؗؗؗؗؗؗؗؗؗؗؗ,4;#B3HFO\Us[ahͻqñxǺϲ֪ۢ␑ݐڐڐڐڐڐڐڐڐڐڐڐڐ+3:#A2GFM\SsY^fnvƴ~ϫ֢ۙ≗ފۊۊۊۊۊۊۊۊۊۊۊۊ+39"@1FEK[QsV\dlsƮ{Ϥ՛ۑ₞ރۃۃۃۃۃۃۃۃۃۃۃۃ+29!@0EDJZOrT[biqŨyΞՔڊ߁{|||||||||||||+28 ?/DBIYMqSY_fnġu͗~Ӎقyžsuuuuuuuuuuuuu+17=-C@IWMpRW]cjÚrˏ{х·z˖qʰlnnnnnnnnnnnnn*06<*B=JVMoPV[afmȅt{}q͋i̞eͿfffffffffffff ).4:'E:JVMnOU[`flsx{o҅gєaЫ_д_д_д_д_д_д_д_д_д_д_д_д_д ' ,2#E=HUKjN{T[ag~lxrrxlgމaݕ`ݚ`ݚ`ݚ`ݚ`ݚ`ݚ`ݚ`ݚ`ݚ`ݚ`ݚ`ݚ`ݚ +!$2>&D>GSIeMtT\bhzmusqxl~g慨b叫`䒫`䒫`䒫`䒫`䒫`䒫`䒫`䒫`䒫`䒫`䒫`䒫`䒫4>(B=EOH_LlTv]~c|iwossowk}gc틚b퍚b퍚b퍚b퍚b퍚b퍚b퍚b퍚b퍚b퍚b퍚b퍚b퍚 +$5<)?:BIGVLaTj]q|dvwjzsn}osmwj{gcbbbbbbbbbbbbbܶ)48(<5@BELKUS\z\budfqjinnklqmiuogype~rbsbtbtbtbtbtbtbtbtbtbtbtbtbtٹ* 04$8/=9DB{JIuQNqZRmaUkgXhlZfo[er\cv^az__`_a_a_a_a_a_a_a_a_a_a_a_a_a' +/4(;0xA7qH-hE1cK4^Q6\W8Z\9X`;Wc;VgRr?Rs?Rs?Rs?Rs?Rs?Rs?Rs?Rs?Rs?Rs?Rs?Rs?Rs?+6>$F1N@ZQebpq{򐐓놣邫~|yȮw԰pزlسlسlسlسlسlسlسlسlسlسlسlس+6>$F1N@ZQebpq{򐐓놣邫~|yȮw԰pزlسlسlسlسlسlسlسlسlسlسlسlس+6>$F1N@ZQebpq{򐐓놣邫~|yȮw԰pزlسlسlسlسlسlسlسlسlسlسlسlس+6>$F1N@ZQebpq{򐐓놣邫~|yȮw԰pزlسlسlسlسlسlسlسlسlسlسlسlس+6>$F1N@ZQebpq{򐐓놣邫~|yȮw԰pزlسlسlسlسlسlسlسlسlسlسlسlس+6>$F1N@ZQebpq{򐐓놣邫~|yȮw԰pزlسlسlسlسlسlسlسlسlسlسlسlس+6>$F1N@ZQebpq{򐐓놣邫~|yȮw԰pزlسlسlسlسlسlسlسlسlسlسlسlس+6>$F1N@ZQebpq{򐐓놣邫~|yȮw԰pزlسlسlسlسlسlسlسlسlسlسlسlس+5=#E0M@XRccmsx뎖舠愩䀲}zȵvӸnԺmոmոmոmոmոmոmոmոmոmոmոmո*4<"C/K@VR`djvt~예蒒䌜ᆥ߂~{sprҼrҼrҼrҼrҼrҼrҼrҼrҼrҼrҼrҼ*3;!B/J?TR]egwpz蝄䗎݉ڃyr̺tŵvvvvvvvvvvvv*3: A.I?RR[edymvݙؐ҈΄ʁǀκwϱxȭzízízízízízízízízízízíz*29 A-H>PQYfazjrܥzԚΓɍĉνб}ѩ|˦~Ŧ~Ŧ~Ŧ~Ŧ~Ŧ~Ŧ~Ŧ~Ŧ~Ŧ~Ŧ~Ŧ~*29@,G=NQWf_zg޳n֨vΟǘǼ̷гҩӢ͟ǟǟǟǟǟǟǟǟǟǟǟ)18?+F*D;KOQeX{_ѿgȵowȧΡҜՔ׎Ҏ̎̎̎̎̎̎̎̎̎̎̎)06=)D:INOdV{]eúmt|ȡΚҔՎׇӈ͈͈͈͈͈͈͈͈͈͈͈ )/6<(C8HMMcTz[cjrzȚΓҍՆ׀Ԃ΂΂΂΂΂΂΂΂΂΂΂ ).5<&A7FKKbRyYahpwǓ͋хy{{{{{{{{{{{{ (.4:$@5EIK_QxW^elt|Ƌ̄}wqtttttttttttt ' -39">2FEK^PvU[bipyĄă|ďuŢoillllllllllll & +17>-GEK^NuSX^emu}ҀuҍmҞfҶadddddddddddd % +) /4A+GEK^MsRW]cj~quzm؄e֐_բ[]]]]]]]]]]]] +#& + 7A-GFJ\LpPW^djzqrxlށf݊`ܘ[۬XۿXۿXۿXۿXۿXۿXۿXۿXۿXۿXۿXۿ "$9A/FFHZKkOzW^e}kwrqxkf䇫a㑮\⟰Y⬱Y⬱Y⬱Y⬱Y⬱Y⬱Y⬱Y⬱Y⬱Y⬱Y⬱Y⬱*:@1DDGVJeOqX|_fymtroxk}g섛b댞^ꗠ[ꠡ[ꠡ[ꠡ[ꠡ[ꠡ[ꠡ[ꠡ[ꠡ[ꠡ[ꠡ[ꠡ[ꠡ. +9>0AAEPI]NgXp`v{g{umqrmwj|gc_]]]]]]]]]]]] 07;.>Ye?Xi@VmAUpBTtBSyCR|DR|DR|DR|DR|DR|DR|DR|DR|DR|DR|DR|D #y*q1j8#d>'_E*ZJ,WP.UU/SY0Q]1P`2Oc3Ng3Lj4Ko5Jr5Jr5Jr5Jr5Jr5Jr5Jr5Jr5Jr5Jr5Jr5Jr5*5< E+M9YGeVqc|oy|yĖwΘuٚqޜlggggggggggg*5< E+M9YGeVqc|oy|yĖwΘuٚqޜlggggggggggg*5< E+M9YGeVqc|oy|yĖwΘuٚqޜlggggggggggg*5< E+M9YGeVqc|oy|yĖwΘuٚqޜlggggggggggg*5< E+M9YGeVqc|oy|yĖwΘuٚqޜlggggggggggg*5< E+M9YGeVqc|oy|yĖwΘuٚqޜlggggggggggg*4< D+M8XGdVpd{pz􃧎򀱒|yÙw͛vڝqݟkggggggggggg)3;C*K8VHaXlgwt򎌉񊘑큭}zxͦuبo۪hܬkߧkߧkߧkߧkߧkߧkߧkߧkߧkߧkߧ)29A)I7SH^Xiisw~품댓針炨~zxͱsճlֵlٱoܫoܫoܫoܫoܫoܫoܫoܫoܫoܫoܫ)18@(H7QG[Yfjpzz薄后≘߂}xuǻrҽmҼpֵrگrگrگrگrگrگrگrگrگrگrگ(17?'G6OGYYckl|v⚀ޑىԁ}zxwqtԸvزvزvزvزvزvزvزvزvزvزvز (07>&F5MFWY`lj~sݜ{֒ь̆Ȃ}|´u®wӻyֵyֵyֵyֵyֵyֵyֵyֵyֵyֵyֵ (/6=%D4LFUY^mgީo֟wЗʐŋöĭzŧ{Ѿ}շ}շ}շ}շ}շ}շ}շ}շ}շ}շ}շ (/5<$C3JESY[md٭kѣtʛ}Ĕ°ŭƥǠԹԹԹԹԹԹԹԹԹԹԹ (.5<#C2IDQXYmݻaԲįrşzéƥȞȚ˜ӻӻӻӻӻӻӻӻӻӻӻ '-4;"B1HCOWWmڿ_жgȬowġǞɗɓēҼҼҼҼҼҼҼҼҼҼҼ ' -3:!A0GBLVUl]̺eðmu}ĚǖʑʍōѾѾѾѾѾѾѾѾѾѾѾ ' ,29 @.E@KUSk[ȾdkszœȏʊˆƇѿѿѿѿѿѿѿѿѿѿѿ & +28>,D>ISQjZaipxČȇʂǁ % *07=*B!VD#RI$PN&MR'KV(JZ)H])G`*Ed+Dh+Bm,Aq-Aq-Aq-Aq-Aq-Aq-Aq-Aq-Aq-Aq-Aq-)4;D&M1Y>eKqV}`ho}tzxx|vtǁsуq݅plhdddddddddd)4;D&M1Y>eKqV}`ho}tzxx|vtǁsуq݅plhdddddddddd)4;D&M1Y>eKqV}`ho}tzxx|vtǁsуq݅plhdddddddddd)4;D&M1Y>eKqV}`ho}tzxx|vtǁsуq݅plhdddddddddd)4;D&M1Y>eKqV}`ho}tzxx|vtǁsуq݅plhdddddddddd)3;C&L1W>dKoW{bkrx|}ywuņsЉr܊okfdddddddddd(29A%J1T?`MlZwfpy~{xus͓qەniegggggggggg(08@$H0Q?]Mh\ti~u~섓뀝|xurɝpؠlߢfikkkkkkkkkk (07>#G/O>[Nf]pl{y錅燏䁙|wspƧnժiܫiިl⡾n圾n圾n圾n圾n圾n圾n圾n圾n圾n ' /6="E/M>XNc_mnw|䐁ቋނ{vsqpϯnگmܬoॷq㠷q㠷q㠷q㠷q㠷q㠷q㠷q㠷q㠷q ' .5'D7JJT^Թ]r˯fçnv~ȼҼֵۮۮۮۮۮۮۮۮۮۮ $ ) /6<%C5IHR]м[qdzdls{ŽѾֶگگگگگگگگگگ # +( .5;#A3HEQ\Zpøbjqy¾Ѿշٰٰٰٰٰٰٰٰٰٰ # +' -3:!?0FCO[Xo`gov~ѿ~Ըٱٱٱٱٱٱٱٱٱٱ " & ++ 28=,DAMYVn^els{{wѾwԹyزyزyزyزyزyزyزyزyزyز +!% * /5:'C@KXSl[~biqx|wsoҽoԹqزqزqزqزqزqزqزqزqزqز +#' , 2=#B=IVQjX|_fmu}{uokgӻgոiٲiٲiٲiٲiٲiٲiٲiٲiٲiٲ  $( 2>#D;HSOhUy\cjr{ztÅmÑhácĶ`շ_ֵaگaگaگaگaگaگaگaگaگaگ 4?%D;HPMdSuY`g|otxmтgҐaӠ]ԷYٲWڰZܫZܫZܫZܫZܫZܫZܫZܫZܫZܫ$6?'C;GOJ`QoW|^~eulnuga㌥\䜧W審T˩QۨSSSSSSSSSS (7>(B;EKIZPgWr_{zfsnmwhc^ZURқOݛOݛOݛOݛOݛOݛOݛOݛOݛOݛ ڹ, 7<)@8DFHSN^Wg{_nvgtpoxkv|gc_\XTRҋRҋRҋRҋRҋRҋRҋRҋRҋRҋܮҿ- 49'=4B@HJNSzVZu^_pfdlnhhtke|nbp_r\tYvUwSxSxSxSxSxSxSxSxSxSxӵ+16#;.@7~F@wMFrTLn\PjdTfkWdqYaw[^~]\_ZaWbUdReReReReReReReReReRe֬ʾ ',28'{>/tD5nK:iQ>eXAb`D_fF]mH[rJYxLW~MUNSPQQOROROROROROROROROROR˶" (.x4 p;&jA*eH.`N1\S4ZZ6W_8Ue9Sj:Qp;Pu=Nz>M?K@IAIAIAIAIAIAIAIAIAIA  +}"t)m0f7`=!\C$WI&TN(QS)OX+M\,Ka-Je.Hj.Fn/Et0Cz1A2A2A2A2A2A2A2A2A2A2 {q i#a*[1V7R=NBKGHKFO DS!BW!@Z"?^#=b#;f$9l%8q%8q%8q%8q%8q%8q%8q%8q%8q%8q%y(z3;D!M+X6f@sJ|RxXv^sbqeohnklmknjpiqhrgsdtatatatatatatatataty(z3;D!M+X6f@sJ|RxXv^sbqeohnklmknjpiqhrgsdtatatatatatatatataty(z3;D!M+X6f@sJ|RxXv^sbqeohnklmknjpiqhrgsdtatatatatatatatataty(z3;D!M+X6f@sJ|RxXv^sbqeohnklmknjpiqhrgsdtatatatatatatatatatz(}2:B!L+V6dApK~|T{\xaufsjqmopmrltkvjwixfybzayayayayayayayayay{( 08A J+S6`BmNxX`|gxmursupyn{m~kjiecd~d~d~d~d~d~d~d~d~|' /7?H*Q6]CiPu[em{swyt}qomLJkԉjgcfggggggggg }' .5=F)O6ZDfQr^|h삇r~yyurolĐjғidfhiiiiiiiii ~' -4<D(M6XDcRn`yl熃w䀌zvqmjiΜiߜgik쏾lllllllll & ,3:B'K5UD`Skbup|݂{vrpnmɠmڠj⠿l暹n锷o쏷o쏷o쏷o쏷o쏷o쏷o쏷o쏷o % +29A&I4RC]TgdqsیzՅ{wtrqãqԤoशp㞲r痯sꓯsꓯsꓯsꓯsꓯsꓯsꓯsꓯs $ * 08?$G2OCZTdeژmvԐvΊʄ|yvuuϧsߧsᢪu曨v薨v薨v薨v薨v薨v薨v薨v薨v $ ) /6>#E1MAWSܥafԝjvΕsȎ|É}{yyʩxݪwߥy䞢y癢y癢y癢y癢y癢y癢y癢y癢y # +( .5۵SQӮ]e˥fuĞnví֮ݫᢖ䝖䝖䝖䝖䝖䝖䝖䝖 ! & +, 29@+G<غQPϱ[dǩdtlt|ӯۭऐ㟐㟐㟐㟐㟐㟐㟐㟐 !% + 17>(F9ԽPO˵YcíbsjryѰگߦ⠊⠊⠊⠊⠊⠊⠊⠊  $) /6<%D6NNȹXb`rhowαڰߧ⢅⢅⢅⢅⢅⢅⢅⢅ +#( -4:!B5MLĽV`^qfmt|̲|ٱ~ި~~~~~~~~~ +!&+ 16@3KKT_\pc~kry~zwɱtٱvީxxxxxxxxx +#(-3>1IIR]Zna|hov~|wspȰlٰoީqqqqqqqqq #'22D<}JEwQLqYRmaWii[eq^axa^d[fXhUjRkOmNmNmNmNmNmNmNmNmNmܢγ#*06"<+{B3tI:nO?iVDf^GbfJ_mM]tOZ{QWSUURWPXMYLZLZLZLZLZLZLZLZLZѫż&,3x9$q@*kF/fL3aR6]Y9Z`;Xg=Vn?TtARzBPCNELFIGHHHHHHHHHHHHHHHHHHǵ! |(t/m5go(MpDmJkNiQgTfVdWcYbZa[a\`]`^_^^_]_]_]_]_]_]_]_]_xsm* p2v:yDzN%yX.wf6tt>pDmJkNiQgTfVdWcYbZa[a\`]`^_^^_]_]_]_]_]_]_]_]_xsm* p2v:yDzN%yX.wf6tt>pDmJkNiQgTfVdWcYbZa[a\`]`^_^^_]_]_]_]_]_]_]_]_xtn) s1y9|B}L%|W.zd7wr@s~GpLmQkUiXgZf\e^d_c`bbabacad^d^c^c^c^c^c^c^c^cyuo) v0}8@J%T/a9|nBxzJtQqVnZl^jahcgeegdicjckbl`m`j`i`i`i`i`i`i`i`izvp( z.6?H%R/^:kD|wMxUt[q`ndlhjkhmgoeqdsctbuatbocmcmcmcmcmcmcmcm{ wr' }-5=F$O/[:hEtP|~Xx`tfpknoksiugxezd|c}b}cyetfrfrfrfrfrfrfrfr| xu& ,3;D#M.X;dGpR{\{ewlrrowl{igēcۆadf~hyhwhwhwhwhwhwhwhw} yx% + 29B"J.T;aHlUw`jystzpligfȌf،ehik}k{k{k{k{k{k{k{k{} z{$ ) 07@!H-Q:]IhWsdނ|p|zvromkjjёik펼lnnnnnnnnn~ {~" +( .6>F+N9ZIeX܍ngֆxsр|{wtrpon̕nޕnꓴp팰qqqqqqqqq {! ' -4<C)K8WHܙaYՒkhϋttʅ}}ƀ|yvtsrǘrڙr藬s됩ttttttttt | & ++ 2:A'I6ޥTGמ_YЗhhɐqtĊz}~{xwvÛv՜u囤w锢xxxxxxxxx } $ * 18?%G4ڪREҢ\X˛fgĔotw~}{zzўy䞝z藛{쏚{{{{{{{{ }#) +/6="߳E1֮PDΧZWƟdflst~|~~͠~⠖~晕~둔~쎔~쎔~쎔~쎔~쎔~쎔~쎔~ ~"' - 4;ܸD-ҲOCʪYV£afjsr}zʡࡏ囏꓏됏됏됏됏됏됏됏 !%+ 28ټB,ϵMBƮWU`ehro}wȣޣ䝉镉뒉뒉뒉뒉뒉뒉뒉 +#) /6@*̹K@òUS^dfqm|u|ţܤ㞃薃꓃꓃꓃꓃꓃꓃꓃ +!&, 3?)ȽJ?SR\bdpk{rz~¤|ڤ|}}}}}}}}} +"(/='H=QPZaaoizpw~zwuؤtvwwwwwwww !-;%F;ONW__mfxmu||wrom֣lopppppppp + 9"C8MLU\\jcvjry{uokgeաdghhhhhhhh߼ +( 6A5JHRYYgarh|ozwtnhc`^֝\_```````` ۱,5>1GDOUVb]ndwzlstm}gÇbÔ]åYĺWؘUXXXXXXXXX Զ/ 9>,E?LOS\Zh{aqtixmq~g{a҆\ғWӤTԻQڏOQRRRRRRRR֬λ!08=+B:IHQT|X^t_gngngosbxx\|W㏀S䟂O崄MτKLMMMMMMMMۢϲ%/6<)A5G@|OJuWRo_Xjg^eobaxf\jXmToQqNrLsJsIsIsIsIsIsIsIsIsҩȹ%-4:%@/zF7tM?nTEi]JeeNamQ^tUZ}WWZT\Q^N`LaIbHbHbHbHbHbHbHbHbסɲ"*17 x>'qD.kK3fQ8bY;^a>[hAXpDVwFSHPJNLKMINGOFPFPFPFPFPFPFPFP̫& |-t4n;hA$bH(^N+ZT.W[0Ta3Qh4Oo6Mw8J9H;FA>A>A>A>A>A>A>A>µx! p(i0c7^=YCUI!RN#OT$LZ&J_'Ge(El*Cs+@z,>-<.:/9/9/9/9/9/9/9/9/~ tle# ^*X1S7O=KBHGELCQ@U>Z<`9f7l 5r!3y"1"0#0#0#0#0#0#0#0#{qh _XR# +M) H/D5A9>>;B8F6J3N1S/X-]*b(h&o%r%r%r%r%r%r%r%rlg_- e1k:mDmN kY'ig-fu3c8a<_?]A\C[DZFYGYHXHWIWIVJVJVJUJUJUJUJUJUJUJUJlg_- e1k:mDmN kY'ig-fu3c8a<_?]A\C[DZFYGYHXHWIWIVJVJVJUJUJUJUJUJUJUJUJmg`, g1n9pCpM nX'le.is4f:d>aA`D^F]H\I[JZKZLYMXMXNXNXNWNWNWNWNWNWNWNWNnhb+ k/r8tAuK sU(qb/np6k|=hAeEcIaK`M_O^P]R\S[T[UZUZVYVZSZSZSZSZSZSZSZSnie) o.u6x?yI xS(v_0rl8oy?lEiJfMdQcSaU`W_X^Z][\\\][]\[]X]W]W]W]W]W]W]Wojh' s, y4|=}F|P({\1wi:suBpIlNiSgVeYc\b^``_b^c]d]e]d_``\`\`\`\`\`\`\`\pkl% v+ }2;DN(X2|fjJ}tUx~^sfnmjshvfydzc|c}b}c{gviqjkjkjkjkjkjkjkjksov! & +- 4=E%N1Z>fLނpX{ydvlrrovlzj}ihgʂgۂgꁾj{lvmpmpmpmpmpmpmpmpt oy% + 2:B#K0W>ݍbMׇl[ҁue|~mxttyq}omlkņkՆj憵nozptptptptptptptptu p|#) +08@ H-ޙT=ؓ_MьiZˆrfƁzn}uy{vtrpooЊn㊭rr~swswswswswswswswu q"' . 5=F+ڞR;җ\LˑfZŋofwov~|{xvtss̍ruvv{vzvzvzvzvzvzvzv r %, 3:ݨD'գO9͜ZKƕcYleto|w}|zxwwȐwݐyyz}z}z}z}z}z}z}z}w t#) 08ڭB$ѧM8ɠXJ™aYjerozw}~}{{Œ{ڒ|쎔}}}}}}}}}w v!'- ߲4ֱ@#ͪL7ŤVI_Xgdonww}“֔ꑎ􁍀􁍀􁍀􁍀􁍀􁍀􁍀x x$* ܷ1Ӵ>!ʮJ5TG]Wecmnuv|}ԕ铈󃈃󃈃󃈃󃈃󃈃󃈃󃈃x +z!&ټ/ Ϸ= DzH4RF[Vcbkmrvz}і蔂퍂򅂇򄂇򄂇򄂇򄂇򄂇򄂇y +|߻!ֿ, ̻;õG2QDYTaailpuw}}{ϖz{||||||||z +* ȿ9E0OCWR_`gkntu|}}yvt͖rtvvvvvvvv{  (7C.L@UP]^dikrrzz{vrol˖kmoooooooo|  +ٲվ %5@+J=SMZ[afippxw~ztokgeʔcegggggggg}  ڨԵ!2=(G:PJWW_cflmtyt{s}nhd`]ʐ\]_``````` լϹ.:$D5METS\^cgyjosrvmz{gb]YWɊUVXXXXXXXXأϱɾ, 7@0I?QLXWy``sghlonfxta˂x\ˎ|W˝S˱Q˂OPQ{Q{Q{Q{Q{Q{Q{Q{ޙѩɶ "/8>*F8NDyUOr\Xld_fle`uj[nVیqRܛtOݯvLwKvKuLrLrLrLrLrLrLrLr֠˯¼%/6='D2yK;sSCm[JgcPbkU^tZY}]UaQcNeKfIgGgGfGfGfGfGfGfGfGfݗͨö$-5~;"wB*qI1kP8fX=b`A^hEZqHWyKSNPQMSJTHUFVDVDVDVDVDVDVDVDVҠŰ"*{2t9n@"hG(cM,^S0Z[3Wc6Tk8Qs;O|=L?IAFBDCBD@E@E@E@E@E@E@E@EǪx& p.j5d<_CZI!VO$SV&P\)Mc*Jj,Hr.E{/C1@2>3<4:5:5:5:5:5:5:5:5|tl! e) _0Z7U=QCMIJOGTEZB` ?g!=o#:w$8%6&3'1'1'1'1'1'1'1'1'xo g`Z# T* O0K6G<CA@F=J;P8U6[3a0h.o+w)&&&&&&&&ukbZ +SMH"C( ?. +<2 87 5; 2?/C-H*M'R%X"_ eluuuuuuuu`Y#R/ Z2 _:aD`O][ [h%Xu)V-T/S1Q3P4O5O6N6N7M7M7M8L8L8L8L8K7K7K7K7K7K7K7`Z"T. [0 a9cCbN_Y ]g&Zt*X.V1U3S5R6Q7Q8P9O9O:O:N:N:N;M:M:M:M:M:M:M:M:M:a["W, _/ e7hAgLdV!ad'_q,]}0Z4Y6W8V:U;TR?Q?Q@P@P@P@P@P>P>P>P>P>P>P>b\!Z* +c- i6l?kIiT!fa(cn.az2^6\:ZX@WAVBUCTDTESESFSFRFSDTBTBTBTBTBTBTBc]!^' +g, m4p=pGnR"k^)hk/ew5b:`>^A\C[EZGYHXIWJVKULUMUMULVIWGWGWGWGWGWGWGd^ a% l* r2u;uEsO"qZ*nh1jt8g~=dBbF`I^L\N[PZQYSXTWUWVWUYQZN\L\L\L\L\L\L\Le_ e" p) +w0z9zByL!wV*td3po;lzBiGfLcPaS_V]X\[Z\Y^Y_X_Z[]X_T`Q`Q`Q`Q`Q`Q`Qf`i!t' {. 6?I!}S*z`4uk=qvFmMiSfXc\a`^c]e\f\g[g[f^ba^cZdWdWdWdWdWdWdWgbny%, 4<EO*\5{g?vrIq{RmZi`fcdfciak`l`m`m_mbhedg_h\h\h\h\h\h\h\hcq}#) +19BK(X4߁cA{mMvwVr]nclgijgmfoeqdrdscsfnhikdkakakakakakakaifu!'. 6?H&ߌT3ه_AҁjN|sWw{_teqjnnlqjsiuhwhxgxitlnninenenenenenenejix%+ +3;E#ڒQ1Ҍ\ĂfMǁoX}x`yfvlspqsovmylzl{l|mypsqmriririririririkl{#)0 8ݜCԗO0͑Z@NjcMlXu`~|gzmxruvsyr{q}ppp}svupulululululululkn~ &- +4٢@МL.ɕW?aLjXrayhn|szwx{v~uttӂt瀚wzxsxoxoxoxoxoxoxolp")ި0 ԥ>̠J-ĚU>^LgWo`wh~ns~x||zyxxЄx䃓{|{v{q{q{q{q{q{q{qms%ۭ. ѩ<ȣH,S<\KeVm`th|nty}~}||͆{↍~x~s~s~s~s~s~s~smu װ+ά:ŧG*Q;ZIcUk_rgynty}ˇᇆ򁇂zuuuuuuun xݱӳ)ʰ9E)O:XHaTi_pgwn~ty~Ȉ~߈񂁆{vvvvvvvo z ڶз'dz7C'N8WG_Sf]nfum|ty~|yƉx݉yz|{w{w{w{w{w{w{wp }  ޥدչ ̺$÷5A%L6UE]Qd\kerlzsx}|xurĉq܉rt}txtxtxtxtxtxtxq   +بӲмȾ!3?#I3RBZObZicpkwqwz|vrnkˆjۈkm}nynynynynynynyr  ڠӫε0= G0P@XL_Wf`mh~toy|utzo~kgdbچce|fxfxfxfxfxfxfxt ߗգίɹ- :D-MnE%hL+cT0_\5[d8Wl:<:;;;;;;;;;;;;;;êzsl' f/`7[>WDRJOQLWI^!Ff#Cn$@w&=(;)8*7+5,4,4,4,4,4,4,4,~vnga"[* +V1 Q8M>ICFICO@U=[:b7j4s1}/,+* * * * * * * }qia[TO#J)F0 +B5 >: ;? 8D5I2O/U,\)d&l#u!~}pd\TM HB> :&6+20/4,8 )= +&B +#G M S Z b irxxxxxxxSL&I. O1 T9VCUOR[OhLu!J#H%G&F'E(D)D)D)C)C*C*B*B*B)B)B)B(B(B(B(B(B(B(TM&L, S/ X7ZBYLVYSfPr"N~%L'K)J*I+H,G,G-G-F-F-F-E-E-E-E-E,E,E,E,E,E,E,UM%O* V- \6^@]KZVWc Tp$R|'P)O+M-L.K/K0J0J1I1I1I1H2H2H1H1H0H/H/H/H/H/H/VO%R( [, +`4 c>bI^S\`!Ym%Vy)T,S.Q0P2O3N4N5M5L6L6K7K7K7K7K5L4L3L3L3L3L3L3WP$V&_* +e2 h<gFdQa\"^j'\v+Y/W2V5T6S8R9Q:P;PN>N=O;P9Q8Q8Q8Q8Q8Q8XQ#[#e( k0 m9mCkMgX"ef)br._|3\7Z:XV@UBTCSDREQFQGQFSCTAV>V=V=V=V=V=V=YS"_ j&p. s6s@qJnU#kb*hm1dx7a<_@]C[FYHXJVLUNTOSPSQUMWJYGZD[C[C[C[C[C[CZWdo$u+ y3 y=xFuQ"r]+ni3jt;f}AcF`K^O[RZTYUXVXWXXWXZT\P]M_I_H_H_H_H_H_H\[is"z(~0 9~C|M"yY+te5po>kyFgMeQbTaW_Y^[]\]^\^\^][`WaScOdNdNdNdNdNdN]_mx &- 6?H U+za6ukAqtIm}OjThXf[d^c`bbacad`dabd]fXgThShShShShShS^bq{#*2 ;EۆR)Ԁ]6{gAwpJsyQpWm[k_ibhdffeheieiehgbi]kXlWlWlWlWlWlW_et &. 6ݐBՌN'ΆZ5ȁdA|mKxuRu}Xr]panelgkjjliminhmkgmbo\o[o[o[o[o[o[_hw#*2 ؖ?АL&ɋW4†aAjK}rSzyYw_tcrgpjomnompmqlqokqes_s^s^s^s^s^s^`kz%ܝ-Ӛ<˕I%ďT3^@gJoS~vZ{~_ydwhulsorqqsqtptrnuhwbwawawawawawaan}١*Ϟ:ǙG#R2\?eJlStZ{`}e{iymwpvsuuuvtvvqxkzezczczczczczcbpޢԤ(̡8ÜE"P1Z>bIjRqYy`ej}n{qztywyxxxzt|m}g}e}e}e}e}e}ebs   ۦѨ%ȥ6C N0X=`HhQoYv_}ejnr~u}x}y}z}voiggggggcu  ٢֩ +Ϋ#Ũ4AL.V<^GfQmXt_{ejosvy~z|{|w~qjiiiiiifx +ٜդҬʮ 2 @J,T:\FdOkXr^yejos}vzyx{v{vxxrykzjzjzjzjzjzjh zܕ՟ѧίƱ0 >H*R8ZDaNiVo]wd~in{swvtyq{o{oyrsslskskskskskskk ~٘Ѣ̪ɲ. +;F(O6WB_LfTm\tb~|hymurqumxjzhzhyjsllmkmkmkmkmkmkoޏԛͥȮö+9D%M3U?\IcRjY}r`xyfsknojsfvcxax`wcrelejejejejejejsړϟȩ²'6A!J/R;ZEaN|hUwo\rwbmghlcp_r\tZuYt[o^j^i^i^i^i^i^ixԘˤî +"2=G*O6W@|^IvePplWkt\f}baf]jYmUnSoRnTkVfVeVeVeVeVeVe~ۏΝũ- +9C$L/{T9u[BpbIjjOerU`{Z[^WbSdPfMgLfMcO`O_O_O_O_O_O_Ӗȣ'4?{H'uP1oX9i_@dgF_oKZxPŨTQ̐WM͠ZJ͵[H\G[GYHWHWHWHWHWHWHW܍̝#0 z:tDmL&hT.c\4^d:Yl?UuCP܀GLݍJIݝLF޲MDNCMCMBKBKBKBKBKBKBKҖĥ}$w/ p8j@dG`O#[X(X`,Th0Pq3M{6I9F;C=A>?>>>==============ȟyr"l, f5a=\DWKSRPZ Mb#Jj%Ft(C*@,>-;/9/8070606060606060|smga(\0 +W8 S>NEKKGRDYAa>i;s8~5 3!1"0#.#.#.#.#.#.#.#zoga[V"Q*L1H7 +D= AC =I:O7V4]1e.o+z(&$"""""""ymb[TNID"@(<.94592> /C +,I +(O %W "_ hr}yl_TMGA<730$,)(-%1"6;@GNV ^ +g p +z +} +} +} +} +} +} +F=*A-F/ J8 KBKNGZDgAs?=<;:::9998888888888888G>*D+I- N6 O@NLLXHeEqC}A@? > >!=!=!=!iHfSc_"`k(]v,Z1X4V7U9S;R=Q>P@OAOAOAP?RYAWCVEUFUGTHTITIUGWCX@Y>Z;Z;Z;Z;Z;Z;OWdnt%x-y6 w?uJqW"mb+im3fv:c?`C^F]H\J[LZNYOYOYPYO[J\G^C_A_A_A_A_A_AQ[hsy"})1 ~;|EyS!t^+ph5lrЅKɀW+{a5wj>trEqzKoOlSkViYh[g]f_e`e`g\iVjRkNkNkNkNkNkNUe s~"ۑ+Ҏ;ˊIąT*^5|g>yoFvvLs~QqUoXm\l^kajbicidj`lZnUoQoQoQoQoQoQXh v ֕'Β9ƎFQ)[4d>}lFzsLx{QuVsZr]p`ocnenfmgndp]rXsTsTsTsTsTsTZk +y ܗҙ%ʖ6 ’DO(Y4b=jE~qL|xRzVx[v^tbsergqhqirgt`u[vVvVvVvVvVvV]n { ڕؚ +Ϝ"ƚ4 BM'W3_=gEnLuR~|W|[z_xcwfviujukuiwby]zXzXzXzXzXzX_ p~ڑ՗ӝ˟ Ý2 +@K%U1]I$S0[:cCjKqQxV[`dh~~k|~lz}my}m{f|`}\}\}\}\}\}\duڍӖΝˣå.<G"Q.Y9aBhJoPvV}[`d{hxkvmtnrntgvax]x]x]x]x]x]fxאϙʠƦ+:E O,W7_AfHmOtU{[}`ydvhrkommnlnnhpbr]r]r]r]r]r]j{݈ӓ̜ƣ(7CL*U5\>cGjNqT|xYx^scogljilgmemggibk^k^k^k^k^k^m~ٌϗȠ %4@J'R2Z;aDhK{oQvvWr~\maieehbj`k^k`fbad]d]d]d]d]d]rԐ˛ä 1 =G#O.W8^@zeGulMpsSk|Xg]ba^d[fYgWgYc[_\[\[\[\[\[\[w܈ϕƠ,9CL)T2y[:tbBoiHjqNeyS`W\[X^UaRaQaR_S[UXUXUXUXUXUX}Սɛ'5?I#yQ,sX3n_:hgAdoF_wKZOVSRVOXLYKYKWLTMRMRMRMRMRMR߄ϔá /~:wDrM#lU+g\1bd7]lD֫@BAA@A@@?@?@?@?@?@?@?̕{up$k0f: aB\KXST\ Qd#Mm'Jw*F-C/@1>2<2;2;1:2:2:2:2:2:2ßypkf#a-\6 X> SEOMLUI]FeBo?z: 6&3,/1+6(<%B"IQZd o | + + + + + + + vh[OE?950 ,)% !$).39@ HQZeoy9"2-8+;.?7 @B >M ;Z7f4r2~0//...------,,,,,,,,,,:"4+;)>,C5 D@ CK?X'C*H3I> IIEUBb?n==<<<;;;;;;;;;;;;;;= ?"H P%U.V8 +UB SNOZLfIrG|FED C!B!B"B"A"A#@#@#@#@"A!A!C CCCCC?DMV#\+]5 ]? ZJVVSbQnNxM"K#J%I&H'H(G)G)F*F*E+E*F)G'H&I%I%I%I%I%I%@IS] b(d1d; aE]PZ]XiUt"S}&R(P+O,N.M/L1K2K2J3J3K2L0M.N,N*N*N*N*N*N*ANYci$k-k6 +iAeLbY_d ]o%Zx*W.V1T3S5R6Q8Q9P:P:P;P:Q7R5S2T0T/T/T/T/T/ER_hn!q)r2p< mGjTg`!cj(`s.^|2\5Z8Y;XV?V@UAUBTBV?W;X8Y5Y5Y5Y5Y5Y5IVdmsw$x,w6 uBrPn["jf*go0dw5b9`<_?]A\C[EZFZHYHYHZE\A]>^;^:^:^:^:^:MZ hrx|~&~0|> xLtX"pb+mk2js7h{c>c>c>c>P^ +l u|ۃ*҂; ~HzT!v^+rg2oo9mw>k~BiEgHfKdNcPcQbRbSbQdKfGgCgBgBgBgBgBSbo +y  ߇Ո&͆7 +ƃEQ!{[*wd3tl9rs?ozCnGlKjNiPhSgUfVfWfVhOjKkFkEkEkEkEkEU er{އۊ ь#ɋ5CN X*|a2yi9vp?twDr~HpLoOmRlUkWjYjZjYlSmNnIoHoHoHoHoHX +hu~ۅ׊Վ͐ ŏ2@LV)_2}g9zn?xuDv{ItMsQqTpWoYn[n\m\oVqPrLrJrJrJrJrJZkwށ؈ӍБɓ0>JT(\1d9~k?|rDzyIxMwQuUtXs[r]r^r^sXtSuNvLvLvLvLvL]my܃ԋϐ̔Ŗ-<GQ'Z0b8i>pD~vI}~M{RyVxYw\v^}v_|u_}wZ~xTyOyNyNyNyNyN_p|نю˓ȗ+:EO%X/`7g>nCtI{MR~V|Z|{]zz_xz`vz`wz[x|Vz|Qz|Oz|Oz|Oz|Oz|ObrՉ͑ȖÛ(7 CM$V-^6e=lCsHyMR}VyZv]t_rap~aq\sWtRtPtPtPtPtPdu܂ьʔĚ%5 AK"T,\4c;jBpGwM{QwVtZp]n_kajaj]lWnRnQnQnQnQnQhx؅ΏƗ "2 ?IQ)Y2`9g@~nFzuKv}PrUnYj\g^e`c`d]fWhShQhQhQhQhQl|ԉʓ›/<FO&V/^7}e=xkCtsIpzNlRhVdZa\^^]^][_VaRaQaQaQaQaQp݁ύƘ+8CL"T+|[3wb9si?npEjxJfOaS]VZYWZVZVXXTYPZOZOZOZOZOv׆ʒ&4 +?H{Q&vX-q_4mf:hn?dvD_I[MWPTSQTOTOSPPRLRKRKRKRKRK|ЌŘ /;{EuMpU'k\-fd3bk8]s=Y}AUEQHNKKLILIKJIJFKFKFKFKFKFڄʓ~(y5 s@nIiQdY$``*\h.Wq3S{7O;K>H@FADACAC?C>D>D>D>D>D>ЌÚw so-j9 fCaL]TY\Ue#Qn'Mx+Iσ.Fϑ1Cϣ3@й4?4>4=4=4=3=3=3=3=3ȕulfc#`1\<XF TOQWM`JiGsC!@ߍ#=%;&9&9%7&6'6'6'6'6'6'~tja]Y"V-R6N?JG +GO DWA`>j;v85310/......~rh^VRNK'G0D8@?=F:N7V +4_ 0i -u*(&$#"!!!!!~rf[QKF B? ;'8.451;.B+I'Q$[ er  + +        qdXMC>95 2.+#')$. 4;BJT_ +kyrdWJ?71,($ ! % + +18AKUany,'*,/*1,353A1M +-Y )f &r $}""!! !     + +        -&-)2'4*839?6J +3W /c ,o)z(''&&&%%%% % $ $ $ # $ $ $ $ $ $ $ .&0&6$9'>1?<=H +:T 6`3l0w..-,,,,++++***********/%4";!@%E/F9EE +AQ >]:i8t6~5443332222111111333330$9@H#L,M6LA JM FYCe@p>z=<;;:::99988999::::::4!>FO T(U2T= QH NTK`HkFvEDCBAA@@@???@@AAAAAAA9CMV[%].\8YC VOR[PgNqLzKJI H"G#G#F$F%E%E&E&F%G#G"H!H H H H H =IT]b!d)c3a> ]I[VXbVlTvR~"P$O&N(N)M*L+L,K-K-K.L,M*N(N&N%N%N%N%N%BMZchj$j-h8eD cQ`]]g[q"Yy&W)V,U.T/S1R2R3Q4Q5P5Q3R0S.S,T*T*T*T*T*FQ +_ hmpp'o1n?kMgYdc bl%_t*^|-\0[2Y4X6W8W9V:V;U[@ZAZAZA[<]8]5^3^3^3^3^3M [gou +x y{%z7wEtQp[!md(kl-is2gz6e9da@`B_D_E^F^F`Aa=b9c7c7c7c7c7P ^jsx|} +!3|ByNuX!ra(pi.np3lw7j~;h>gAfCdFdHcIcJbJdEeAf=g:g:g:g:g:Sbmv|ՀӁ˄Ã0?}KzU w^(tf.rm3pt8n{syCpGlKhNeQcSaS`RbMdIeEeEeEeEeEjzφŐ)7 +BKS$~Z+za1vh6ro;nw@jEfIbL_O\Q[QYQ[L]H^E^E^E^E^Eoʋ%3?H}P yX't_-pf2lm8htI?G@F?G=G]G YPUXR`NiJsG~"Cɋ%@ɛ'>ɰ(<(;(:(:)9)9)9)9)9)Õzpf]YW'U4R?OHLQ I[ FdCn@z<و:٘8ڭ654211111zoe[RMKI,F6C?AH>Q;[9e +6p 3~1.,+*)(((((zncYOGCA>%;.865>3F0O-X*c'p$~"  +        {naVLB<852/$,+)2%9"AJT_l{   +     |n`TI>40+( $!$+29 BLXfu}o`SF:0(#  !(09CO]ky,"*%)%+'4%?"KXdp{    +%')&)(-2-=)I%V!bn y    "))$-"0%405:1F-R)_ &k $u +" +! +! +! +  &&. 27#;,<7:C6O2[ /g +-r +| * * ) ) ( ( ( ( +' +' +' ' ' ' ' +' +) +) +) +) +) ++!38? C)D3C??Ks<|<;:::9998888999999994>GOS!T*S5P@ML JY HdFoExDCBBAA@@@@@@AAAAAAAA9C NVZ\%[/X:TFSS Q_OjMsL{KJIIHH G G!F!F"F!G HHHHHHH>HT \`ba(_3]@[N +YZWdUnTvR}Q P"O$N%N&M'M(L)L)L)M&M$N#N!N!N!N!N!B MYa eggf+e;cI +aU^`\iZqYx"W%V'U)T*S,S-R.R/Q0Q0R-S*S(T&T%T%T%T%FR^eik kl$l7jE +hQe\cd`m!_t%]{(\*[-Z/Y0X2W4V5V5V6W3X/X,Y*Y)Y)Y)Y)IWbinpo +r r3pA +mNkXhafi#dp'cw*a~-`0_2]4]6\8[9[:Z:[8\3]0^-^-^-^-^-LZemruuww/u> sJpUm^ke$il(gs,fz/e2c4b7a9`;`=_>_>_d@cAcAc@e:e6f3f3f3f3f3Ralu{~~)~8|EyOvXt`#rg(pm-ot0m{4l7k:j=i@hBgCgDgCh=i9j5j5j5j5j5Tcox~ǁ‚&6B}M{Vx]#ve(tk,sq0qx4p8o;n>mAlC}kE|kF{jE|l?|m;}m7}m6}m6}m6}m6Wfr{ɁÅ #3@ JS|["zb'xi,wo0uv4t}8s<r?|pBzpExoFvoGunGvoAwp HQY!~`'}g+{m0zt4x{8}wrt:st9st9st9st9]lyˁÈ.; +FOW ^&e+l/~~r4{}y8x|fAcDaF_G^G_C`?a;a;a;a;a;hxʄ#2= GOzW v^%se*ol/ks3h{8d<`?]BZDXEWEXAY>Z:[:[:[:[:n}Ɖ.: ~DyLuTq["mb'ii+eq0by4^8ZT@RAQAQ>R;S8T8T8T8T8t̓(}5x@ sIoQkXg_!cg&_n*[w/X3T6P9M;K;J;J9K7L5L5L5L5L5{lj|y!u0p;lE hMdU`\]dYl#Ut'Q~+N.J1G3E4D3D2D1D0D/D/D/D/΃|rnk(h5d?`H ]PYXV`RiNrK|"G%D'A)?)>)>)=)=(=(=(=(=(Ƌtib +_\+Z7WATKQS +N\JdGnDy@Æ=Õ;ç9þ87655555uk`WO MK+J7HAFKCTA^>h ;t 8ҁ5ґ3Ҥ1ӽ0/.-,,,,vk`VLC= ;:(837>6I4S2^0j-x+)' % $ # " " " " " wj_TJ@84 +1/!-*+3)='F$Q!\ixwj]RG=4,)&# '.7@KW +euxj\PD9/&!  '/8DP_pzk]OB6+!  +%/;HWgw,('*2=JW +coy)%$&!1;GT`l w   + +  &"!$ &$).(9$D Q]it}!"'). 1+26.A*M&Y#e py&,/7:&:19=4H1U-`+k)u)~((''''&&&&%&&'''''''+28@C!C,A7>C;O8[5f4q3y3221111 0 0 0 0 0 +1 1 1 1 1 1 1 1 07 @GKK&I1G=DIAV?a>l=u <} +< ; ; ; ::::99:::::::::5<H +NRR Q*N5KBJPI\Gg +Fp ExEDCCCBBAAAAAAAAAAAA9 +CNT XXW!T-T<SKRW Pa OjNrMzLKJIIHHGGGGHHHHHHH>ISZ]] [[%\7[FZR +X\VeUnTuR|QQPO!N"N#M$M%M%M$N!NNNNNNANX^ab` +b d3cAaN _X]a[iZpYwW~ V"U$T%T'S(R)R*R+R)S&T$T"T!T!T!T!ER\chigij.i>gJ eTc]ae_l^s ]z"\%['Z)Y+X,W.W/W/W/X+Y(Y%Y$Y$Y$Y$HV`hmomno+o:mG jQhZfbeicp!bv$a}'`)^,].]0\1[3[3[3\.]+](^'^'^'^'KYdmrtsst's7qC +oNmWk_ifhm"fs%ez(d+c-b0a2`4`6_6_6`2a.b+b)b)b)b)N\hqvxwwx$x4vA tKqTo\nclj"kp&jw)h~,g/f2e4d6d8c9}c9}d4~e0~e-~f+~f+~f+~f+Q`lty||{ | |1z>xIvRtZrapg"on%nt)l{,k/j3i5|h8zh9yg:wg;wh6xi2xi/yi-yi-yi-yi-Tcox}.~<|FzOxWv_te!sk%rr)py,~o0|n3ym6wl9ul;sk<;:999999‹{odYUS"Q/O;MDKMHVE_Ci @s =:7543210000}qf[QGCA!@->8=C(I'U&b%q#܀!ݓީsfZOE;2*#!&0;FSap   + tfYMB8.&  " ++5AN]nugYL@4*!  $.9GWi|whYK>2& + +%1?Pbt (%$ +& 0;HUamx&! #.9 ER^ju~" +6BO [ gqz%''&3!>JWbmw   + +  $'.0#0.-:(F$R!^ir{%* 0 798(743@/L,Y*d)m)v(~((''''''&&'((((((((+ 09 ?A@!>-;98F6S5^4i4r4y333332222222 2 +2 +2 +2 +2 +2 +2 +06AF HGE$A1@>@L@Y?c?l>t>{= = += < < < ; ;;:;;;:::::4=GLNMJH'I8JGJSI^Hg Go Fv F}EEDCCCBBBBBBBBBBB8CMQSRN Q!S3SBSNQY Pb OjNqMxL~LKJIIHHHHHIIIIII<IQX\[WY[.[>ZJYT +W] VeUmSsSzRQPOONN M!M!NOOOOOO@MW_cc_`b*b9`F_Q +]Z\bZiYoXvW|VUU!T"S$S%S%R&S#T TTTTTCQ\dhiffg&g6fCdM +cVa^`e_l]r\y[[!Z#Y%X'X(W)W)X&X#Y!YYYYGUaimnlk l"l2k?iJ +hSf[ebciboav`|!_#^%](]*\+\,[,\*]&]#]!]!]!]!KZemrsqp pq/p<nG +lPjXi_hfglesdz!c$b'b)a+}`-{`.z`/y`,ya(ya%za#za#za#za#N^iquwvttu,t:rE pNoVm]lckjjpiw"h%}g({f+ye-wd/ud0td0sd.td*te'te$te$te$te$Qamty{zxxy)x7vBuK sTq[paognn}mu"{l}%xk(vj+ti.rh0ph1ng1ng0oh+oh(oh&oh&oh&oh&Uepx|~~|||&|4z@yI wQvYt_~sf{rlyqs"vp{%so)qn,nm.ll0jl2ik2hk1il,jl)jl'jl'jl'jl'Yit{#1=}G {OzW|y]zwdwvjtuq"qty%os)lr,ir.gq1ep2cp2cp1dp-ep*ep'ep'ep'ep']mw .:D M{Tx~[u}br{hozo!lzw%jy(gx+dw.av0_u1^u2]u1^u-_u*`u(`u'`u'`u'bq{+7~AzJ wRsYp`mfjn gu#d~~'a}*^}-[|/Y{0X{1W{0Xz,Yz*Zz'Zz'Zz'Zz'gu&}3y>uG +rOnVk]hdekbs!^|$[(X+U-S.Q.Q.R+R(S&S&S&S&m{~z w/s:oClL hSeZba_i\qXz!U$R'O)M*K+J*K(K&L%L$L$L$tÀ}vro)l5h?eHbP _W\^YfUnRxOK"H$F%D%D%D#D"D!D!D!D!{ynhe!c.`:]CZKWS T[ QcNkKuHEB?>===<<<<Ă~se^ZW%U2S<QEONLVI_ Fh Cr@}=;876544444vk_SL IH'F2E=CFAP?Y=c:m7z5 +2 0 / . - ,++++ymaVK@: 75$4/3:2D0O/Z-f+s)Ƃ'Ɠ%ƨ##"!    {nbWLA8.%! (4?KYgwՊ֠׼}ocVK@6,$  # +.:HVgyqcVI=3)  )5CSeyrcUH;0% #/=NavteVG:-" '6H\p%! #-9FS`lv~ "  + +6CP\hs{( 3?LYdox%/; H T`jt|  $% #+6BO[fow  + +  !(-.,$*0%<!IU`jsz$'15 +641(.5*B(O(Z)e)n)u)|**)))))))))***)))))09== ;73+3:4H6U6_6h6p6w6~55554444344 3 3 3 333.7@CC@;<"?4ACAOAZAc@k@r?y?> > += += = < < < < < < < ; ; ; ; 2>EKMKEGI.K>KJJUI^IfHm Gt +Fz F EEDDCCCCCCCCCCC6CMTVUOPR)S9SFRQQZPb +Oi No MvM|LKKJJIIIIIIIIII;HT[^]XWY%Z5YBXMWVV^ Ue TkSrSxRQPPOONNNOOOOOO@NY`dd`^ _ `1_>^I]R \Z [aZhYnXuW{VUUTTS S STTTTTTDS^eiifcde-d;cFbO aW `^_e^k]q\x[ZYY X!~X"|W#{W"{X{X{X{X{X{XGXcjmnlhij*i8hCgLeT d[cbbhao`u_}_}^ {]"y\#w\%v\%u\$u\!u\u]u]u]u]L\fmqrpmmn'm5l@kJjR hYg_ffel~ds|dzzcwb!ua#sa%r`&p`'o_&o`"p` p`p`p`p`P`jquvuqqr#r2q=oGnO lWk]}jc{ijyiqwhxugrf!pe$ne&ld'kd(jc(jd$jd!kdkdkdkdTcntyzyuu v v/u;sErM +qT |p[ynbwnhumorlvpkmj"ki$ii&gh(eh(dg(eh$eh"fhfhfhfhXgqx|~}yz zz,y8xB~vK {uR xtYus`srfpqmnqukp}ho!fn$dm&bm(`l(_l(_l%`l"al alalal]ku|~~~~)}5}|@z{HvzP syWqx^nwdkwkivsfu{ct!as$^r&\r'Zr(Yq(Zq%Zq"[q [q[q[qboy$|2x=uErM +oU l~[i}bf|id{qa{y^z [y"Xx%Vx&Tw'Sw&Tw$Tv"Uv UvUvUvgt}}z v.s9pBlJiR gYd`ag^o[xXU R"P$N~$M~$M}"N} N|O|O|O|my}wro(l4i>fGcO`V ^][eXmUvROLI H!G GGGHHHsxojg"d/b9_B\KZRWZ +Tb QjNsK~HECA@@@@@@@ztg` ]Z'X3V=TFQNOVL^Jg +Gp D{A><:9888888znaVQNL*K5I?GHEPCYAb>l;x 9 +6 4 2 1 0 /////~rfZND@><*;49>8H7R5\3g1s/,*(''%% $ $ $ ui]RF;2-+*'(1'<&F$R#^"k zxk^RG<2(*6B O ^ +n ΀ΔΫyl_RF;1' &2?N^o݃ݙ޲{m_RE9.$ ".;K\o~o`RD7+  (6GZnqbRC6)!0BVj}!*6DQ^is{'3ANZfpx%0<JVblt|   +  !+8EQ]gpx &2 ?LWbks{" " +8EQ \ f n v } !(+* '##0=JV`iqx~ !     ")131- (%%'6)D*P+[,d-l-s-y-,,,,,,,,,,,,++++'17;<7/ +1406>7K8V8_8g8n8t7z7776666555555555+7@FHE==?*A9BFBQBZAbAiAp@v@|??> > +> += = = = = = = = += += +2>IOQOIGI%J4KAJLJUI]IeHkHqGx F~ F E EEDDDDDDD D D D 7EPWYXRO P Q0R=QHQQPYOaOg Nm +Mt Mz LLKJJJIIJJJJJJ;LV]`_ZVWX,X9XEWNVVU]Td +Tj Sp RwR~QPPOOO~N}O}O|O|O|O|OAQ[beea\\](^6]A\K[SZZY` +Yg XmWtW{VU}U{TzTxSwSvSvTvTvTvTvTFV`fijfbab$b3b>aH`P_W^^ +]d \j\q}[x{ZyZwYuXsXrXqWpXpXpXpXpXpXKZdjmnkffg!g0f;eEdMcTb[ +}aa {ahy`ox_vu_~s^q]o]n\l\k\k\k\k\k\k\k\O^hnqrpkj kk,j8iBhK~gR{fY +ye_ weeudlsdtqc|nblajah`g`f`f`f`f`f_f_f_Tbkquvtoooo)n5n@}mHzlPwkW tj] ridpiknhrlgzjfgfeecdbd`d`dadadacacacXfouyzyssss&s3{r=xqFupNsoU po[ nnblmiimpglyekbj`j^i\i[i[h[h\h\h\h\h\jsy}~}www}w"zw/ww:tvCquKntSltY is` grgernbqw_p]oZoXnWnUnUmVmVlWlWlWlanw}}||| x|u|,r|7o|@l{IizPgyW dy^ bxe_wm]wuZvWuUuRtQtOsOsPrPrPrPrPrgs{}vrn'l3i=fEdMaT_[ +\c Z~kW}sT}}Q|O{L{JzIzIyIyJxJwJwJwlxxpjg!e.b9`B]J[QXXV` +Sh QqN{KHFDCBBBCCCs~sib _\(Z3X=VESMQUO]Le Jn Gy DA?=<;;;;;;y|pcYTQ O+N6L?JHHPFXDaAk?v< +9 7 5 4 3 32222vj]QIEC"A-@7>@=I;S:\7f5r30.,+*)) ( +( +( +znbVI?742"1,/6.@-J+T*`(l&z$"!~qeYMB6-$ )3>IUcq tgZNB7-# #/;HVevƉƞƷvi[NB6," !,9FVgzՎզxj\NA5* (5CTg{zl]N@3' "0@Sg{}n_O@2% +<Pey'4BO[gpy$1>KWcmu} !,:GS_iqy (5ANZdmt{ + + ".;HT^hov} '4AMXbjqx~  * +9 FR\elsy"'(&!2@L V!_!g"n"t"z""""###""#######*2661''*+,:-F.Q.Z/b/i/p/v/|///............&2=BC?736%749A9L9U9]9e9k9q9w9~88887777777666-;FKMJC> @ A/B<BHBQBYB`BgAmAs@y@@??? ? +> +> +> +> > > >>3CMSUSLGHI+J8JCJMJUI\IcHiHoGvG}F F +E E E EDD D ~D ~D ~D ~D :JTY[ZUOOP'P4P@PIPQOXO_NeNlMr My +L L K~K|J{JzJxJxJwJ wJ wJ wJ @OY_a`\UUV#V1V<VFUNUUT\SbSiRo ~Rv |Q~ {QyPwPuOtOsOrOqOqOqNqNqNFT^cfea[Z [[-[9[CZKYRYY~X_|WfzWl +xVt vV|uUsUqToTnTlSlSkSkSkSkSkSJXbgjjg`_ __*`6_@^H}^P{]Vx\]v\cu[j +s[q qZzoZmYkYiXhXgXfWfWfWfWfWfWO\eknnkedcd&d3~c={cFxbMvaTs`Zr`ap`h +n_o l_xj^h]f]d\c\a\a[a[a[a[a[a[S`inqrpihhh#|h0yg:vgCtfKqeRoeXmd_kdf +icm gcvebcbaa_a]`\`[`\_\_\_\_\_Wdmruvtnml{lxl,ul7rkAokImjPkjWii]gid +ehl bht`g~^f\fZeXeWeVdVdWdWcWcWc\hpvyzyrq{q vpsp)pp4mp>kpFioNfoUdn[bnb `mj ]mr [l|YlVkTjRjQjPiQiQhQhQhQhamuz}~~y|vuvpvmv%jv1hv;fvCcuKauR_tY]t`Zsh +Xsp UrzSqPqNpMpKpKoKnKnKmKmKmfqy~x}o|j{f| d|,b|7`|@^{H[{OY{VWz^UyfRyn +Oyx MxJwHwFvEvDvDuDtEsEsEslv~tib _\'Z2X<VDTLRSP[NcLlIv +F DA~?~>~=}=|={=z=z=zr|}od[VS!Q,O6N?LGJOHWF`DiAt?< +: 8 7 6 6 5 5 5 5 yxk^SL +IF$E/C8BA@J?R=\;e9p6|420..-,, , , ~reXMB< :8&60593B2K0U/`-k+x)'%$#"""""vj^QE;1* ('$%.$8"B!MXdrzmaTH=2(  +6 A M +[ iy}pcVJ>3(  )5AO^nseWJ>2' '3@O`rυϛϳufXJ=1% #/>ObuwhYK=/# *:Mbwzk[L<.! %6Kaw$2?LYdmv}!.;HU`jry + )6DP\enu|$1>KV`iqw}*8EP[dkrx~  +"0>JU^fmsy  +'6CNX`hntz + #  + + .<HR[biou{$.21+! '"5#B$L%U%]%d%k%q&w&}&&&&&&&&&''&&&!09>>91*,!.0/<0G0P1X1`1f1l1r1y11111000000000*9CHHE>678+97:B:L:T:[:b:h:n:u:|:9999988888772AKPPNH@@A&B3B>BHBPBWB^BdAjAqAxA@@@@~?|?{?z?y?y>x>x>:HQVWUPIGH!I/I:IDILITHZHaHgGmGu~G||F{FyF wE +vE uE tE sE +rD rDrDrD@MV[][VPM NO+O7OAOINPNW~M]|Md{MjyLrwLyvLtK +rK qK oJ nJ mJ lJ lJ +lI +lI lI ER[`ba]VSST'T3T=TF|SMzSTxRZvRauRhsQoqQwpP nP lP kO iOhOgOfO fN fN fN +fN +JW_dfeb\XXX$X0|X:zXCwXKuWQsWXqV^oVenVmlUujU~ +hU gT eTcSbSaSaSaR aR aR aR N[chjjg`]\~] z]-w\7t\@r\Hp[Om[Ul[\jZciZkgZseY| +cY aX`X^X]W\W\W\W \V \V \V R_fknnkeb}a yaua)ra4pa=m`Ek`Mi`Sg_Zf_ad_ib^q`^z +^] \]Z\Y\W\V[W[W[ WZ WZ WZ Wbjorrpjfyf tepe&me1ke;ieCgeKedRcdXad__cg]co[cy +Yb Wb UaSaRaQ`Q`Q_R_ R^ R^ [fnsvvunzktknjkj#hj.fj8djAbjH`jO^iV\i]ZieXhmVhw Tg Rg PfNfLfKeLeLd Ld Lc Lc `krwz{zuwrnphoeobp*`p4^p=]pE[oMYoTWo[UncSnkPnuNm +Lm Jl HlFlEkEj Fi Fi Fi Fi eow|{tyivbu ^v\v&Zv0Xv:VvBTvJSvQQuYOuaMuiJtsHt~Es +Cs Ar @r ?r ?q ?p ?o ?o ?o kt|}pe~[|V|T| R}+P}5N}>M}FK}NI|VH|^E|gC{qA{|>{l>?LSWYWRLFFG%G1H;~HC|GKzGRxGXvG_uGesGmrFtpF}oFmFlEjEiEhEgEgDfDfDfDDQX\^\XRLLL!~L-{M8xM@vMHtLOrLUpL\oLcmLjlKrjK{iKgKfJdJcJ bJ aJaIaIaHaHIU\`ba]WRQ|QxQ*uQ4sQ=pQEnQLlQRkPYiP`hPhgPpePycPbO`O ^O ]O +\N +[N [N[M[M[MMY`dffb\W|V wVsV'pV1mU:kUBiUIgUPfUWdU^cUfaUn`Uw^T\T[T YS +XS +WS +VR VR VQVQVQR\dhjjga~]w[rZnZ#kZ.hZ7fZ@dZGcZNaZU`Z\^Yd]Yl[YuYYWXUX TX +RX +QW +QW +QV QVQUQUV`glnnlfzbr`l_i_ f_+c_5a_=`_E^_L\_S[^ZY^bX^jV^tT^~R]P] N] +M\ +L\ +L[ L[ LZLZLZZdkprsqkvgmegdcd`d(^d2\d:ZdBYdJWdQVdXTd`RchPcrNc}LbJbIb Gb Fa Fa F`F_F^F^_iptwwv~rsnhkai +]iZi$Xj.Vj7Uj?SjGRjNPjVNi^LifJipHi{FhDhBhAg@g@f@e@e@d@ddmty|}{|xpuer[pVpSpQp*Op3Np<LpDKpKIpSHp[FpdDpnBoy@o>nwa JVcrsfYL?3( +  *5@M[jzwi[NA4)   *5AP_pzl]OB5( +(4ARcvĊġĺ}n`QB4'$2ASg|ْ٪qbRC4&  !0BVksdTE5& +.BXn -:GS^gov| + (6COZckrx~ #1>JU_gntz+8EOYbiouz%2?JS\djpu{ +8CMV^ekpu{#0<GPX_ekpv{ '4@IRY`fkqw}&)&  + -9CLTZaglsy*364/'&3=GNU\ b h n u | !!!!"~"~!}!}!'4=@?;4+%' (-)8*B*J*Q*W*^*d+j+q+x++~+|+{+z+x+w+v+u+u*u*0=DHHD>6/ 01(243=3E3M3S3Z~3`}3f{3mz3uy3~w3v3t3s3r3p3o3n3n2m2m27DKNOLF@889$9/:9~:A|:Iz:Px:Vw:\u:ct:js:rq:{p:n:m:k:j:i:h:g9g9g9g8>IPTUSMGA??}@+z@5x@>u@Es@Lr@Sp@Yo@`m@gl@ok@xi@h@f@e@c@b@a?a?a?`>`>CNUYZXTNHE {EwE(tE2qE:oFBmEIkEPjEVhE]gFefFmeFvcFbE`E_E]E\E[E[D[D[C[CHSY]^]YSNzJ uJqJ$nJ.kJ7iJ?gJFeJMdJTcJ[bJb`Kk_Kt]K~\JZJYJWJVJVIUIUHUHUGLV]acb_Y}TuPpOlO!iO+fO4dN<bNC`NJ_OQ^OX\O`[OiZOrXO|WOUOSNRNQNPNPMPLPLPLQZaegfc]zYpUjTfTcS(aS1^S9]SA[SHZSOYTVWT^VTgUTpST{QTPSNSMSLSKRKQKQKPKPU^eikkhbv^kZeY aX^X%\X/YX7XX?VXFUXMTYURY\QYeOYnNYyLXJXIXGXFXFWFVFUFUFUYcimoom}hrdh``^[]X^"V^+T^4R^<Q^DP^KN^RM^ZK^cJ^lH^wF^D]C]A]@]@\@[@Z@Z@Z^gmrtts{nokegZdUcRcPc(Nd1Ld9KdAIdHHdPGdXEdaDdjBdu@d>cj^q(=q1;q9:qA8qI7qR6q[4qe2qq1q}/q-q+p*p*p*n*m*l*low}~rdX}L{Az9y 6y4y"3y+1y30y<.yD-yM+yW*yb(yn&y{$y#y!x xw v u t tu}yl_RF;0*(&#%,#5">!HR]iw~}}|sfYK?4)#-6@KW d +rxk^QC7," #-8CP]k{}pbUG:.#%/:FTcstfXJ<0$  $/;IXi{whZK>0$ ".;K]ozk\M>0#  +,;NavӋԣԻ|n_O?0"*;Pe{qaQA1" (<Ri + *7DP[dlsy %3@LW`hou{ .;GQ[cjpv{ (5ALV^elqw|"/;FPX`flqv{ (4@IRZaflqv| -9CLT[aglqw} $1<FNU[aglrx#%! )5?GOV\ b g m +t +{ + + + + + + (/1/*"!.8BIPW]cipw~|{yxwww&29<;6/&  (!3!<"E"L"R"X#^#e}#l|#s{#{y#x#v#u#s#r#q$p$o$o#o#/;ADD@:2)()#*.+8+@}+G{+Ny+Tx,[v,au,ht,pr,xq,o,n,m-k-j,i-h,h,g,g+7AHKKHB<401}2*z23x3<v3Cs3Jr3Qp3Wo3^m3el3lk4ui4h4g4e4d4c4b4a3a3a2`2=GNQQOID=~8 z8v8&s90q98o9@m9Gk9Mi9Th9Zg9be:jd:sc:}a:`:_:]:\:[:[9Z9Z8Z8BLRVVUPJDy>t>p>"m>,j>5h><f>Cd>Jc>Qa?W`?__?g^?p]@{[@Z@X@W@V?U?U?U>T>U=GPWZ[ZVP|JsDnCjCgC)dC1bC9`C@^CG]CN[DUZD]YDeXEnWEyVETESEQEPDODODOCOBOBKT[^_^[UyPoJhHdHaH%_H.\H6ZH=XGDWHKVHSUIZTIcSIlRJwPJOIMILIKIJIJHJGJGJFOX_bdc`ZuUjPcN +_M\M"YM+WM4UM;SMBRMIQMQPNXONaNNkLNuKNINHNFNENDMDMELEKEKS\cfhge|_q[gV^SYRVRTR(RR1PR9NR@MRGLROKSVIS_HSiGSsESDSBSAS?S?R?Q?Q?P?OXagjlljyenad]YXSWPWNW%LW.JX6IX=GXEFXLEXTCX]BYgAYr?Y~>X^R=^[;^e:_p8^|7^5^4^2^2]2\2[2[3Zbjptvvuuqin]kRgGeBd@d>d&#tG"tQ t\tgttttsssqpoot|vi[NB7~,}"}}}}&}.}7}A}K}V}c}q } | |{{z y x +w{|obUG;0%   &0:EP]kzuhZM?3' (2=IVdtzl_QC6) )4@M\l}~pbTF8+ )5BQbtteVH9, +(5DVh|whYI:,&5GZo΄Ϝζyk[K;, $6J_u|n^N=-"6Md| '4AMXahov{"0=HS\dkqw|+7CNW_gmrx} %2=HRZbhmsx}+7BLU\bhmrw} %1<FNV]bhmrw}*5?HPW]bhmrx~ +!-8AJQW]bhmsz   + +%0:CKQW]chov}~}|{zz&,-+% +) 3 = EKRX^djr~z|{yxvusrqqq%06872+"#.7?G~M|SzYy`wfvntvsqpnmljiiih.8>A@<6.% !~"){#2y#;w$Bu$Is$Or$Up$\o$cm$jl%sj%|i%g%f%e%c%b%b%a%a%a$5?EHGD>80~) +z)v*$s+.q+6o+>m,Ek,Kj,Qh,Xg,_e,gd,pc-za-`-_-]-\-[-Z-Z-Z,Z,;EKNNKE@9x2s1o1 l1*j22h2:f2Ad2Gb2Na2U`2\^3d]3m\3wZ4Y4X4W4U4T4T3T3T2T2AJPSSQLF|@s9m7i7f7&c7/a76_8>]8D\8KZ8RY8YX8bW9kU9uT9S:R:P:O9N9N9N8N8N7ENTWXVRLxGn@g= c<`<#]<,[<3Y<:W_Q>iP>sN?M?L?K?I?H>H>H=H=H<JSX[\[W~RtMjGbB]BZBWA(UA0RA7PA>OAENBMMBULC]KCgJCqID}HDFDEDDCCCCCCBCACANW\`a`]{WqRfM]HWGTGQF%OF-MF5KF<JGCIGKHGSGH[FHeDHoCH{BIAI?H>H=H=G=G>F>ER[`dedbx\mXcSXNRL NLLL"JL+HL3FL:ELADLIBMQAMY@Mc?Mn=NzRFi3f.f,f*f$)f,'f4&f<$fE#fO!gY gdgqgffffedcblty}x~k{]xPuDs9q-o$n +!nnn&o/o7o@oJoUoaono}o n n m +l k j jszreWJ}>{2z'yxw wxx( x1 x: +xExPw\wjwxwvvuttsszyl_QC7+  !*4?JWes~~}||~rdWI;.#  $-7CP^m~wi[M?2% $.:GUew{m_PB4'  $/<K[m~qbSD5' ".>OauteUF6(  .@Sh~ɕɮwhXH8( +0DYoyk[J:) + 1H_v$1=IT]elrx}-9DOXahnsy~ '3?JS\cioty~!.9DNV^djoty~ (3>HPX^dinsy~!-8AJRX^dinsy &1;CKRX^chnsz *4=ELSX^cinu| "-6>FMSX^djpx}{zxwvuut$)*'!  %/8@GMS~Y}_{ezlxtv}usqpnml k +k +k $.353.' (~2{:yAxHvNtTsZqaphnqmzkihgedcbbb-6;=<82+" +{x#u-r5p=oCmJkPjVh]geemdwba_^][[ZZZ4=CED@;4-x$s"p#m#(j$1h$8f$?e%Fc%La%S`%Z^%a]%j\&tZ&Y&X&V&U&T&S&S&S&S%:CHKJHB<{5s.l)h*e*$c+-a+4_+;]+B[+HZ+OX,VW,^V,gU-rS-}R-Q-O-N-M-L-L-L,M,?HMPPNICw=n6f1 +b0_0 \0)Z11X18V1>T1ES1LR1TP2\O2eN3oM3{K3J3I3H3F3F3F2F2G1DLRUUSO|IsCj=a7[6X6U6&S6-Q64O6;N6BL6IK7QJ7YI8cH8mG8yE9D9C9B9@8@8A8A7A6HQVYZXTzNpIfC[=V;R;O;"M;*K;1H:8G;?G;GE>>=><>;=;=;<;<<;MUZ]^]YwTmObJWDPA L@J@G@(E@/C@6B@=AAE@AM?AU>B_F4=F;;FB:FK9GS8G]6Gh5Ht4H2H1H0H.G/G/F0E0EU]bfgf~dr_g[]WRRFM@K=K;K"9K*8L16L95L@4LH2MQ1M[0Mf.Mr-M,M*M)M'M(L(K)K*JZbgjlk|ipeea[^OYCU:R +6R4R3R&1R./R6.R=-RF+SO*SY(Sd'Sp%S~$S"S!S S R!Q"P"P_gloqqzonlchWdKa?]3Z.Y,Y*Y")Y*'Y2&Y:$YC#YL!ZV ZaZnZ|ZZZYYXWVelquwwxulr^nRkFh:e/b&a +#a!aa%a.a6a?aHaSa^akayaa a ` ` _^]krw{}}t{gxYuMrAo5m)kji ii i(i1i: iD iO i[igiviihhgfferx~|ob~T{Fy:w.v#tssrrr"r+r5r?rJrVrcrqrqqponnnyvi[M?3'~}}|| |||&|/|9|D|Q|^{m{|{zyxxwv|oaSE7*(2=JXgwtfXI;-  )4AO_pxj[M>0" )6EUfz|n_P@1# )8H[nqbRB2#(:MbwĎŧteUE4$ )=Ri݀ޘޱvhXG6%,BYp -9EPYahnty~ )5@KU]djotz #0;FOW_ejpuz*5@IRY`ekpuz +$/:CLSZ`ejotz)4=FMTZ_djot{ #-7?GNTY_diou|&08@GNTY_djpx}|{zyy + )2:AHNTY_e~l}s{{ywutrqpoon!&&# +!+3;}B|HzNyTwZu`tgropxnmkjhgfeed#+01/*# ~z$x-u 5s +<q +Cp +In Om Uk \i ch kf ue c a ` _ ] \ \[ [ +49:94.'zuqn'l0j7h>fDeKcQbX`__h]r\|ZYWVTTSSS2;@BA=71{)s!m if#c+a3_:^@\G[MYTX\VeUoSzRPO NLL LLL9AFHGD?9v2n+f$a#^#\$'Z$/X$6V$<T$CS%JQ%QP%YO&bM&lL&wK&I'H'F'E&E'E&E&E%>FKMMKE{@r:i3`,[)W)U*#R*+P*2O*9M*?K*FJ+NI+VH,_F,jE,uD-C-A-@-?->->,?,?+BJORRPLxFo@e:\3U0 Q/N/ L/(I//H/5F/<E0CD0KC1TA1]@2h?2s>2<2;3:28282829190GOTVWUQuKlFbAW:O6J5H4E4$C4+A42@59?5A>6I=6R;7[:7f97r886858482727373645KSXZ[Z~VsQiL_GTAJ;D:B:?:!=9);:0::79:?8;G7;P5dIdUdadod~ccbbaa`qw|yl}_{PxCv6t*rpo +nn nnn&n/m9mDmPm]mkmzlkkjiihx~sfXI;}/{#zy yxx xxw!w*w3w>wKwXvfvvvutsrrqyl^OA3& #,7DRaq~}||~qcTF7) $.;IYj|ugXI:,#0?O`syk\L=- #1BTh~|n_O>/ "4G[qqbRA0 #7Lczؓ٫teUD3!&<Sk)6ALU]djpuz +%1=GPX_fkpuz,7BKSZafkpu{ &1;ENU[afkpu{ +6?HOU[`fkpu| %/9AIOU[`ejpv})2;BIOUZ_ejqx ",4<CIOTZ_els{}{yxvuttt %.5=CIO}T|Zz`ygwnuwsqpnlkjiih##'|/y6w=vCtIsOqUp[nbljjsh|gecba`_^^!)..,&  | +xt r)o0m7k>jDhJgPeWc^bf`o^y][YXWVUUU*26761+$|tn + k +h "e *c 2a 8` ?^ E]L[SYZXcVlUwSRPOMLLLL19=?=:4~.v&ngb_\%Z-X4W;UATHROQWO_NiLtKIHFEDDDE7?CEDA<z6r/i(a ZWU!R)P0O7M=LDJKISG\FgE rC B @ ? > = = = ><DHJJGBw=n7e0\)T# +P#M#K#%I#,G#3E$:D$AC$HA%Q@%Z?&d>&p<&};'9'8'7'6&6&7&7%AHMOOM~ItCk=a7W1N*I)F)D)"B))@)0>)6=)><*F;+N:+X8,b7,n6,{4,3,2,0,/,0,1+1+FMQTTR|NrIhC^>T7I1C. @.=.;.&9.,8.47/;6/C40L30U21`11l/2y.2-2+2*2)1*1+0+0JQVXYWzSoNeI[DP>F9>4 947353#33*241149/5A.5J-6S,6^*7j)7w(7&7%7#7"7$6%5%5NUZ\]\xYmSbOYKNFC@8;3919/9 -9(,:/*:6):?(;G&;Q%<\$}L|[|k||{zyxww{n`QB3% (5CSdvrdUE6'  *9IZmvhXI9) +<Ocxyk\L;+ .AUk|n_O>- 1G]uҍӦԾqbRA/ 6Mf~ &2>HQY`flqv{!-9CLT[aglqv{(3=GOV\bglqv| +"-7AIPW\bglqv}'1;CJQW\afkqw~ +!+4=DKQV[`ekqx%.6>DKPUZ`fls{}|{zz '07>DJOUZ`g}n{vywvtrqponn  !)1~8}>{DyJxOvUu[sbqiorn{ljhgedccc  |y#v+s2q8p?nDmJkPiVh]fedmbwa_]\[YYXX '++(#} wrol$i,g3e9d?bE`K_R]Y[aZjXtVUSRPONNN(0342.(~ woi +eb_&]-[4Y:X@VFUMSUQ]PgN qM }K I H F E E E E 07;<;71z*q#ib[ X V S(Q.P5N;LBKIJQHZFdEoC{B@?=<<==6=ABA>9v3m,d%\TPMK#I*G1F8D?CFAN@W>a=l<y:8764556;BFHGD|?s:j4`-W&NIFCA'?->4<;;C:K8T7_6 j4 w3 1 0 . - . / /@GKMMJzFp@g;]4S.J'B# +?"<":"#8"*6#15#84$@3$H2%R0%\/&h-&u,&*&)&(&&&'&(%)%DKOQQOxKnFdAZ;P5F/=)8(5(3' 1'&0(..)5-)=,*F+*P*+Z(+f',s%,$,",!, + +"+#*HOTVVTvQlKbGWAM<C6812. /---+-$).+(.3'/;&/D$0M#0X"1d 1r1111110/MSXZ[~YuVjQ_MVIKDA>69,4 (3&3%4"#4)"40 595A6K6V6b7p77776654QX\__}^s\hW^STOJK>E2@';!: :::&:.;6;?ZIZUZcZrYYXWVVUnty{}s{fxXuJr/! #0>M^p~}paRB2#$3CTg|teUE5% &7I]rwiYI8' +(;Of}zl\K:),AWöʣʿn_O>,1Hay".:DMU\bhmrw|)4?HPW]chmrw} $.9BKRX^chmrw~)3=ELRX]bglrx #-6?FLRW\aglry'08@FLQW\afmt| !*19@FKQV[agnv|{ywvuut#+3:@EK~P|V{[ybwiuqt{rpnlkjihh   +~%{-y3w:u@sErKpPoVm]kdimhvfdb`_^]]\ { wsp'n-l4j:h@fEeKcQbX``^h\rZ}YWUTSRRQ%((% xrmif c(a._4]:\@ZFXMWTU\SdQnPzNLKJIHGG'-12/+%zrj d_\Y"W(U/S5Q;PANHLPKXIaGkFwDBA@>>==.58984~.v(m e]U +ROM#K*I0H6F=D DC LA +T? +^> i< u: 9 7 6 5 +4 4 5 4;?@?;{6r0i)`"WOI FDB%@+>2=9;@:H8Q7[5g4s20/-,,--:@DEEBx=o7f1\*S$JB ><:!8(6.553=2E1O/Y.d,q*)'&$$%&>EIJJGvCl=c8Y2P+F%=7420$.+-2,:+C)L(W& b% o# ~"     CIMOO~MtIjC`>V9M3B,9'1" +-!+!(!!'"(&"0%#7$$@#$J!%U %`&n&|&&&&%%$GMQTS|RsNhI^DT?J:@56/+)&'$'"'!(% (-)5)>*H*R+^+l,z,,+++**KRVXX{WqTfN\JSFIA?<47(1!. ...#.*/3/;0E0P1\1j1y 1 +1110 0 /PVZ]]z\pYeU[QRMHI%95445 5(5069 6C 7N 7Z7h7v7777665U[_bbyao_d[ZXPTDO7J,E!A=; < +< <%<.=7=A=L>X>e>t>>==<;;Z`dghwgnecbX^KY?U3P'LIFD +DDD#D+D5E>EIEUEcEqEDDCBBA`fjmnwmnl`gScF_9[-X!TQ OM MMM M(M2M<MGMSM`MoLLKJIIHflps~tvtiq[mMi@e3b&_\ZXWWVVV$V.V8UCUPU]UlT|TSRQPOmswy}{qxcvUrFo9l,igecbaa ``_ _)_4_?_L^Y^h^y]\[ZYXuz~xk}\{Nx?v1s#qo +nmkkkj jji#i.i:iGhUhdhugfecbb|}qcTE~6|'zy xwvvuuut ttt't3t@sOs_sprqpnmmvhYJ;+ *8GXj~}}|{zy{m^O?/  +-=Obv~qbRB1!!1CWltfVE4#"6J`xwiZH7%&;Rjńğĺl]L;)+C[t*6@IQX^dimrw} %0;DLSY_dimrx~ *5>FMTY^chmsy%.8@HNTY^chms{ )2:BHNSX]bhnu}#+4;BGMRW\bhow~}|| &-5;AGLQW\bj}r{{ywusrpoon '.5};{AzFxKwQuWs]rdplnvljhfeccbb + +|x!u(s/q5o;n@lFjLiQgXe_chbq`|^\ZYXWVV{v +qnk"h)f/d5b;aA_F]L\SZ[XcVmTxRPONLKKK#&%"{ smh d`]#[)Y0W6V;TARHPOOVM_KiItGFDCBA@@%+//-(~"vmf_ZVSQ$O*M0K6I=HCFJDRB\Af?q=<:98766-36751z+q%i`X QMIGE%C+A2?8>?<F:O9X7c5o4}20/.-,,39<=<9w3n-e'\SKC + @=; 9'7 -6 44 +;3 +C1 L/ V. a, m* {( ' % $ " # $ 8>BCB~?t:k4b.X(O!F>7 420".)-0+7*@(I'S%_$l"z =CFHG|Er@i;_5V/L)B#91,*(&%%-$4"=!F Q]jxAGKMLzJqFgA]<S6I0?*6%,& " "*2:DO[ h v   FLOQQyOoLeF[BQ=G8>34-*( " !!""'#/#8$B%M%Y &f &t +&&&&%%$JPTVVxTnQcLYHPDF?<:25'/*( (()%)- *6 *? +J,V,d,r,,,,+**OTXZ[wZmWbSYOOKEG9A.<"72/ + / /0#0+141=2H2T2a3p322110/SY]_~`v_l]bYXVMQAL5G)B>: 7 777!7)828;9F9R9_9n9~987765Y_ce}fuelca`U[IW=<;_dhk|ltkkj^ePaC]6X*TQNKJI IHH#H,H6HAHMHZHiGyGFEDCBejoq{rsrfnYjJf=c0_#\Y WTSS +RQQQ)Q3Q>QJPWPfPvONMLKJlqux{ynvasRpCl6i(fda`^]\\ [[Z$Z.Z:ZGZTYcYsXWVUTSsy|u}h{ZxKu.  +=Qg~rcSB1  0E[rufWF4" 5Me~iZI7%%=Voފۦ &2<EMTZ_dinsy !,7@HOUZ_dintz&1:BIOUZ_dinu| !*4<CJOTY^ciov~$-6=CINSX^cipx '/6=CHMRX]cjr|}{yxwwv!(07=BGL~R|X{^yewmuvsqomljiih ~#{)y0w7v<tArGqLoRnXl`jhhqf|db`_]\\\ z vsp$m*k0i6h<fAeGcMaS_[]c[lYwWVTSQPPP }vqlheb$`+^1\6[<YAWHUNTVR^PhNsLJHGFEDD!##~v ohc ^[WU%S+Q1O7N<LCJJHQFZEdCoA|?><;:::$),,*%zqiaZU QNKH&G,E2C8A>?E>M<V:a8l7y53210//+1442.v(m"d\T +LG DA> <';-937:5A4J2S0^/j-w+*('&&%17:;9|6s0j+a$XOF>:753"1(//.6,>*F)P'[%g#u! 7<@A?z<q7g2^,U%KB:1 .+) ' $& +$ +2# :! C N Y f t    ;ADFEyBo>e8\3R-H'? 5-% +" '/7AKWdr   +  + @FIJJwHmCc>Z9P4F.<(3#* $,5>I U b +pDJMOOvMlIbDX?N:E6;02,(&! ! * 2 < G S!`!n!~!!! INRT~TuRkOaJWFMBD=;903%.($ +##$ $(%0&:&E'Q'^'l(|''&&%$MSWX|YtWjT`PVMMICE7?+9 40 +,++++&,/,8-C-O-\.j.z--,++*RX[]{^s]j[_WVTKO?J2E&@<843 333$3-364A4M4Z4h4x432110X]aczdrcia_^SYFT9P-K!GC +?=< ;;;!;*;4;>;J;W;f;v::9876]cgizjqiih[cN^AZ4V'RNKHFE +DDCC'C1C<CHCUCdCtBA@?>=dimoypqpdlVhGd:`-\ YVSQONN MLL#L.L9LELRKaKqJIHGFEkptvxwlt^qOm@j2f%c` ^\ZYXW WVVV)U4UAUOU]TnTSQPONrw{}s{eyWvHs8p*mjhgedcbba +a``#`/`<_J_Y_j^|][ZYXzyl]~N{>y/v trqponmmlll kkk(k5jDjTjeixhgedc~qcTD4$}|{zyyxxxwwww +www-w<vMv_urutrqpvhXH8' "2CVjyl]L;* &8Lax}o`P?- ++?UlrdTC0 0H`ygWF4! 7Pkֆառ ".8AIPV[`ejou{(3;CKQV[`ejov} ",6>EKQV[_ejpw&/8?EKPUZ_dkqy  )19?EJOTY_elt}"+28>DINSY_fn~w|zwvtrqqp $+28}>{CzHxMwSuYs`rhpqn|kigfdccc|yv%t,r2p8n=mBkHjMhTf[dcbl`w^\ZXWVVUzu qmjh&e,d2b7`<_B]H[OYVW^UgSrQONLKJIIxqlg c_\ Z&X,V1T7S=QCOJMQKYIcGnEzDB@?>>>! zrjc^Y UQO M&K,I2G8F>DEBM@U>_<j:w9765433"(**'~"vme \UPKHDB!@'?-=3;99@7H5Q3\2g0t.-+*))))/120{+r&i`XOGB >;86"4(2.15/<-E+N*X(d&q$#! 05897y3o.f(]!TKB :5 2/,+$)*'1%9$A"K Vbo~5;>>=w:m5d/Z)Q#G>6- ( %#!&-5>HS`n}   + + :?CD~Cu@l;b6X0O+E%<2)!     +" +) 2 ; E Q ^ l| >DGH}HtEjA`<V7M2C,:&0!'   & /9CO\jzCHLM|MsJiG_BU=K9B49/0*&%   %-7AMZhxGMPRzRrPhM^HTDK@B;97.2#,& !  # +!5!?"K"X#f#v""!! LQUVyWqUgR]NTKKGAC5=)72-)' &&'!')(3(=(I)V)e)t)('&%%QVZ[y\p[gY]UTRIMW1S$OK GDBA@ ?>>">,>6>B>P>^>n=<;:98chk~nwnonbjSfEa7]*YVSPMLJI HGGG(G4G?GMG[FlF}ECBA@jor}tvuir[nMk=g/c"`][XVUTSR RQQ$Q/Q;QIPXPhO{NLKJIqvy}{pycwTsEp5m&jg +eca`_^^]\ \\[*[6[E[TZeYwXWUTSy}wi}Z{Ky;v+sqonlkjiihhgg gg#f0f?eOe`erdba_^|o`QA~0| zyxwvutttsssssss(r7rGqYqmponlkteVE4$,>Q~e~{}|{zwiZI8'!3F[rzm^M<*%9OhpaQ@-+BZtdUC1 +2LgЁЛз +  !"$%&()*+-./02346789;<=>@ABDEFGIJKMNOPRSTUWXY[\]^`abcefgijklnopqstuwxyz|}~ +  !"$%&()*+-./02346789;<=>@ABDEFGIJKMNOPRSTUWXY[\]^`abcefgijklnopqstuwxyz|}~ +  !"$%&()*+-./02346789;<=>@ABDEFGIJKMNOPRSTUWXY[\]^`abcefgijklnopqstuwxyz|}~ +  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~mft1! +  !"#$%&'()*++,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ +  !""#$$%&&'())*+,--./01223456789:;<=>?@BCDEFHIJLMOPRSUWXZ\^`bdfhjmoqtvy|~ +  !""#$$%&&'())*+,--./01223456789:;<=>?@BCDEFHIJLMOPRSUWXZ\^`bdfhjmoqtvy|~iﻤvOO[yOIwūóiTll6>z.zDls nf|j,!=zmt٫_@zIVn154MsjHg?h1l5sR! + y~gjvؼ͞vS6~e4 QJ/Kfu0jqc-]ZEXIWc[D_j[TT[gιۮhK1#Օ_0tu2Tt&:3%X"q{,rjSdaawf%d~AdХoe_]`huشx^E\oC/l, Z sh Z)E[3#$9  +F}nG+ʭ}|~§tȗnK+vx;NQ,Nj)unc+TH;/%QV?;0$  )ŸܵuX="8b2 [|D[N>{$1s g3]aUPM@LJOBFFDBA@ACGLU_lnRڤwP.g{7;KAYgQ>. %Js<#z׾سuY>!(u@g|FWI5||:o_aUI?>6/*k$5& +$+3cxj$]OQE:K0&T5 =u +!0>LXα}ڨ~Y8z;M%$gx ^MHv4#7`D; y|T"2EZs͒dD?:641/,+*+.w(OkG&%X&Kr xCk^)QzBN0C[ cp}¿aD. AR"]lY;Ha:,Je.< +$3CVkҳ{uqnlkjjjlouR+ a\B& &Pw 0YZjScZ6Q~_o}s^OD;4/+'%"! !#)D!P3b ErmdW#IX: )S/'9,;J[nӿV;& |;bqK7%8]1^ Hjb 3Kfk{밓ocZSMHEA><;<=AIUo% ;{$OvElG Sq=&A`?+9HXi|ŹzZD4( 4dx9j^\N >N- H&-Lz ++=Ri}ܩxohb^ZWUSSSV\dp)W>>u',Sx5]H,a%=WsV=M]m~ƾ|_PE;4/*&"")3BYBm+Os$QW:Vv>->Obwު{wtqpooqt{;( U HrlbS:Db3&&GY+Ii6 /BXqeype]WRNKHFDDEIPZi~ 8 b 2Vz89\d )Il9 0Ga}vCWhzٿgH?:51-*(&%&(.7FZu~(Os*P 2Xx3U{E*B]{x/BSfzěʎ|ywutuvyN,&!)>Zn$~I-l +T~1$FlX.Gd/8J]s¿pjfcba`adgmvG + "Ahj0\)"N{M;`q ":Uu>7J_vȅƯ_WTSTUW[_fo|L Etn3Y52MkT> endobj xref +0 11 +0000000000 65535 f +0000000016 00000 n +0000000279 00000 n +0000020943 00000 n +0000000000 00000 f +0000023667 00000 n +0000020994 00000 n +0000021216 00000 n +0000023555 00000 n +0000023429 00000 n +0000580912 00000 n +trailer +<<90A51FAC79B4AA4892FBD17DB496883A>]>> +startxref +581179 +%%EOF +2 0 obj <>stream + + + + + Adobe Illustrator CS6 (Windows) + 2015-03-26T21:09:06+02:00 + 2015-03-26T21:11:08+01:00 + 2015-03-26T21:11:08+01:00 + + + + 256 + 96 + JPEG + /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAYAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A8tYGx2KuxV2KuxV2KuxV 2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVWtLO6vLlLa1 iaaeQ0SNRUmgqT7AAVJ7DIznGAuRoKAjpNL0qFzFJqsbSJs5hikkj5dwr/Dyp4jY9tsoGbIRYh8y GVDvQ+qaZPp116MjLLGwD29zESYpo2+zJGxAqD7ioNQQCCMsw5hkjY27x1B7j+PMbIIpvRLbTLrV 7O31S7Nhp0syJd3qoZTFGTRn4DdqDBqJzjjJgOKQGw5Woq90bcaJpD3NxDpmsw3IjdhbG5R7T1kD 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 6Yrb/9k= + + + + + + 1 + False + False + + 111.000115 + 41.000081 + Millimeters + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + + + application/pdf + + + HackerHotel + + + + + proof:pdf + xmp.did:D69572F2F3D3E411AD5D85A92A9E06F7 + uuid:4233d7ae-0f2e-4634-96e3-fe739da4e74e + xmp.did:D69572F2F3D3E411AD5D85A92A9E06F7 + 1 + + proof:pdf + + + + + saved + xmp.iid:D69572F2F3D3E411AD5D85A92A9E06F7 + 2015-03-26T21:09:02+01:00 + Adobe Illustrator CS6 (Windows) + / + + + + + + Adobe PDF library 10.01 + False + + + PDF/X-1:2001 + + + PDF/X-1:2001 + PDF/X-1a:2001 + + + + + + + + + + + + + + + + + + + + + + + + + +endstream endobj 6 0 obj <>/Properties<>>>/Rotate 270/TrimBox[0.0 0.0 314.646 116.221]/Type/Page>> endobj 10 0 obj <> endobj xref +0 1 +0000000000 65535 f +2 1 +0000581556 00000 n +6 1 +0000602220 00000 n +10 1 +0000602453 00000 n +trailer +<<8BC25EE1F263034A82E97377275F5E67>]/Prev 581179>> +startxref +602720 +%%EOF diff --git a/hackerhotel2024/artwork/logos/HackerHotel.svg b/hackerhotel2024/artwork/logos/HackerHotel.svg new file mode 100644 index 0000000..eb09280 --- /dev/null +++ b/hackerhotel2024/artwork/logos/HackerHotel.svg @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hackerhotel2024/artwork/logos/HackerHotel_Logo_Lasercutter.svg b/hackerhotel2024/artwork/logos/HackerHotel_Logo_Lasercutter.svg new file mode 100644 index 0000000..ff8fd9e --- /dev/null +++ b/hackerhotel2024/artwork/logos/HackerHotel_Logo_Lasercutter.svg @@ -0,0 +1,406 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hackerhotel2024/artwork/logos/by.svg b/hackerhotel2024/artwork/logos/by.svg new file mode 100644 index 0000000..b349817 --- /dev/null +++ b/hackerhotel2024/artwork/logos/by.svg @@ -0,0 +1,54 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hackerhotel2024/artwork/outro.svg b/hackerhotel2024/artwork/outro.svg new file mode 100644 index 0000000..1074b18 --- /dev/null +++ b/hackerhotel2024/artwork/outro.svg @@ -0,0 +1,639 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2024 + was brought to you by + + More Recordings available on media.ccc.de + + + + + + + + + www.ccc.de + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hackerhotel2024/artwork/overlay-leonardo.png b/hackerhotel2024/artwork/overlay-leonardo.png new file mode 100644 index 0000000..d58dc2f Binary files /dev/null and b/hackerhotel2024/artwork/overlay-leonardo.png differ diff --git a/hackerhotel2024/artwork/overlay-leonardo.svg b/hackerhotel2024/artwork/overlay-leonardo.svg new file mode 100644 index 0000000..6c169ae --- /dev/null +++ b/hackerhotel2024/artwork/overlay-leonardo.svg @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RoomLeonardo Da Vinci + + + + + diff --git a/hackerhotel2024/artwork/overlay-rembrandt.png b/hackerhotel2024/artwork/overlay-rembrandt.png new file mode 100644 index 0000000..f5da51b Binary files /dev/null and b/hackerhotel2024/artwork/overlay-rembrandt.png differ diff --git a/hackerhotel2024/artwork/overlay-rembrandt.svg b/hackerhotel2024/artwork/overlay-rembrandt.svg new file mode 100644 index 0000000..a87a56b --- /dev/null +++ b/hackerhotel2024/artwork/overlay-rembrandt.svg @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RoomRembrandt + + + + + diff --git a/hackerhotel2024/artwork/overlay-willem.png b/hackerhotel2024/artwork/overlay-willem.png new file mode 100644 index 0000000..f38784d Binary files /dev/null and b/hackerhotel2024/artwork/overlay-willem.png differ diff --git a/hackerhotel2024/artwork/overlay-willem.svg b/hackerhotel2024/artwork/overlay-willem.svg new file mode 100644 index 0000000..75b004d --- /dev/null +++ b/hackerhotel2024/artwork/overlay-willem.svg @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RoomWillem van Oranje + + + + + diff --git a/hackerhotel2024/artwork/overlay.svg b/hackerhotel2024/artwork/overlay.svg new file mode 100644 index 0000000..ede8c30 --- /dev/null +++ b/hackerhotel2024/artwork/overlay.svg @@ -0,0 +1,485 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + RoomLeonardo Da Vinci + + + + + diff --git a/hackerhotel2024/artwork/pause.svg b/hackerhotel2024/artwork/pause.svg new file mode 100644 index 0000000..51b7b95 --- /dev/null +++ b/hackerhotel2024/artwork/pause.svg @@ -0,0 +1,963 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BREAK + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hackerhotel2024/intromusic.mp3 b/hackerhotel2024/intromusic.mp3 new file mode 100644 index 0000000..1222d1d Binary files /dev/null and b/hackerhotel2024/intromusic.mp3 differ diff --git a/hackerhotel2024/outromusic.mp3 b/hackerhotel2024/outromusic.mp3 new file mode 100644 index 0000000..48d9111 Binary files /dev/null and b/hackerhotel2024/outromusic.mp3 differ diff --git a/jh16-berlin/__init__.py b/jh16-berlin/__init__.py index b2a0eeb..8e6a330 100644 --- a/jh16-berlin/__init__.py +++ b/jh16-berlin/__init__.py @@ -2,6 +2,7 @@ from renderlib import * +from schedulelib import * from easing import * from collections import deque diff --git a/jh16-nord/__init__.py b/jh16-nord/__init__.py index 3a6d628..c1430de 100644 --- a/jh16-nord/__init__.py +++ b/jh16-nord/__init__.py @@ -2,6 +2,7 @@ from renderlib import * +from schedulelib import * from easing import * from collections import deque diff --git a/jh16-sued/__init__.py b/jh16-sued/__init__.py index a9c7390..6aaff17 100644 --- a/jh16-sued/__init__.py +++ b/jh16-sued/__init__.py @@ -2,6 +2,7 @@ from renderlib import * +from schedulelib import * from easing import * from collections import deque diff --git a/jh16-west/__init__.py b/jh16-west/__init__.py index 9b83e46..6139d8b 100644 --- a/jh16-west/__init__.py +++ b/jh16-west/__init__.py @@ -2,6 +2,7 @@ from renderlib import * +from schedulelib import * from easing import * from collections import deque diff --git a/jh18-berlin/__init__.py b/jh18-berlin/__init__.py index fba2d2a..a2322db 100644 --- a/jh18-berlin/__init__.py +++ b/jh18-berlin/__init__.py @@ -2,6 +2,7 @@ from renderlib import * +from schedulelib import * from easing import * from collections import deque diff --git a/jh18-koeln/__init__.py b/jh18-koeln/__init__.py index 2c98431..7a9e3b5 100644 --- a/jh18-koeln/__init__.py +++ b/jh18-koeln/__init__.py @@ -2,6 +2,7 @@ from renderlib import * +from schedulelib import * from easing import * from collections import deque diff --git a/jh18-ulm/__init__.py b/jh18-ulm/__init__.py index e2d3a4d..b1d09b6 100644 --- a/jh18-ulm/__init__.py +++ b/jh18-ulm/__init__.py @@ -2,6 +2,7 @@ from renderlib import * +from schedulelib import * from easing import * from collections import deque diff --git a/jh19-berlin/config.ini b/jh19-berlin/config.ini index 2a10de5..73365a8 100644 --- a/jh19-berlin/config.ini +++ b/jh19-berlin/config.ini @@ -1,34 +1,35 @@ -[default] -schedule = https://projects.alpaka.space/media/jhber19-schedule.xml +[meta] +schedule = https://projects.alpaka.space/media/jhber19-schedule.xml template = intro-alpha.mov alpha = true prores = true +inout_type = n [title] in = 175 -out = 260 -font = SourceSansPro-Bold.otf -fontsize = 90 +out = 260 +fontfile = SourceSansPro-Bold.otf +fontsize = 90 fontcolor = #ffffff -x = 1090 +x = 1090 y = 450 [speaker] -in = 175 -out = 260 -font = SourceSansPro-Regular.otf -fontsize = 36 +in = 175 +out = 260 +fontfile = SourceSansPro-Regular.otf +fontsize = 36 fontcolor = #ffffff -x = 1090 +x = 1090 y = 900 [text] in = 200 -out = 250 -font = SourceSansPro-Regular.otf +out = 250 +fontfile = SourceSansPro-Regular.otf fontsize = 45 fontcolor = #c68100 x = (w-text_w)/2 y = 927 -text = '' +; text = diff --git a/jh19-hh/__init__.py b/jh19-hh/__init__.py index 2a95c8c..f48cac2 100644 --- a/jh19-hh/__init__.py +++ b/jh19-hh/__init__.py @@ -2,6 +2,7 @@ from renderlib import * +from schedulelib import * from easing import * from collections import deque @@ -184,7 +185,7 @@ def debug(): '../insert_Hanno.mkv', insertFrames, { - '$TITLE': "Hanno", + '$TITLE': "Hanno", '$SUBTITLE': "Jugend hackt Hamburg", } ) @@ -193,7 +194,7 @@ def debug(): '../insert_Julia.mkv', insertFrames, { - '$TITLE': "Julia", + '$TITLE': "Julia", '$SUBTITLE': "Moderatorin und Mentorin", } ) @@ -240,7 +241,7 @@ def tasks(queue, args, idlist, skiplist): infile = 'insert.svg', outfile = "insert_{}.mkv".format(projectname.replace("/", "_")), parameters = { - '$TITLE': event['title'], + '$TITLE': event['title'], '$SUBTITLE': event['personnames'], } ).animated(insertFrames)) diff --git a/jh19-rostock/__init__.py b/jh19-rostock/__init__.py index eb8c769..a3a3420 100644 --- a/jh19-rostock/__init__.py +++ b/jh19-rostock/__init__.py @@ -2,6 +2,7 @@ from renderlib import * +from schedulelib import * from easing import * from collections import deque diff --git a/jh19-ulm/__init__.py b/jh19-ulm/__init__.py index fba2d2a..a2322db 100644 --- a/jh19-ulm/__init__.py +++ b/jh19-ulm/__init__.py @@ -2,6 +2,7 @@ from renderlib import * +from schedulelib import * from easing import * from collections import deque diff --git a/jh20-jue/config.ini b/jh20-jue/config.ini index 310d66d..05878cf 100644 --- a/jh20-jue/config.ini +++ b/jh20-jue/config.ini @@ -1,31 +1,35 @@ -[default] +[meta] schedule = https://releasing.c3voc.de/releases/jhjue2020/schedule-jhjue20.xml -; intro_template.ts was derived from a png which was derived from jhjue-20-intro.svg +; intro_template.ts was derived from a png which was derived from jhjue-20-intro.svg ; ffmpeg -loop 1 -i jh20-jue/jh20-jue-intro.png -ar 48000 -ac 2 -f s16le -i /dev/zero -c:v mpeg2video -pix_fmt:v yuv420p -qscale:v 2 -qmin:v 2 -qmax:v 7 -keyint_min 0 -bf 0 -g 0 -intra:0 -maxrate:0 90M -c:a mp2 -b:a 384k -t 5 jh20-jue/jh20-jue_intro_template.ts template = jh20-jue_intro_template.ts alpha = false prores = false +; in and out time format: t for seconds, n for frame number +inout = n -; fields for title and speaker names are empty in the template.ts, so we'll render them in via ffmpeg +;; Some font settings can have defaults, which can be overridden in the +;; 'title', 'speaker' and 'text' sections below. +[default] +;; default font +fontfile = ebisu.ttf +;; default font color +fontcolor = #ffffff + +;; fields for title and speaker names are empty in the template.ts, so we'll render them in via ffmpeg [title] ; inframe for title -in = 20 -; outframe for totle +in = 20 +; outframe for title out = 225 -; title font -font = ebisu.ttf ; title font size fontsize = 70 -; title color -fontcolor = #ffffff -; title position from upper left corner x = 600 y = 865 [speaker] in = 40 out = 225 -font = ebisu.ttf fontsize = 40 fontcolor = #eeeeee x = 600 @@ -35,13 +39,11 @@ y = 950 [text] in = 3 out = 4 -font = ebisu.ttf fontsize = 45 -fontcolor = #ffffff x = 640 y = 1000 -text = '' +; text = ; build intros via -; ./make-ffmpeg.py jh20-jue/ +; ./make-ffmpeg.py jh20-jue/ diff --git a/jh21-rn/config.ini b/jh21-rn/config.ini index 293225e..626db55 100644 --- a/jh21-rn/config.ini +++ b/jh21-rn/config.ini @@ -1,13 +1,14 @@ -[default] +[meta] schedule = https://pretalx.c3voc.de/jugend-hackt-rhein-neckar-2021/schedule/export/schedule.xml template = jh21-rn-template.ts alpha = false prores = false +inout_type = t [title] in = 1 out = 6.5 -font = SourceSansPro-Semibold.ttf +fontfile = SourceSansPro-Semibold.ttf fontsize = 85 fontcolor = #ffffff x = 410 @@ -16,7 +17,7 @@ y = 877 [speaker] in = 2 out = 6.5 -font = SourceSansPro-Semibold.ttf +fontfile = SourceSansPro-Semibold.ttf fontsize = 45 fontcolor = #ffffff x = 410 @@ -25,10 +26,10 @@ y = 954 [text] in = 3 out = 6.5 -font = SourceSansPro-Semibold.ttf +fontfile = SourceSansPro-Semibold.ttf fontsize = 45 fontcolor = #ffffff x = 1920 y = 1080 -text = '' +; text = diff --git a/jugendhackt/Readme.md b/jugendhackt/Readme.md new file mode 100644 index 0000000..6918d5a --- /dev/null +++ b/jugendhackt/Readme.md @@ -0,0 +1,45 @@ +# Jugend Hackt Design + +Different Jugend hackt events use a similar design for intro and outro, but different accent colors. +This can be achieved by replacing the color and location in a template SVG. + +## Usage + +With this configuration, intros and an outro can be generated for any Jugend hackt event using the `make-ffmpeg.py` workflow. +The ffmpeg video filter-based workflow uses one background video and applies the title and speaker names on top. + +To setup a new event, take the color codes from below and follow these steps: + +1. Generate "outro.ts" + - Copy `outro-template.svg` to `outro.svg` + - Replace `$LOCATION` in the SVG with the location name (in capital letters) + - Replace `$alpaca_color` in the SVG with corresponding color code + - Convert the SVG into png, e.g. with `inkscape --export-filename=outro.png outro.svg` + - Generate a video from the background: `ffmpeg -loop 1 -i outro.png -f lavfi -i anullsrc -c:v mpeg2video -t 10 -aspect 16:9 -c:a mp2 -b:v 2500k -map 0:v -map 1:a outro.ts` +2. Generate "intro-background.ts" + - Copy `intro-background-template.svg` to `intro-background.svg` + - Replace `$LOCATION` in the SVG with the location name (in capital letters) + - Replace `$alpaca_color` in the SVG with corresponding color code + - Convert the SVG into png, e.g. with `inkscape --export-filename=intro-background.png intro-background.svg` + - Generate a video from the background: `ffmpeg -loop 1 -i intro-background.png -f lavfi -i anullsrc -c:v mpeg2video -t 10 -aspect 16:9 -c:a mp2 -b:v 2500k -map 0:v -map 1:a intro-background.ts` +3. Edit the schedule URL in the `config.ini` +4. Run `./make-ffmpeg.py jugendhackt/` and copy the generated files to the encoder + +Note: Do **not** commit the customized SVGs to the repo, but keep this folder generic. +If you really want to commit the config, copy this to a different folder. + +## Colors + +| Location/ Usage | Color Code | Color Name | +| ---------------------------- | ---------- | ----------- | +| Jugend hackt Logo | #00a6de | Soft Blue | +| Hamburg, MV | #00b48d | Soft Green | +| Dresden | #f3971b | Soft Orange | +| Frankfurt | #51509d | Soft Purple | +| Halle | #e6414a | Soft Red | +| Berlin | #00498c | Deep Blue | +| AT/Linz | #4cad37 | Deep Green | +| Rhein-Neckar, München, Ulm | #ea680c | Deep Orange | +| Köln | #4c2582 | Deep Purple | +| CH/Zürich | #e52420 | Deep Red | +| kein Event | #e95197 | Pink | diff --git a/jugendhackt/SourceSansPro-Semibold.ttf b/jugendhackt/SourceSansPro-Semibold.ttf new file mode 100644 index 0000000..bf69cc2 Binary files /dev/null and b/jugendhackt/SourceSansPro-Semibold.ttf differ diff --git a/jugendhackt/config.ini b/jugendhackt/config.ini new file mode 100644 index 0000000..94180a5 --- /dev/null +++ b/jugendhackt/config.ini @@ -0,0 +1,52 @@ +[meta] +schedule = https://pretalx.c3voc.de/jhhh23/schedule/export/schedule.xml +;; path to background video +template = intro-background.ts +;; whether background video uses transparency (needs to be .mov) +alpha = false +;; whether background video is prores 4444 +prores = false +;; in and out time format: t for seconds, n for frame number +inout_type = t +;; fade-in duration (seconds), leave out or set to zero to disable +;fade_duration = 0.5 + +;; Some font settings can have defaults, which can be overridden in the +;; 'title', 'speaker' and 'text' sections below. +[default] +;; default font +fontfile = SourceSansPro-Semibold.ttf +;; default font color +fontcolor = #ffffff + +;; fields for title and speaker names are empty in the template.ts, so we'll render them in via ffmpeg +;; parameters are: +;; - in: start frame/ time +;; - out: end frame/ time +;; - fontfile: font file +;; - fontcolor: font color +;; - fontsize: font size (pixel) +;; - x: horizontal position (top left corner) +;; - y: vertical position (top left corner) +[title] +in = 1 +out = 9.5 +fontsize = 67 +x = 400 +y = 870 + +[speaker] +in = 2 +out = 9 +fontsize = 50 +x = 400 +y = 950 + +;; optional extra text, comment out "text" field to disable +[text] +in = 0 +out = 0 +fontsize = 0 +x = 0 +y = 0 +;text = some additional text diff --git a/jugendhackt/intro-background-template.svg b/jugendhackt/intro-background-template.svg new file mode 100644 index 0000000..ac45ff3 --- /dev/null +++ b/jugendhackt/intro-background-template.svg @@ -0,0 +1,1629 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $LOCATION + + + + + + + + + + + + diff --git a/jugendhackt/intro-background.svg b/jugendhackt/intro-background.svg new file mode 100644 index 0000000..1527640 --- /dev/null +++ b/jugendhackt/intro-background.svg @@ -0,0 +1,1629 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HAMBURG + + + + + + + + + + + + diff --git a/jugendhackt/jh23hh-schedule.xml b/jugendhackt/jh23hh-schedule.xml new file mode 100644 index 0000000..f1bd502 --- /dev/null +++ b/jugendhackt/jh23hh-schedule.xml @@ -0,0 +1,42 @@ + + + + + jugend-hackt-hamburg-2023 + Jugend hackt Hamburg 2023 + 2023-10-29 + 2023-10-29 + 1 + 00:05 + Europe/Berlin + + + + + 2023-10-29T13:00:00+02:00 + 13:00 + 01:00 + Betahaus + jugend-hackt-hamburg-2023-101-abschluss + + + false + + Abschlusspräsentation + Teilnehmende von Jugend hackt Hamburg 2023 + + Talk + de + Alle Projekte werden auf der großen Bühne vorgestellt. + + + + Hanno S. + Rike + + + + + + + diff --git a/jugendhackt/outro-template.svg b/jugendhackt/outro-template.svg new file mode 100644 index 0000000..f60f73f --- /dev/null +++ b/jugendhackt/outro-template.svg @@ -0,0 +1,1558 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $LOCATION + + + + + + + + + + + + + CC-BY 4.0 Jugend hackt 2023 jugendhackt.org + diff --git a/jugendhackt/outro.svg b/jugendhackt/outro.svg new file mode 100644 index 0000000..fe05f82 --- /dev/null +++ b/jugendhackt/outro.svg @@ -0,0 +1,1558 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HAMBURG + + + + + + + + + + + + + CC-BY 4.0 Jugend hackt 2023 jugendhackt.org + diff --git a/jugendhackt/source.xcf b/jugendhackt/source.xcf new file mode 100644 index 0000000..e01939d Binary files /dev/null and b/jugendhackt/source.xcf differ diff --git a/ke1/__init__.py b/ke1/__init__.py index 0135851..88dc29b 100644 --- a/ke1/__init__.py +++ b/ke1/__init__.py @@ -2,6 +2,7 @@ from renderlib import * +from schedulelib import * from easing import * from collections import deque diff --git a/lac18/__init__.py b/lac18/__init__.py index 644d870..5a8fa80 100644 --- a/lac18/__init__.py +++ b/lac18/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/make-adobe-after-effects.py b/make-adobe-after-effects.py index abb9434..dcda85c 100755 --- a/make-adobe-after-effects.py +++ b/make-adobe-after-effects.py @@ -2,7 +2,7 @@ # vim: tabstop=4 shiftwidth=4 expandtab import subprocess -import renderlib +import schedulelib import argparse import tempfile import shlex @@ -86,6 +86,10 @@ parser.add_argument('--bgloop', action="store_true", default=False, help=''' parser.add_argument('--keep', action="store_true", default=False, help=''' Keep source file in the project folder after render. ''') + +parser.add_argument('--mp4', action="store_true", default=False, help=''' + Also create a MP4 for preview. + ''') args = parser.parse_args() @@ -109,7 +113,7 @@ if not args.debug and not args.pause and not args.outro and not args.bgloop and error("Either specify --debug, --pause, --outro or supply a schedule") if args.debug: - #persons = ['blubbel'] + # persons = ['blubbel'] persons = ['Vitor Sakaguti', 'Sara', 'A.L. Fehlhaber'] events = [{ 'id': 11450, @@ -139,7 +143,7 @@ elif args.bgloop: }] else: - events = list(renderlib.events(args.schedule)) + events = list(schedulelib.events(args.schedule)) def describe_event(event): @@ -177,15 +181,15 @@ def run_output(command, **kwargs): def run_once(command, **kwargs): - DETACHED_PROCESS = 0x00000008 - return subprocess.Popen( - fmt_command(command, **kwargs), - shell=False, - stdin=None, - stdout=None, - stderr=None, - close_fds=True, - creationflags=DETACHED_PROCESS) + DETACHED_PROCESS = 0x00000008 + return subprocess.Popen( + fmt_command(command, **kwargs), + shell=False, + stdin=None, + stdout=None, + stderr=None, + close_fds=True, + creationflags=DETACHED_PROCESS) def enqueue_job(event): @@ -196,21 +200,18 @@ def enqueue_job(event): work_doc = os.path.join(tempdir.name, event_id + '.aepx') script_doc = os.path.join(tempdir.name, event_id+'.jsx') ascript_doc = os.path.join(tempdir.name, event_id+'.scpt') - if platform.system() == 'Windows': - intermediate_clip = os.path.join(tempdir.name, event_id + '.avi') - else: - intermediate_clip = os.path.join(tempdir.name, event_id + '.mov') + intermediate_clip = os.path.join(tempdir.name, event_id + '.mov') if event_id == 'pause' or event_id == 'outro' or event_id == 'bgloop': copyfile(args.project + event_id + '.aepx', work_doc) if platform.system() == 'Darwin': - run(r'/Applications/Adobe\ After\ Effects\ 2020/aerender -project {jobpath} -comp {comp} -mp -output {locationpath}', + run(r'/Applications/Adobe\ After\ Effects\ 2024/aerender -project {jobpath} -comp {comp} -mp -output {locationpath}', jobpath=work_doc, comp=event_id, locationpath=intermediate_clip) if platform.system() == 'Windows': - run(r'C:/Program\ Files/Adobe/Adobe\ After\ Effects\ 2020/Support\ Files/aerender.exe -project {jobpath} -comp {comp} -mp -output {locationpath}', + run(r'C:/Program\ Files/Adobe/Adobe\ After\ Effects\ 2024/Support\ Files/aerender.exe -project {jobpath} -comp {comp} -mp -output {locationpath}', jobpath=work_doc, comp=event_id, locationpath=intermediate_clip) @@ -227,57 +228,55 @@ def enqueue_job(event): with open(script_doc, 'w', encoding='utf-8') as fp: fp.write(scriptstr) - copyfile(args.project+args.introfile,work_doc) + copyfile(args.project+args.introfile, work_doc) if platform.system() == 'Darwin': - copyfile(args.project+'intro.scpt',ascript_doc) + copyfile(args.project+'intro.scpt', ascript_doc) run('osascript {ascript_path} {scriptpath}', - scriptpath=script_doc, - ascript_path=ascript_doc) + scriptpath=script_doc, + ascript_path=ascript_doc) - #run('osascript {ascript_path} {jobpath} {scriptpath}', + # run('osascript {ascript_path} {jobpath} {scriptpath}', # jobpath=work_doc, # scriptpath=script_doc, # ascript_path=ascript_doc) - run(r'/Applications/Adobe\ After\ Effects\ 2022/aerender -project {jobpath} -comp "intro" -mp -output {locationpath}', + run(r'/Applications/Adobe\ After\ Effects\ 2024/aerender -project {jobpath} -comp "intro" -mp -output {locationpath}', jobpath=work_doc, locationpath=intermediate_clip) if platform.system() == 'Windows': - run_once(r'C:/Program\ Files/Adobe/Adobe\ After\ Effects\ 2022/Support\ Files/AfterFX.exe -noui -r {scriptpath}', - scriptpath=script_doc) + run_once(r'C:/Program\ Files/Adobe/Adobe\ After\ Effects\ 2024/Support\ Files/AfterFX.exe -noui -r {scriptpath}', + scriptpath=script_doc) time.sleep(5) - run(r'C:/Program\ Files/Adobe/Adobe\ After\ Effects\ 2022/Support\ Files/aerender.exe -project {jobpath} -comp "intro" -mfr on 100 -output {locationpath}', + run(r'C:/Program\ Files/Adobe/Adobe\ After\ Effects\ 2024/Support\ Files/aerender.exe -project {jobpath} -comp "intro" -mfr on 100 -output {locationpath}', jobpath=work_doc, locationpath=intermediate_clip) if args.debug or args.keep: path = tempdir.name - dirs = os.listdir( path ) + dirs = os.listdir(path) for file in dirs: print(file) copyfile(work_doc, args.project + event_id + '.aepx') copyfile(script_doc, args.project + event_id + '.jsx') - copyfile(intermediate_clip, args.project + event_id + '.avi') + copyfile(intermediate_clip, args.project + event_id + '.mov') return event_id def finalize_job(job_id, event): event_id = str(event['id']) - if platform.system() == 'Windows': - intermediate_clip = os.path.join(tempdir.name, event_id + '.avi') - else: - intermediate_clip = os.path.join(tempdir.name, event_id + '.mov') + intermediate_clip = os.path.join(tempdir.name, event_id + '.mov') final_clip = os.path.join(os.path.dirname(args.project), event_id + '.ts') + preview = os.path.join(os.path.dirname(args.project), event_id + '.mp4') if args.alpha: ffprobe = run_output('ffprobe -i {input} -show_streams -select_streams a -loglevel error', - input=intermediate_clip) + input=intermediate_clip) if ffprobe: run('ffmpeg -threads 0 -y -hide_banner -loglevel error -i {input} -c:v qtrle -movflags faststart -aspect 16:9 -c:a mp2 -b:a 384k -shortest -f mov {output}', input=intermediate_clip, @@ -288,7 +287,7 @@ def finalize_job(job_id, event): output=final_clip) else: ffprobe = run_output('ffprobe -i {input} -show_streams -select_streams a -loglevel error', - input=intermediate_clip) + input=intermediate_clip) if ffprobe: event_print(event, "finalize with audio from source file") run('ffmpeg -threads 0 -y -hide_banner -loglevel error -i {input} -c:v mpeg2video -q:v 2 -aspect 16:9 -c:a mp2 -b:a 384k -shortest -f mpegts {output}', @@ -304,7 +303,12 @@ def finalize_job(job_id, event): event_print(event, "finalized " + str(event_id) + " to " + final_clip) else: event_print(event, "finalized intro to " + final_clip) - + + if args.mp4: + run('ffmpeg -threads 0 -y -hide_banner -loglevel error -i {input} {output}', + input=final_clip, + output=preview) + event_print(event, "created mp4 preview " + preview) if args.ids: if len(args.ids) == 1: diff --git a/make-apple-motion.py b/make-apple-motion.py index 3d579b7..c2940e9 100755 --- a/make-apple-motion.py +++ b/make-apple-motion.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 # vim: tabstop=4 shiftwidth=4 expandtab -import subprocess -import renderlib +import schedulelib import argparse import tempfile import shutil @@ -12,8 +11,6 @@ import sys import os import re -from xml.sax.saxutils import escape as xmlescape - # Parse arguments parser = argparse.ArgumentParser( description='C3VOC Intro-Outro-Generator - Variant to use with apple Motion Files', @@ -27,17 +24,17 @@ parser.add_argument('schedule', action="store", metavar='Schedule-URL', type=str URL or Path to your schedule.xml ''') -parser.add_argument('--debug', action="store_true", default=False, help=''' - Run script in debug mode and render with placeholder texts, +parser.add_argument('--develop', action="store_true", default=False, help=''' + Run script in develop mode and render with placeholder texts, not parsing or accessing a schedule. Schedule-URL can be left blank when - used with --debug + used with --develop This argument must not be used together with --id - Usage: ./make.py yourproject/ --debug + Usage: ./make.py yourproject/ --develop ''') parser.add_argument('--id', dest='ids', nargs='+', action="store", type=int, help=''' Only render the given ID(s) from your projects schedule. - This argument must not be used together with --debug + This argument must not be used together with --develop Usage: ./make.py yourproject/ --id 4711 0815 4223 1337 ''') @@ -46,6 +43,32 @@ parser.add_argument('--exclude-id', dest='exclude_ids', nargs='+', action="store Usage: ./make.py yourproject/ --exclude-id 1 8 15 16 23 42 ''') +parser.add_argument('--vcodec', type=str, default='mpeg2video', help=''' + ffmpeg video codec to use. defaults to mpeg2video, libx264 or copy (keeps the original h264 stream) is also often used. + ''') + +parser.add_argument('--acodec', type=str, default='mp2', help=''' + ffmpeg video codec to use. defaults to mp2, aac or copy (keeps the m4a stream) is also often used. + ''') + +parser.add_argument('--num-audio-streams', dest='naudio', type=int, default=1, help=''' + number of audio-streams to generate. defaults to 1 + ''') + +parser.add_argument('--no-cleanup', action='store_true', help=''' + keep temp-dir for debugging purposes + ''') + +parser.add_argument('--snapshot-sec', type=int, default=3, help=''' + number of seconds into the final clip when to take a snapshot (for inspection purposes or as thumbnail) + ''') + +parser.add_argument('--setting-path', default='hd1080p.compressorsetting', help=''' + filename in the script-dir (where this python script resides), + the work-dir (where the .motn-file resides) or absolute path to + a .compressorsetting file + ''') + args = parser.parse_args() @@ -65,10 +88,10 @@ def error(str): if not args.motn: error("The Motion-File is a rquired argument") -if not args.debug and not args.schedule: - error("Either specify --debug or supply a schedule") +if not args.develop and not args.schedule: + error("Either specify --develop or supply a schedule") -if args.debug: +if args.develop: persons = ['Arnulf Christl', 'Astrid Emde', 'Dominik Helle', 'Till Adams'] events = [{ 'id': 3773, @@ -80,7 +103,7 @@ if args.debug: }] else: - events = list(renderlib.events(args.schedule)) + events = list(schedulelib.events(args.schedule)) def describe_event(event): @@ -90,9 +113,22 @@ def describe_event(event): def event_print(event, message): print("{} – {}".format(describe_event(event), message)) +def find_settingpath(): + artwork_dir = os.path.dirname(args.motn) + setting_path = os.path.join(artwork_dir, args.setting_path) + if os.path.exists(setting_path): + return setting_path + + setting_path = os.path.join(os.path.dirname(__file__), args.setting_path) + if os.path.exists(setting_path): + return setting_path + + return args.setting_path + tempdir = tempfile.TemporaryDirectory() print('working in ' + tempdir.name) +settingpath = find_settingpath() def fmt_command(command, **kwargs): @@ -100,21 +136,30 @@ def fmt_command(command, **kwargs): for key, value in kwargs.items(): args[key] = shlex.quote(value) - command = command.format(**args) - return shlex.split(command) + return command.format(**args) def run(command, **kwargs): - return subprocess.check_call( - fmt_command(command, **kwargs)) + os.system(fmt_command(command, **kwargs)) def run_output(command, **kwargs): - return subprocess.check_output( - fmt_command(command, **kwargs), - encoding='utf-8', - stderr=subprocess.STDOUT) + # Apple Compressor behaves weirdly with its stdout. It will not terminate right when ran through + # os.subprocess, but work fine when run via os.system. To still get the output, we pipe it into a + # tempfile. This solution is quite stable. + # see https://twitter.com/mazdermind/status/1588286020121870336 + with tempfile.NamedTemporaryFile() as t: + cmd = fmt_command(command, **kwargs) + os.system(f'{cmd} >{t.name} 2>&1') + return t.read().decode('utf-8') +def xmlescape(xml): + xml = xml.replace("&", "&") + xml = xml.replace("<", "<") + xml = xml.replace(">", ">") + xml = xml.replace("\"", """) + xml = xml.replace("'", "'") + return xml def enqueue_job(event): event_id = str(event['id']) @@ -131,10 +176,11 @@ def enqueue_job(event): fp.write(xmlstr) compressor_info = run_output( - '/Applications/Compressor.app/Contents/MacOS/Compressor -batchname {batchname} -jobpath {jobpath} -settingpath hd1080p.compressorsetting -locationpath {locationpath}', + '/Applications/Compressor.app/Contents/MacOS/Compressor -batchname {batchname} -jobpath {jobpath} -settingpath {settingpath} -locationpath {locationpath}', batchname=describe_event(event), jobpath=work_doc, - locationpath=intermediate_clip) + locationpath=intermediate_clip, + settingpath=settingpath) match = re.search(r"", compressor_info) if not match: @@ -145,7 +191,8 @@ def enqueue_job(event): def fetch_job_status(): - compressor_status = run_output('/Applications/Compressor.app/Contents/MacOS/Compressor -monitor') + compressor_status = run_output( + '/Applications/Compressor.app/Contents/MacOS/Compressor -monitor') job_status_matches = re.finditer(r"", compressor_status) status_dict = {} @@ -177,7 +224,8 @@ def filter_finished_jobs(active_jobs): elif status == 'Successful': finished_jobs.append((job_id, event)) else: - event_print(event, "failed with staus=" + status + " – removing from postprocessing queue") + event_print(event, "failed with staus=" + status + + " – removing from postprocessing queue") return new_active_jobs, finished_jobs @@ -187,15 +235,24 @@ def finalize_job(job_id, event): intermediate_clip = os.path.join(tempdir.name, event_id + '.mov') final_clip = os.path.join(os.path.dirname(args.motn), event_id + '.ts') copy_clip = os.path.join(os.path.dirname(args.motn), event_id + '.mov') + snapshot_file = os.path.join(os.path.dirname(args.motn), event_id + '.png') shutil.copy(intermediate_clip, copy_clip) - run('ffmpeg -y -hide_banner -loglevel error -i {input} -f lavfi -i anullsrc -ar 48000 -ac 2 -map 0:v -c:v mpeg2video -q:v 0 -aspect 16:9 -map 1:a -map 1:a -map 1:a -map 1:a -shortest -f mpegts {output}', + run('ffmpeg -y -hide_banner -loglevel error -i {input} -ar 48000 -ac 2 -map 0:v:0 -c:v {vcodec} -q:v 0 -aspect 16:9 '+(args.naudio * '-map 0:a:0 ')+' -c:a {acodec} -f mpegts {output}', input=intermediate_clip, - output=final_clip) + output=final_clip, + vcodec=args.vcodec, + acodec=args.acodec) + + run('ffmpeg -y -hide_banner -loglevel error -i {input} -ss {snapshot_sec} -frames:v 1 -vf scale="iw*sar:ih" -f image2 -y -c png {output}', + input=intermediate_clip, + output=snapshot_file, + snapshot_sec=str(args.snapshot_sec)) event_print(event, "finalized intro to " + final_clip) + active_jobs = [] if args.ids: @@ -206,7 +263,8 @@ if args.exclude_ids: filtered_events = events filtered_events = filter(lambda event: not args.ids or event['id'] in args.ids, filtered_events) -filtered_events = filter(lambda event: not args.exclude_ids or event['id'] not in args.exclude_ids, filtered_events) +filtered_events = filter( + lambda event: not args.exclude_ids or event['id'] not in args.exclude_ids, filtered_events) filtered_events = list(filtered_events) print("enqueuing {} jobs into compressor".format(len(filtered_events))) @@ -222,7 +280,7 @@ for event in filtered_events: print("waiting for rendering to complete") while len(active_jobs) > 0: - time.sleep(15) + time.sleep(10) active_jobs, finished_jobs = filter_finished_jobs(active_jobs) print("{} jobs in queue, {} ready to finalize".format(len(active_jobs), len(finished_jobs))) @@ -231,5 +289,9 @@ while len(active_jobs) > 0: finalize_job(job_id, event) -print('all done, cleaning up ' + tempdir.name) -tempdir.cleanup() +if args.no_cleanup: + print('all done, *NOT* cleaning up, *TEMPFILES REMAIN* in ' + tempdir.name) + +else: + print('all done, cleaning up ' + tempdir.name) + tempdir.cleanup() diff --git a/make-blender.py b/make-blender.py index eafae78..99035fe 100644 --- a/make-blender.py +++ b/make-blender.py @@ -1,8 +1,13 @@ #!/usr/bin/env python3 # vim: tabstop=4 shiftwidth=4 expandtab +""" +Generate intros by rendering a blender project with some text fields replaced by +the schedule contents. +The blender project must be configured to use mkv/matroska as output file format! +""" import subprocess -import renderlib +import schedulelib import argparse import tempfile import shlex @@ -14,14 +19,14 @@ from shutil import copyfile titlemap = {} -#titlemap = { +# titlemap = { # "205" : { # "title" : "Attacking CPUs with Power Side Channels from Software" # }, # "20" : { # "title" : "New title for Talk id 20" # } -#} +# } # Parse arguments parser = argparse.ArgumentParser( @@ -112,7 +117,7 @@ if not args.debug and not args.pause and not args.outro and not args.bgloop and error("Either specify --debug, --pause, --outro or supply a schedule") if args.debug: - #persons = ['blubbel'] + # persons = ['blubbel'] persons = ['Vitor Sakaguti', 'Sara', 'A.L. Fehlhaber'] events = [{ 'id': 11450, @@ -142,7 +147,7 @@ elif args.bgloop: }] else: - events = list(renderlib.events(args.schedule)) + events = list(schedulelib.events(args.schedule)) def describe_event(event): @@ -217,13 +222,14 @@ def enqueue_job(event): for key, value in event.items(): value = str(value).replace('"', '\\"') scriptstr = scriptstr.replace("$" + str(key), value) - + with open(work_doc, 'w', encoding='utf-8') as fp: fp.write(scriptstr) - + if platform.system() == 'Darwin': if args.debug: - print("running: Blender.app --background %s --python-use-system-env --python %s --use-extension 0 --threads 0 --render-output %s --render-anim" % (work_source, work_doc, intermediate_clip)) + print("running: Blender.app --background %s --python-use-system-env --python %s --use-extension 0 --threads 0 --render-output %s --render-anim" % + (work_source, work_doc, intermediate_clip)) run(r'/Applications/Blender.app/Contents/MacOS/Blender --background {source} --python-use-system-env --python {jobpath} --use-extension 0 --threads 0 --render-output {locationpath} --render-anim', source=work_source, jobpath=work_doc, @@ -231,14 +237,16 @@ def enqueue_job(event): if platform.system() == 'Windows': if args.debug: - print("running: blender.exe --background %s --python-use-system-env --python %s --use-extension 0 --threads 0 --render-output %s --render-anim" % (work_source, work_doc, intermediate_clip)) + print("running: blender.exe --background %s --python-use-system-env --python %s --use-extension 0 --threads 0 --render-output %s --render-anim" % + (work_source, work_doc, intermediate_clip)) run(r'C:/Program\ Files/Blender\ Foundation/Blender\ 2.92/blender.exe --background {source} --python-use-system-env --python {jobpath} --use-extension 0 --threads 0 --render-output {locationpath} --render-anim', source=work_source, jobpath=work_doc, locationpath=intermediate_clip) if platform.system() == 'Linux': if args.debug: - print("running: blender --background %s --python-use-system-env --python %s --use-extension 0 --threads 0 --render-output %s --render-anim" % (work_source, work_doc, intermediate_clip)) + print("running: blender --background %s --python-use-system-env --python %s --use-extension 0 --threads 0 --render-output %s --render-anim" % + (work_source, work_doc, intermediate_clip)) run(r'blender --background {source} --python-use-system-env --python {jobpath} --use-extension 0 --threads 0 --render-output {locationpath} --render-anim', source=work_source, jobpath=work_doc, @@ -256,7 +264,7 @@ def finalize_job(job_id, event): if args.alpha: ffprobe = run_output('ffprobe -i {input} -show_streams -select_streams a -loglevel error', - input=intermediate_clip) + input=intermediate_clip) if ffprobe: run('ffmpeg -threads 0 -y -hide_banner -loglevel error -i {input} -c:v qtrle -movflags faststart -aspect 16:9 -c:a mp2 -b:a 384k -shortest -f mov {output}', input=intermediate_clip, @@ -267,7 +275,7 @@ def finalize_job(job_id, event): output=final_clip) else: ffprobe = run_output('ffprobe -i {input} -show_streams -select_streams a -loglevel error', - input=intermediate_clip) + input=intermediate_clip) if ffprobe: event_print(event, "finalize with audio from source file") run('ffmpeg -threads 0 -y -hide_banner -loglevel error -i {input} -c:v mpeg2video -q:v 2 -aspect 16:9 -c:a mp2 -b:a 384k -shortest -f mpegts {output}', @@ -330,8 +338,8 @@ for event in events: intermediate_clip = os.path.join(tempdir.name, event_id + '.avi') final_clip = os.path.join(os.path.dirname(args.project), event_id + '.avi') else: - intermediate_clip = os.path.join(tempdir.name, event_id + '.mov') - final_clip = os.path.join(os.path.dirname(args.project), event_id + '.mov') + intermediate_clip = os.path.join(tempdir.name, event_id + '.mkv') + final_clip = os.path.join(os.path.dirname(args.project), event_id + '.mkv') copyfile(intermediate_clip, final_clip) event_print(event, "copied intermediate clip to " + final_clip) diff --git a/make-ffmpeg-fade.py b/make-ffmpeg-fade.py index 6f1e98b..3c1eecd 100755 --- a/make-ffmpeg-fade.py +++ b/make-ffmpeg-fade.py @@ -1,325 +1,5 @@ #!/usr/bin/env python3 # vim: tabstop=4 shiftwidth=4 expandtab -import os -import sys -import subprocess -import renderlib -import argparse -import shlex -from PIL import ImageFont -from configparser import ConfigParser -import json - -# Parse arguments -parser = argparse.ArgumentParser( - description='C3VOC Intro-Outro-Generator - Variant which renders only using video filters in ffmpeg', - usage="./make-ffmpeg.py yourproject/", - formatter_class=argparse.RawTextHelpFormatter) - -parser.add_argument('project', action="store", metavar='Project folder', type=str, help=''' - Path to your project folder - ''') - -parser.add_argument('--debug', action="store_true", default=False, help=''' - Run script in debug mode and render with placeholder texts, - not parsing or accessing a schedule. - This argument must not be used together with --id - Usage: ./make-ffmpeg.py yourproject/ --debug - ''') - -parser.add_argument('--id', dest='ids', nargs='+', action="store", type=int, help=''' - Only render the given ID(s) from your projects schedule. - This argument must not be used together with --debug - Usage: ./make-adobe-after-effects.py yourproject/ --id 4711 0815 4223 1337 - ''') - -parser.add_argument('--room', dest='rooms', nargs='+', action="store", type=str, help=''' - Only render the given room(s) from your projects schedule. - This argument must not be used together with --debug - Usage: ./make-adobe-after-effects.py yourproject/ --room "HfG_Studio" "ZKM_Vortragssaal" - ''') - -parser.add_argument('--skip', nargs='+', action="store", type=str, help=''' - Skip ID(s) not needed to be rendered. - Usage: ./make-ffmpeg.py yourproject/ --skip 4711 0815 4223 1337 - ''') - -parser.add_argument('--force', action="store_true", default=False, help=''' - Force render if file exists. - ''') - -args = parser.parse_args() - -if (args.skip is None): - args.skip = [] - - -def headline(str): - print("##################################################") - print(str) - print("##################################################") - print() - - -def error(str): - headline(str) - parser.print_help() - sys.exit(1) - -cparser = ConfigParser() -cparser.read(os.path.join(os.path.dirname(args.project), 'config.ini')) -template = cparser['default']['template'] -alpha = cparser['default']['alpha'] -prores = cparser['default']['prores'] - -fade_duration = 0.5 - -title_in = float(cparser['title']['in']) -title_out = float(cparser['title']['out']) -title_duration = title_out - title_in -title_font = cparser['title']['font'] -title_fontsize = int(cparser['title']['fontsize']) -title_fontcolor = cparser['title']['fontcolor'] -title_x = int(cparser['title']['x']) -title_y = int(cparser['title']['y']) - -speaker_in = float(cparser['speaker']['in']) -speaker_out = float(cparser['speaker']['out']) -speaker_duration = speaker_out - speaker_in -speaker_font = cparser['speaker']['font'] -speaker_fontsize = int(cparser['speaker']['fontsize']) -speaker_fontcolor = cparser['speaker']['fontcolor'] -speaker_x = int(cparser['speaker']['x']) -speaker_y = int(cparser['speaker']['y']) - -text_in = float(cparser['text']['in']) -text_out = float(cparser['text']['out']) -text_duration = text_out - text_in -text_font = cparser['text']['font'] -text_fontsize = int(cparser['text']['fontsize']) -text_fontcolor = cparser['text']['fontcolor'] -text_x = int(cparser['text']['x']) -text_y = int(cparser['text']['y']) -text_text = cparser['text']['text'] - -font_t = os.path.join(os.path.dirname(args.project), title_font) -font_s = os.path.join(os.path.dirname(args.project), speaker_font) -font_tt = os.path.join(os.path.dirname(args.project), text_font) - -fileformat = os.path.splitext(template)[1] -infile = os.path.join(os.path.dirname(args.project), template) - -schedule = cparser['default']['schedule'] - -if not (os.path.exists(os.path.join(args.project, template))): - error("Template file {} in Project Path is missing".format(template)) - -for ffile in (title_font, speaker_font, text_font): - if not (os.path.exists(os.path.join(args.project, ffile))): - error("Font file {} in Project Path is missing".format(ffile)) - -if not (os.path.exists(os.path.join(args.project, 'config.ini'))): - error("config.ini file in Project Path is missing") - -if alpha == 'true' and not fileformat == '.mov': - error("Alpha can only be rendered with .mov source files") - -if not args.project: - error("The Project Path is a required argument") - -if not args.debug and not schedule: - error("Either specify --debug or supply a schedule in config.ini") - -if args.debug: - persons = ['Thomas Roth', 'Dmitry Nedospasov', 'Josh Datko'] - events = [{ - 'id': 'debug', - 'title': 'wallet.fail', - 'subtitle': 'Hacking the most popular cryptocurrency hardware wallets', - 'persons': persons, - 'personnames': ', '.join(persons), - 'room': 'Borg', - }] - -else: - events = list(renderlib.events(schedule)) - -def describe_event(event): - return "#{}: {}".format(event['id'], event['title']) - - -def event_print(event, message): - print("{} – {}".format(describe_event(event), message)) - - -def fmt_command(command, **kwargs): - args = {} - for key, value in kwargs.items(): - args[key] = shlex.quote(value) - - command = command.format(**args) - return shlex.split(command) - - -def run(command, **kwargs): - return subprocess.check_call( - fmt_command(command, **kwargs), - stderr=subprocess.STDOUT, - stdout=subprocess.DEVNULL) - - -def fit_text(string: str, frame_width): - split_line = [x.strip() for x in string.split()] - lines = "" - w = 0 - line_num = 0 - line = "" - for word in split_line: - w, _ = translation_font.getsize(" ".join([line, word])) - print("{}, {}".format(w, line)) - if w > (frame_width): - print("too wide, breaking") - lines += line.strip() + "\n" - line = "" - - line += word + " " - - lines += line.strip() - return lines - - -def fit_title(string: str): - global translation_font - translation_font = ImageFont.truetype(font_t, size=title_fontsize-10, encoding="unic") - title = fit_text(string, 1080) - - return title - - -def fit_speaker(string: str): - global translation_font - translation_font = ImageFont.truetype(font_s, size=speaker_fontsize-10, encoding="unic") - speaker = fit_text(string, 1080) - - return speaker - - -def enqueue_job(event): - event_id = str(event['id']) - if event_id in args.skip: - event_print(event, "skipping " + str(event['id'])) - return - if (os.path.exists(os.path.join(args.project, event_id + '.ts')) or os.path.exists(os.path.join(args.project, event_id + '.mov'))) and not args.force: - event_print(event, "file exist, skipping " + str(event['id'])) - return - - event_title = str(event['title']) - event_personnames = str(event['personnames']) - event_title = event_title.replace('"', '') - event_title = event_title.replace('\'', '') - event_personnames = event_personnames.replace('"', '') - - t = fit_title(event_title) - s = fit_speaker(event_personnames) - print(s) - - if args.debug: - print('Title: ', t) - print('Speaker: ', s) - - outfile = os.path.join(os.path.dirname(args.project), event_id + '.ts') - - videofilter = "drawtext=fontfile={fontfile}:fontsize={fontsize}:fontcolor={fontcolor}:x={x}:y={y}:text='{text}':".format( - fontfile = font_t, - fontsize = title_fontsize, - fontcolor = title_fontcolor, - x = title_x, - y = title_y, - text = t) - videofilter += "alpha='if(lt(t,{fade_in_start_time}),0,if(lt(t,{fade_in_end_time}),(t-{fade_in_start_time})/{fade_duration},if(lt(t,{fade_out_start_time}),1,if(lt(t,{fade_out_end_time}),({fade_duration}-(t-{fade_out_start_time}))/{fade_duration},0))))',".format( - fade_in_start_time = title_in, - fade_in_end_time = title_in + fade_duration, - fade_out_start_time = title_in + fade_duration + title_duration, - fade_out_end_time = title_in + fade_duration + title_duration + fade_duration, - fade_duration = fade_duration - ) - videofilter += "drawtext=fontfile={fontfile}:fontsize={fontsize}:fontcolor={fontcolor}:x={x}:y={y}:text='{text}':".format( - fontfile = font_s, - fontsize = speaker_fontsize, - fontcolor = speaker_fontcolor, - x = speaker_x, - y = speaker_y, - text = s) - videofilter += "alpha='if(lt(t,{fade_in_start_time}),0,if(lt(t,{fade_in_end_time}),(t-{fade_in_start_time})/{fade_duration},if(lt(t,{fade_out_start_time}),1,if(lt(t,{fade_out_end_time}),({fade_duration}-(t-{fade_out_start_time}))/{fade_duration},0))))',".format( - fade_in_start_time = speaker_in, - fade_in_end_time = speaker_in + fade_duration, - fade_out_start_time = speaker_in + fade_duration + speaker_duration, - fade_out_end_time = speaker_in + fade_duration + speaker_duration + fade_duration, - fade_duration = fade_duration - ) - videofilter += "drawtext=fontfile={fontfile}:fontsize={fontsize}:fontcolor={fontcolor}:x={x}:y={y}:text={text}:".format( - fontfile = font_tt, - fontsize = text_fontsize, - fontcolor = text_fontcolor, - x = text_x, - y = text_y, - text = text_text) - videofilter += "alpha='if(lt(t,{fade_in_start_time}),0,if(lt(t,{fade_in_end_time}),(t-{fade_in_start_time})/{fade_duration},if(lt(t,{fade_out_start_time}),1,if(lt(t,{fade_out_end_time}),({fade_duration}-(t-{fade_out_start_time}))/{fade_duration},0))))'".format( - fade_in_start_time = text_in, - fade_in_end_time = text_in + fade_duration, - fade_out_start_time = text_in + fade_duration + text_duration, - fade_out_end_time = text_in + fade_duration + text_duration + fade_duration, - fade_duration = fade_duration - ) - - if fileformat == '.mov': - if alpha == 'true': - if prores == 'true': - cmd = 'ffmpeg -y -i "{0}" -vf "{1}" -vcodec prores_ks -pix_fmt yuva444p10le -profile:v 4444 -shortest -movflags faststart -f mov "{2}"'.format(infile, videofilter, outfile) - else: - cmd = 'ffmpeg -y -i "{0}" -vf "{1}" -shortest -c:v qtrle -movflags faststart -f mov "{2}"'.format(infile, videofilter, outfile) - else: - cmd = 'ffmpeg -y -i "{0}" -vf "{1}" -map 0:0 -c:v mpeg2video -q:v 2 -aspect 16:9 -map 0:1 -c:a mp2 -b:a 384k -shortest -f mpegts "{2}"'.format(infile, videofilter, outfile) - else: - cmd = 'ffmpeg -y -i "{0}" -vf "{1}" -map 0:0 -c:v mpeg2video -pix_fmt:v yuv420p -qscale:v 2 -qmin:v 2 -qmax:v 7 -keyint_min 0 -bf 0 -g 0 -intra:0 -maxrate:0 90M -aspect 16:9 -map 0:1 -c:a mp2 -b:a 384k -shortest -f mpegts "{2}"'.format(infile, videofilter, outfile) - - if args.debug: - print(cmd) - - run(cmd) - - return event_id - - -if args.ids: - if len(args.ids) == 1: - print("enqueuing {} job".format(len(args.ids))) - else: - print("enqueuing {} jobs".format(len(args.ids))) -else: - if len(events) == 1: - print("enqueuing {} job".format(len(events))) - else: - print("enqueuing {} jobs".format(len(events))) - - -for event in events: - if args.ids and event['id'] not in args.ids: - continue - - if args.rooms and event['room'] not in args.rooms: - print("skipping room %s (%s)" % (event['room'], event['title'])) - continue - - event_print(event, "enqueued as " + str(event['id'])) - - job_id = enqueue_job(event) - if not job_id: - event_print(event, "job was not enqueued successfully, skipping postprocessing") - continue - - -print('all done') - - +print("ERROR: The functionality of this script was added to 'make-ffmpeg.py'!") +print("Specify meta.fade_duration = 0.5 in the config.ini for the same effect.") diff --git a/make-ffmpeg.py b/make-ffmpeg.py index 87b591e..94d1514 100755 --- a/make-ffmpeg.py +++ b/make-ffmpeg.py @@ -1,144 +1,166 @@ #!/usr/bin/env python3 # vim: tabstop=4 shiftwidth=4 expandtab +"""See jugendhackt/config.ini for some config file documentation.""" + import os import sys import subprocess -import renderlib import argparse -import shlex -from PIL import ImageFont +import ssl from configparser import ConfigParser -import json +from pathlib import PurePath +import platform -# Parse arguments -parser = argparse.ArgumentParser( - description='C3VOC Intro-Outro-Generator - Variant which renders only using video filters in ffmpeg', - usage="./make-ffmpeg.py yourproject/", - formatter_class=argparse.RawTextHelpFormatter) +from PIL import ImageFont +import schedulelib +ssl._create_default_https_context = ssl._create_unverified_context -parser.add_argument('project', action="store", metavar='Project folder', type=str, help=''' - Path to your project folder - ''') - -parser.add_argument('--debug', action="store_true", default=False, help=''' - Run script in debug mode and render with placeholder texts, - not parsing or accessing a schedule. - This argument must not be used together with --id - Usage: ./make-ffmpeg.py yourproject/ --debug - ''') - -parser.add_argument('--id', dest='ids', nargs='+', action="store", type=int, help=''' - Only render the given ID(s) from your projects schedule. - This argument must not be used together with --debug - Usage: ./make-adobe-after-effects.py yourproject/ --id 4711 0815 4223 1337 - ''') - -parser.add_argument('--room', dest='rooms', nargs='+', action="store", type=str, help=''' - Only render the given room(s) from your projects schedule. - This argument must not be used together with --debug - Usage: ./make-adobe-after-effects.py yourproject/ --room "HfG_Studio" "ZKM_Vortragssaal" - ''') - -parser.add_argument('--skip', nargs='+', action="store", type=str, help=''' - Skip ID(s) not needed to be rendered. - Usage: ./make-ffmpeg.py yourproject/ --skip 4711 0815 4223 1337 - ''') - -parser.add_argument('--force', action="store_true", default=False, help=''' - Force render if file exists. - ''') - -args = parser.parse_args() - -if (args.skip is None): - args.skip = [] +FRAME_WIDTH = 1920 -def headline(str): - print("##################################################") - print(str) - print("##################################################") - print() +class TextConfig: + inpoint: float + outpoint: float + x: int + y: int + + fontfile_path: str + fontsize: int + fontcolor: str + bordercolor: str = None # border is added, if a color is set + + def uses_fontfile(self): + return self.fontfile_path is not None + + def parse(self, cparser_sect, default_fontfile, default_fontcolor): + self.inpoint = cparser_sect.getfloat('in') + self.outpoint = cparser_sect.getfloat('out') + self.x = cparser_sect.getint('x') + self.y = cparser_sect.getint('y') + + self.fontcolor = cparser_sect.get('fontcolor', default_fontcolor) + + fontfile = cparser_sect.get('fontfile', default_fontfile) + self.fontfile_path = str(PurePath(args.project, fontfile).as_posix()) + + if not os.path.exists(self.fontfile_path): + error("Font file {} in Project Path is missing".format(self.fontfile_path)) + + self.fontsize = cparser_sect.getint('fontsize') + self.bordercolor = cparser_sect.get('bordercolor', None) + + def fit_text(self, text: str) -> list[str]: + if not text: + return [""] + + font = ImageFont.truetype( + self.fontfile_path, size=self.fontsize, encoding="unic") + + return fit_text(text, (FRAME_WIDTH-self.x-100), font) + + def get_ffmpeg_filter(self, inout_type: str, fade_time: float, text: list[str]): + if not text: + return "" + + text_duration = self.outpoint - self.inpoint + filter_str = "" + for idx, line in enumerate(text): + filter_str += "drawtext=enable='between({},{},{})':x={}:y={}".format( + inout_type, self.inpoint, self.outpoint, self.x, self.y + (idx*self.fontsize)) + + filter_str += ":fontfile='{}':fontsize={}:fontcolor={}:text={}".format( + self.fontfile_path, self.fontsize, self.fontcolor, ffmpeg_escape_str(line)) + + if self.bordercolor is not None: + filter_str += ":borderw={}:bordercolor={}".format( + self.fontsize / 30, self.bordercolor) + + if fade_time > 0: + filter_str += ":alpha='if(lt(t,{fade_in_start_time}),0,if(lt(t,{fade_in_end_time}),(t-{fade_in_start_time})/{fade_duration},if(lt(t,{fade_out_start_time}),1,if(lt(t,{fade_out_end_time}),({fade_duration}-(t-{fade_out_start_time}))/{fade_duration},0))))'".format( + fade_in_start_time=self.inpoint, + fade_in_end_time=self.inpoint + fade_time, + fade_out_start_time=self.inpoint + fade_time + text_duration, + fade_out_end_time=self.inpoint + fade_time + text_duration + fade_time, + fade_duration=fade_time) + + filter_str += "," + + return filter_str[:-1] -def error(str): - headline(str) - parser.print_help() - sys.exit(1) +class Config: + schedule: str + template_file: str # video background + alpha: bool = False + prores: bool = False + inout_type: str = "t" # in and out time format: t for seconds, n for frame number + fade_duration: float = 0 # fade duration in seconds, 0 to disable -cparser = ConfigParser() -cparser.read(os.path.join(os.path.dirname(args.project), 'config.ini')) -template = cparser['default']['template'] -alpha = cparser['default']['alpha'] -prores = cparser['default']['prores'] + fileext: str -title_in = cparser['title']['in'] -title_out = cparser['title']['out'] -title_font = cparser['title']['font'] -title_fontsize = cparser['title']['fontsize'] -title_fontcolor = cparser['title']['fontcolor'] -title_x = cparser['title']['x'] -title_y = cparser['title']['y'] + title: TextConfig + speaker: TextConfig + text: TextConfig + extra_text: str = "" # additional text -speaker_in = cparser['speaker']['in'] -speaker_out = cparser['speaker']['out'] -speaker_font = cparser['speaker']['font'] -speaker_fontsize = cparser['speaker']['fontsize'] -speaker_fontcolor = cparser['speaker']['fontcolor'] -speaker_x = cparser['speaker']['x'] -speaker_y = cparser['speaker']['y'] -text_in = cparser['text']['in'] -text_out = cparser['text']['out'] -text_font = cparser['text']['font'] -text_fontsize = cparser['text']['fontsize'] -text_fontcolor = cparser['text']['fontcolor'] -text_x = cparser['text']['x'] -text_y = cparser['text']['y'] -text_text = cparser['text']['text'] +def parse_config(filename) -> Config: + if not os.path.exists(filename): + error("config.ini file in Project Path is missing") -font_t = os.path.join(os.path.dirname(args.project), title_font) -font_s = os.path.join(os.path.dirname(args.project), speaker_font) -font_tt = os.path.join(os.path.dirname(args.project), text_font) + conf = Config() -fileformat = os.path.splitext(template)[1] -infile = os.path.join(os.path.dirname(args.project), template) + cparser = ConfigParser() + cparser.read(filename) -schedule = cparser['default']['schedule'] + meta = cparser['meta'] + conf.schedule = meta.get('schedule') + infile = PurePath(args.project, meta.get('template')) + conf.template_file = str(infile) + conf.alpha = meta.getboolean('alpha', conf.alpha) + conf.prores = meta.getboolean('prores', conf.prores) + conf.inout_type = meta.get('inout_type', conf.inout_type) + conf.fade_duration = meta.getfloat('fade_duration', conf.fade_duration) -if not (os.path.exists(os.path.join(args.project, template))): - error("Template file {} in Project Path is missing".format(template)) + defaults = cparser['default'] + default_fontfile = defaults.get('fontfile', None) + default_fontcolor = defaults.get('fontcolor', "#ffffff") -for ffile in (title_font, speaker_font, text_font): - if not (os.path.exists(os.path.join(args.project, ffile))): - error("Font file {} in Project Path is missing".format(ffile)) + conf.title = TextConfig() + conf.title.parse(cparser['title'], default_fontfile, default_fontcolor) + conf.speaker = TextConfig() + conf.speaker.parse(cparser['speaker'], default_fontfile, default_fontcolor) + conf.text = TextConfig() + conf.text.parse(cparser['text'], default_fontfile, default_fontcolor) -if not (os.path.exists(os.path.join(args.project, 'config.ini'))): - error("config.ini file in Project Path is missing") + conf.extra_text = cparser['text'].get('text', '') -if alpha == 'true' and not fileformat == '.mov': - error("Alpha can only be rendered with .mov source files") + conf.fileext = infile.suffix -if not args.project: - error("The Project Path is a required argument") + if not os.path.exists(conf.template_file): + error("Template file {} in Project Path is missing".format(conf.template_file)) -if not args.debug and not schedule: - error("Either specify --debug or supply a schedule in config.ini") + if conf.alpha and conf.fileext != '.mov': + error("Alpha can only be rendered with .mov source files") -if args.debug: - persons = ['Thomas Roth', 'Dmitry Nedospasov', 'Josh Datko'] - events = [{ - 'id': 'debug', - 'title': 'wallet.fail', - 'subtitle': 'Hacking the most popular cryptocurrency hardware wallets', - 'persons': persons, - 'personnames': ', '.join(persons), - 'room': 'Borg', - }] + if not args.project: + error("The Project Path is a required argument") + + if not args.debug and not conf.schedule: + error("Either specify --debug or supply a schedule in config.ini") + + return conf + + +def error(err_str): + print("##################################################") + print(err_str) + print("##################################################") + print() + parser.print_help() + sys.exit(1) -else: - events = list(renderlib.events(schedule)) def describe_event(event): return "#{}: {}".format(event['id'], event['title']) @@ -148,133 +170,184 @@ def event_print(event, message): print("{} – {}".format(describe_event(event), message)) -def fmt_command(command, **kwargs): - args = {} - for key, value in kwargs.items(): - args[key] = shlex.quote(value) +def fit_text(string: str, max_width: int, font: ImageFont) -> list[str]: + """Break text into array of strings which fit certain a width (in pixels) for the specified font.""" - command = command.format(**args) - return shlex.split(command) - - -def run(command, **kwargs): - return subprocess.check_call( - fmt_command(command, **kwargs), - stderr=subprocess.STDOUT, - stdout=subprocess.DEVNULL) - - -def fit_text(string: str, frame_width): split_line = [x.strip() for x in string.split()] - lines = "" + lines = [] w = 0 - line_num = 0 - line = "" + line = [] for word in split_line: - w, _ = translation_font.getsize(" ".join([line, word])) - if w > (frame_width - (2 * 6)): - lines += line.strip() + "\n" - line = "" + new_line = line + [word.rstrip(':')] + w = font.getlength(" ".join(new_line)) + if w > max_width: + lines.append(' '.join(line)) + line = [] - line += word + " " + line.append(word.rstrip(':')) + + if word.endswith(':'): + lines.append(' '.join(line)) + line = [] + + if line: + lines.append(' '.join(line)) - lines += line.strip() return lines -def fit_title(string: str): - global translation_font - translation_font = ImageFont.truetype( - font_t, size=80, encoding="unic") - title = fit_text(string, 1080) +def ffmpeg_escape_str(text: str) -> str: + # Escape according to https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping + # and don't put the string in quotes afterwards! + text = text.replace(",", r"\,") + text = text.replace(':', r"\\:") + text = text.replace("'", r"\\\'") - return title + return text -def fit_speaker(string: str): - global translation_font - translation_font = ImageFont.truetype( - font_s, size=50, encoding="unic") - speaker = fit_text(string, 1080) - - return speaker - - -def enqueue_job(event): +def enqueue_job(conf: Config, event): event_id = str(event['id']) + + outfile = str(PurePath(args.project, event_id + '.ts')) + outfile_mov = str(PurePath(args.project, event_id + '.mov')) + if event_id in args.skip: event_print(event, "skipping " + str(event['id'])) return - if (os.path.exists(os.path.join(args.project, event_id + '.ts')) or os.path.exists(os.path.join(args.project, event_id + '.mov'))) and not args.force: + if (os.path.exists(outfile) or os.path.exists(outfile_mov)) and not args.force: event_print(event, "file exist, skipping " + str(event['id'])) return event_title = str(event['title']) event_personnames = str(event['personnames']) - event_title = event_title.replace('"', '') - event_title = event_title.replace('\'', '') - event_personnames = event_personnames.replace('"', '') - t = fit_title(event_title) - s = fit_speaker(event_personnames) + title = conf.title.fit_text(event_title) + speakers = conf.speaker.fit_text(event_personnames) + extra_text = conf.text.fit_text(conf.extra_text) if args.debug: - print('Title: ', t) - print('Speaker: ', s) + print('Title: ', title) + print('Speaker: ', speakers) - outfile = os.path.join(os.path.dirname(args.project), event_id + '.ts') - - videofilter = "drawtext=enable='between(n,{0},{1})':fontfile={2}:fontsize={3}:fontcolor={4}:x={5}:y={6}:text='{7}',".format(title_in, title_out, font_t, title_fontsize, title_fontcolor, title_x, title_y, t) - videofilter += "drawtext=enable='between(n,{0},{1})':fontfile={2}:fontsize={3}:fontcolor={4}:x={5}:y={6}:text='{7}',".format(speaker_in, speaker_out, font_s, speaker_fontsize, speaker_fontcolor, speaker_x, speaker_y, s) - videofilter += "drawtext=enable='between(n,{0},{1})':fontfile={2}:fontsize={3}:fontcolor={4}:x={5}:y={6}:text={7}".format(text_in, text_out, font_tt, text_fontsize, text_fontcolor, text_x, text_y, text_text) - - if fileformat == '.mov': - if alpha == 'true': - if prores == 'true': - cmd = 'ffmpeg -y -i "{0}" -vf "{1}" -vcodec prores_ks -pix_fmt yuva444p10le -profile:v 4444 -shortest -movflags faststart -f mov "{2}"'.format(infile, videofilter, outfile) - else: - cmd = 'ffmpeg -y -i "{0}" -vf "{1}" -shortest -c:v qtrle -movflags faststart -f mov "{2}"'.format(infile, videofilter, outfile) - else: - cmd = 'ffmpeg -y -i "{0}" -vf "{1}" -map 0:0 -c:v mpeg2video -q:v 2 -aspect 16:9 -map 0:1 -c:a mp2 -b:a 384k -shortest -f mpegts "{2}"'.format(infile, videofilter, outfile) + if platform.system() == 'Windows': + ffmpeg_path = './ffmpeg.exe' else: - cmd = 'ffmpeg -y -i "{0}" -vf "{1}" -map 0:0 -c:v mpeg2video -q:v 2 -aspect 16:9 -map 0:1 -c:a mp2 -b:a 384k -shortest -f mpegts "{2}"'.format(infile, videofilter, outfile) + ffmpeg_path = 'ffmpeg' + + videofilter = conf.title.get_ffmpeg_filter(conf.inout_type, conf.fade_duration, title) + "," + videofilter += conf.speaker.get_ffmpeg_filter(conf.inout_type, + conf.fade_duration, speakers) + "," + videofilter += conf.text.get_ffmpeg_filter(conf.inout_type, conf.fade_duration, extra_text) + + cmd = [ffmpeg_path, '-y', '-i', conf.template_file, '-vf', videofilter] + + if conf.fileext == '.mov' and conf.alpha: + if conf.prores: + cmd += ['-vcodec', 'prores_ks', '-pix_fmt', 'yuva444p10le', '-profile:v', + '4444', '-shortest', '-movflags', 'faststart', '-f', 'mov', outfile_mov] + else: + cmd += ['-shortest', '-c:v', 'qtrle', '-movflags', + 'faststart', '-f', 'mov', outfile_mov] + else: + cmd += ['-map', '0:0', '-c:v', 'mpeg2video', '-q:v', '2', '-aspect', '16:9', '-map', + '0:1', '-c:a', 'mp2', '-b:a', '384k', '-shortest', '-f', 'mpegts', outfile] if args.debug: print(cmd) - run(cmd) + subprocess.check_call(cmd, + stderr=subprocess.STDOUT, + stdout=subprocess.DEVNULL + ) return event_id -if args.ids: - if len(args.ids) == 1: - print("enqueuing {} job".format(len(args.ids))) +if __name__ == "__main__": + # Parse arguments + parser = argparse.ArgumentParser( + description='C3VOC Intro-Outro-Generator - Variant which renders only using video filters in ffmpeg', + usage="./make-ffmpeg.py yourproject/", + formatter_class=argparse.RawTextHelpFormatter) + + parser.add_argument('project', action="store", metavar='Project folder', type=str, help=''' + Path to your project folder + ''') + + parser.add_argument('--debug', action="store_true", default=False, help=''' + Run script in debug mode and render with placeholder texts, + not parsing or accessing a schedule. + This argument must not be used together with --id + Usage: ./make-ffmpeg.py yourproject/ --debug + ''') + + parser.add_argument('--id', dest='ids', nargs='+', action="store", type=int, help=''' + Only render the given ID(s) from your projects schedule. + This argument must not be used together with --debug + Usage: ./make-adobe-after-effects.py yourproject/ --id 4711 0815 4223 1337 + ''') + + parser.add_argument('--room', dest='rooms', nargs='+', action="store", type=str, help=''' + Only render the given room(s) from your projects schedule. + This argument must not be used together with --debug + Usage: ./make-adobe-after-effects.py yourproject/ --room "HfG_Studio" "ZKM_Vortragssaal" + ''') + + parser.add_argument('--skip', nargs='+', action="store", type=str, help=''' + Skip ID(s) not needed to be rendered. + Usage: ./make-ffmpeg.py yourproject/ --skip 4711 0815 4223 1337 + ''') + + parser.add_argument('--force', action="store_true", default=False, help=''' + Force render if file exists. + ''') + + args = parser.parse_args() + + if (args.skip is None): + args.skip = [] + + config = parse_config(PurePath(args.project, 'config.ini')) + + if args.debug: + persons = ['Thomas Roth', 'Dmitry Nedospasov', 'Josh Datko',] + events = [{ + 'id': 'debug', + 'title': 'wallet.fail and the longest talk title to test if the template is big enough', + 'subtitle': 'Hacking the most popular cryptocurrency hardware wallets', + 'persons': persons, + 'personnames': ', '.join(persons), + 'room': 'Borg', + }] + else: - print("enqueuing {} jobs".format(len(args.ids))) -else: - if len(events) == 1: - print("enqueuing {} job".format(len(events))) + events = list(schedulelib.events(config.schedule)) + + if args.ids: + if len(args.ids) == 1: + print("enqueuing {} job".format(len(args.ids))) + else: + print("enqueuing {} jobs".format(len(args.ids))) else: - print("enqueuing {} jobs".format(len(events))) + if len(events) == 1: + print("enqueuing {} job".format(len(events))) + else: + print("enqueuing {} jobs".format(len(events))) + for event in events: + if args.ids and event['id'] not in args.ids: + continue -for event in events: - if args.ids and event['id'] not in args.ids: - continue + if args.rooms and event['room'] not in args.rooms: + print("skipping room %s (%s)" % (event['room'], event['title'])) + continue - if args.rooms and event['room'] not in args.rooms: - print("skipping room %s (%s)" % (event['room'], event['title'])) - continue - - event_print(event, "enqueued as " + str(event['id'])) - - job_id = enqueue_job(event) - if not job_id: - event_print(event, "job was not enqueued successfully, skipping postprocessing") - continue - - -print('all done') + event_print(event, "enqueued as " + str(event['id'])) + job_id = enqueue_job(config, event) + if not job_id: + event_print(event, "job was not enqueued successfully, skipping postprocessing") + continue + print('all done') diff --git a/make.py b/make.py index 6c0834c..6f5e3f7 100755 --- a/make.py +++ b/make.py @@ -14,7 +14,8 @@ import renderlib import argparse # Parse arguments -parser = argparse.ArgumentParser(description='C3VOC Intro-Outro-Generator', usage="see help with option -h", formatter_class=argparse.RawTextHelpFormatter) +parser = argparse.ArgumentParser(description='C3VOC Intro-Outro-Generator', + usage="see help with option -h", formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('projectpath', action="store", metavar='yourproject/', type=str, help=''' Path to your project is a required argument. Usage: ./make.py yourproject/ @@ -87,7 +88,8 @@ projectpath = args.projectpath try: project = renderlib.loadProject(projectname) except ImportError: - print("you must specify a project-name as first argument, eg. './make.py sotmeu14'. The supplied value '{0}' seems not to be a valid project (there is no '{0}/__init__.py').\n".format(projectname)) + print( + "you must specify a project-name as first argument, eg. './make.py sotmeu14'. The supplied value '{0}' seems not to be a valid project (there is no '{0}/__init__.py').\n".format(projectname)) raise # using --debug skips the threading, the network fetching of the schedule and @@ -98,7 +100,8 @@ renderlib.args = args def render(infile, outfile, sequence, parameters={}, workdir=os.path.join(projectname, 'artwork')): - task = renderlib.Rendertask(infile=infile, outfile=outfile, sequence=sequence, parameters=parameters, workdir=workdir) + task = renderlib.Rendertask(infile=infile, outfile=outfile, + sequence=sequence, parameters=parameters, workdir=workdir) return renderlib.rendertask(task) @@ -188,7 +191,8 @@ def worker(): renderlib.rendertask(task) # print that we're finished - tprint('finished {0}, {1} tasks left'.format(task.outfile, max(0, tasks.qsize() - num_worker_threads))) + tprint('finished {0}, {1} tasks left'.format( + task.outfile, max(0, tasks.qsize() - num_worker_threads))) # mark the task as finished tasks.task_done() diff --git a/minilac16/__init__.py b/minilac16/__init__.py index 3223ab9..645adea 100644 --- a/minilac16/__init__.py +++ b/minilac16/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * from lxml import etree @@ -62,7 +63,7 @@ def tasks(queue, args): def tasks(queue, args): # iterate over all events extracted from the schedule xml-export for event in events(scheduleUrl): - if event['room'] not in ('Seminar room', 'Soundlab', 'Mainhall'): + if event['room'] not in ('Seminar room', 'Soundlab', 'Mainhall'): print("skipping room %s (%s)" % (event['room'], event['title'])) continue diff --git a/mrmcd2014/__init__.py b/mrmcd2014/__init__.py index ca4a209..85a1643 100644 --- a/mrmcd2014/__init__.py +++ b/mrmcd2014/__init__.py @@ -3,6 +3,7 @@ import svg.path, random from lxml import etree from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'http://fahrplan.mrmcd.net/schedule.xml' diff --git a/mrmcd2016/__init__.py b/mrmcd2016/__init__.py index 6078795..f8d1d5b 100644 --- a/mrmcd2016/__init__.py +++ b/mrmcd2016/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/mrmcd2017/__init__.py b/mrmcd2017/__init__.py index 979968b..10022b4 100755 --- a/mrmcd2017/__init__.py +++ b/mrmcd2017/__init__.py @@ -2,6 +2,7 @@ import subprocess from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/mrmcd2019/config.ini b/mrmcd2019/config.ini index 5c02e73..fb74efc 100755 --- a/mrmcd2019/config.ini +++ b/mrmcd2019/config.ini @@ -1,12 +1,15 @@ -[default] +[meta] #schedule = https://talks.mrmcd.net/2019/schedule/export/schedule.xml schedule = file:///home/thorti/git/c3voc/intro-outro-generator/mrmcd2019/schedule.xml template = mrmcd2019.mov +alpha = false +prores = false +inout_type = n [title] in = 50 out = 225 -font = Jura-Bold.ttf +fontfile = Jura-Bold.ttf fontsize = 80 fontcolor = #47acda x = (w-text_w)/2 @@ -15,7 +18,7 @@ y = 540 [speaker] in = 75 out = 225 -font = Jura-Regular.ttf +fontfile = Jura-Regular.ttf fontsize = 50 fontcolor = #094762 x = (w-text_w)/2 @@ -24,9 +27,9 @@ y = 950 [text] in = 242 out = 324 -font = Jura-Regular.ttf +fontfile = Jura-Regular.ttf fontsize = 45 fontcolor = #c68100 x = (w-text_w)/2 y = 927 -text = '' +; text = diff --git a/nixcon2015/__init__.py b/nixcon2015/__init__.py index 55be336..1c73ae0 100644 --- a/nixcon2015/__init__.py +++ b/nixcon2015/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * import math diff --git a/occ16/__init__.py b/occ16/__init__.py index d31e87f..1ac16f5 100644 --- a/occ16/__init__.py +++ b/occ16/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/occon18/__init__.py b/occon18/__init__.py index 6731e9d..f0e9636 100644 --- a/occon18/__init__.py +++ b/occon18/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/osc16/__init__.py b/osc16/__init__.py index 6675c13..b486f28 100644 --- a/osc16/__init__.py +++ b/osc16/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/osc16_dv/__init__.py b/osc16_dv/__init__.py index 356c00d..36d4200 100644 --- a/osc16_dv/__init__.py +++ b/osc16_dv/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/osc17/__init__.py b/osc17/__init__.py index 62b1027..e9c8782 100644 --- a/osc17/__init__.py +++ b/osc17/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/osc18/__init__.py b/osc18/__init__.py index 7151a21..4adff85 100644 --- a/osc18/__init__.py +++ b/osc18/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/osc19/__init__.py b/osc19/__init__.py index e3ca75b..145a639 100644 --- a/osc19/__init__.py +++ b/osc19/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/osc21/__init__.py b/osc21/__init__.py new file mode 100644 index 0000000..ae4b4f8 --- /dev/null +++ b/osc21/__init__.py @@ -0,0 +1,149 @@ +#!/usr/bin/python + +from renderlib import * +from easing import * + +# URL to Schedule-XML +scheduleUrl = 'https://events.opensuse.org/conferences/oSVC21/schedule.xml' + +def bounce(i, min, max, frames): + if i == frames - 1: + return 0 + + if i <= frames/2: + return easeInOutQuad(i, min, max, frames/2) + else: + return max - easeInOutQuad(i - frames/2, min, max, frames/2) + +def introFrames(parameters): + # 3 Sekunde Text Fadein + frames = 1*fps + for i in range(0, frames): + yield ( + ('textblock', 'style', 'opacity', "%.4f" % easeLinear(i, 0, 1, frames)), + ) + + # 4 Sekunden stehen lassen + frames = 4*fps + for i in range(0, frames): + yield () + + # 1 Sekunde Fade to black layer + frames = 1*fps + for i in range(0, frames): + yield ( + ('fadeout', 'style', 'opacity', "%.4f" % easeLinear(i, 0, 1, frames)), + ) + +def pauseFrames(parameters): + frames = 15*fps + colors = ['#21A4D4', '#73BA25', '#6DA741', '#35B9AB', '#00A489', '#173F4F'] + for i in range(0, len(colors)): + z = 0 + for z in range(0,round(frames/4)): + yield ( + ('pausetext', 'attr', 'opacity', '1.0'), + ('sponsors', 'attr', 'opacity', '0.0'), + ('pause_bg_alt', 'style', 'fill', "%s" % colors[i]), + ('pause_bg_alt', 'attr', 'opacity', '%.4f' % easeLinear(z, 0.0, 1, round(frames/4))), + ) + for z in range(0,round(frames/4)): + yield ( + ('pausetext', 'attr', 'opacity', '1.0'), + ('sponsors', 'attr', 'opacity', '0.0'), + ('pause_bg_alt', 'style', 'fill', "%s" % colors[i]), + ('pause_bg_alt', 'attr', 'opacity', '%.4f' % easeLinear(z, 1.0, -1, round(frames/4))), + ) + z=0 + for z in range(0,round(frames/2)): + yield ( + ('pausetext', 'attr', 'opacity', '%.4f' % easeLinear(z, 0.9, -1, round(frames/2))), + ('pause_bg_alt', 'attr', 'opacity', '0.0'), + ('sponsors', 'attr', 'opacity', '%.4f' % easeLinear(z, 0.0, 1, round(frames/2))), + ) + for z in range(0,round(frames/2)): + yield ( + ('pausetext', 'attr', 'opacity', '%.4f' % easeLinear(z, 0.0, 1, round(frames/2))), + ('pause_bg_alt', 'attr', 'opacity', '0.0'), + ('sponsors', 'attr', 'opacity', '%.4f' % easeLinear(z, 0.9, -1, round(frames/2))), + ) + +def outroFrames(p): + # 5 Sekunden stehen bleiben + frames = 5*fps + for i in range(0, frames): + yield [] + +def debug(): +# render( +# 'intro.svg', +# '../intro.ts', +# introFrames, +# { +# '$ID': 4711, +# '$TITLE': "Long Long Long title is LONG", +# '$SUBTITLE': 'Long Long Long Long subtitle is LONGER', +# '$SPEAKER': 'Long Name of Dr. Dr. Prof. Dr. Long Long' +# } +# ) + + render( + 'pause.svg', + '../pause.ts', + pauseFrames + ) + +# render( +# 'infobeamer.svg', +# '../infobeamer.ts', +# pauseFrames +# ) + +# render( +# 'outro.svg', +# '../outro.ts', +# outroFrames +# ) + +def tasks(queue, args, idlist, skiplist): + # iterate over all events extracted from the schedule xml-export + for event in events(scheduleUrl): + if event['room'] not in ('Stage 1', 'Stage 2'): + print("skipping room %s (%s [%s])" % (event['room'], event['title'], event['id'])) + continue + if not (idlist==[]): + if 000000 in idlist: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + if int(event['id']) not in idlist: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + + # generate a task description and put it into the queue + queue.put(Rendertask( + infile = 'intro.svg', + outfile = str(event['id'])+".ts", + sequence = introFrames, + parameters = { + '$ID': event['id'], + '$TITLE': event['title'], + '$SUBTITLE': event['subtitle'], + '$SPEAKER': event['personnames'] + } + )) + + # place a task for the outro into the queue + if not "out" in skiplist: + queue.put(Rendertask( + infile = 'outro.svg', + outfile = 'outro.ts', + sequence = outroFrames + )) + + # place the pause-sequence into the queue + if not "pause" in skiplist: + queue.put(Rendertask( + infile = 'pause.svg', + outfile = 'pause.ts', + sequence = pauseFrames + )) diff --git a/osc21/artwork/hexagons.png b/osc21/artwork/hexagons.png new file mode 100644 index 0000000..0d3b6a1 Binary files /dev/null and b/osc21/artwork/hexagons.png differ diff --git a/osc21/artwork/infobeamer.png b/osc21/artwork/infobeamer.png new file mode 100644 index 0000000..866e893 Binary files /dev/null and b/osc21/artwork/infobeamer.png differ diff --git a/osc21/artwork/infobeamer.svg b/osc21/artwork/infobeamer.svg new file mode 100644 index 0000000..d420efd --- /dev/null +++ b/osc21/artwork/infobeamer.svg @@ -0,0 +1,239 @@ + + + +image/svg+xmlVirtual Conference 2021 + + + + + + + + + + + \ No newline at end of file diff --git a/osc21/artwork/intro.svg b/osc21/artwork/intro.svg new file mode 100644 index 0000000..238f4ac --- /dev/null +++ b/osc21/artwork/intro.svg @@ -0,0 +1,341 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + $TITLE $SUBTITLE $SPEAKER + + openSUSE Virtual Conference 2021 + + + + + diff --git a/osc21/artwork/logo_osc-video.svg b/osc21/artwork/logo_osc-video.svg new file mode 100644 index 0000000..fd4f59b --- /dev/null +++ b/osc21/artwork/logo_osc-video.svg @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + recording by: younameitpostprocessing by: eventuallyhere openSUSE conference 2017Z-Bau, Nuremberg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osc21/artwork/logo_osc-video_preview.png b/osc21/artwork/logo_osc-video_preview.png new file mode 100644 index 0000000..f0b6686 Binary files /dev/null and b/osc21/artwork/logo_osc-video_preview.png differ diff --git a/osc21/artwork/logos/Admin_logo_Transparent_1659x588.png b/osc21/artwork/logos/Admin_logo_Transparent_1659x588.png new file mode 100644 index 0000000..4cf8018 Binary files /dev/null and b/osc21/artwork/logos/Admin_logo_Transparent_1659x588.png differ diff --git a/osc21/artwork/logos/Datto-blue-CMYK.png b/osc21/artwork/logos/Datto-blue-CMYK.png new file mode 100644 index 0000000..808febb Binary files /dev/null and b/osc21/artwork/logos/Datto-blue-CMYK.png differ diff --git a/osc21/artwork/logos/LMI_Logo_Transparent.png b/osc21/artwork/logos/LMI_Logo_Transparent.png new file mode 100644 index 0000000..26bf271 Binary files /dev/null and b/osc21/artwork/logos/LMI_Logo_Transparent.png differ diff --git a/osc21/artwork/logos/SUSE_Logo-vert_L_Green-pos_sRGB.png b/osc21/artwork/logos/SUSE_Logo-vert_L_Green-pos_sRGB.png new file mode 100644 index 0000000..29ce1c6 Binary files /dev/null and b/osc21/artwork/logos/SUSE_Logo-vert_L_Green-pos_sRGB.png differ diff --git a/osc21/artwork/logos/alma.png b/osc21/artwork/logos/alma.png new file mode 100644 index 0000000..74553c9 Binary files /dev/null and b/osc21/artwork/logos/alma.png differ diff --git a/osc21/artwork/logos/fedora.png b/osc21/artwork/logos/fedora.png new file mode 100644 index 0000000..69db4be Binary files /dev/null and b/osc21/artwork/logos/fedora.png differ diff --git a/osc21/artwork/logos/osc21.png b/osc21/artwork/logos/osc21.png new file mode 100644 index 0000000..adf53bf Binary files /dev/null and b/osc21/artwork/logos/osc21.png differ diff --git a/osc21/artwork/logos/shells.png b/osc21/artwork/logos/shells.png new file mode 100644 index 0000000..da32a72 Binary files /dev/null and b/osc21/artwork/logos/shells.png differ diff --git a/osc21/artwork/official-logo-monochrome.svg b/osc21/artwork/official-logo-monochrome.svg new file mode 100644 index 0000000..6c91bb3 --- /dev/null +++ b/osc21/artwork/official-logo-monochrome.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/osc21/artwork/outro.svg b/osc21/artwork/outro.svg new file mode 100644 index 0000000..3a88aec --- /dev/null +++ b/osc21/artwork/outro.svg @@ -0,0 +1,732 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + More Recordings available on media.ccc.de + + + + + + + + + + + + + Video + Team + + + + + + + + + + + + + + + + + + openSUSE Virtual Conference 2021was brought to you by: + + + + + + + + + www.ccc.de + + diff --git a/osc21/artwork/pause.svg b/osc21/artwork/pause.svg new file mode 100644 index 0000000..eb608c0 --- /dev/null +++ b/osc21/artwork/pause.svg @@ -0,0 +1,17538 @@ + + + +image/svg+xmlPause +Thanks to our sponsors + + + + + + + + + \ No newline at end of file diff --git a/osc21/artwork/video-team.png b/osc21/artwork/video-team.png new file mode 100644 index 0000000..ceb962d Binary files /dev/null and b/osc21/artwork/video-team.png differ diff --git a/osc21/artwork/video-team.svg b/osc21/artwork/video-team.svg new file mode 100644 index 0000000..6733672 --- /dev/null +++ b/osc21/artwork/video-team.svg @@ -0,0 +1,143 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + Video + Team + + diff --git a/osc21/artwork/zbau.png b/osc21/artwork/zbau.png new file mode 100644 index 0000000..d4ad699 Binary files /dev/null and b/osc21/artwork/zbau.png differ diff --git a/osc21/artwork/zbau.svg b/osc21/artwork/zbau.svg new file mode 100644 index 0000000..2242f8c --- /dev/null +++ b/osc21/artwork/zbau.svg @@ -0,0 +1,319 @@ + + + +image/svg+xmlVirtual Conference 2021 + + + +Since we cannot leave tips for the nice peoplefrom the Z-Bau this year we have a money pool.The money completely goes to the Z-Bau beergarden.https://t1p.de/zbauIf you like this online event, feel free to leave a tip and support cultural events in Nuremberg. + + + + + + + + + + + + + \ No newline at end of file diff --git a/osc21/intromusic.flac b/osc21/intromusic.flac new file mode 100644 index 0000000..b9be5f2 Binary files /dev/null and b/osc21/intromusic.flac differ diff --git a/osc21/intromusic.mp3 b/osc21/intromusic.mp3 new file mode 100644 index 0000000..1222d1d Binary files /dev/null and b/osc21/intromusic.mp3 differ diff --git a/osc21/outromusic.mp3 b/osc21/outromusic.mp3 new file mode 100644 index 0000000..48d9111 Binary files /dev/null and b/osc21/outromusic.mp3 differ diff --git a/osc22/__init__.py b/osc22/__init__.py new file mode 100644 index 0000000..a947f0b --- /dev/null +++ b/osc22/__init__.py @@ -0,0 +1,149 @@ +#!/usr/bin/python + +from renderlib import * +from easing import * + +# URL to Schedule-XML +scheduleUrl = 'https://events.opensuse.org/conferences/oSC22/schedule.xml' + +def bounce(i, min, max, frames): + if i == frames - 1: + return 0 + + if i <= frames/2: + return easeInOutQuad(i, min, max, frames/2) + else: + return max - easeInOutQuad(i - frames/2, min, max, frames/2) + +def introFrames(parameters): + # 3 Sekunde Text Fadein + frames = 1*fps + for i in range(0, frames): + yield ( + ('textblock', 'style', 'opacity', "%.4f" % easeLinear(i, 0, 1, frames)), + ) + + # 4 Sekunden stehen lassen + frames = 4*fps + for i in range(0, frames): + yield () + + # 1 Sekunde Fade to black layer + frames = 1*fps + for i in range(0, frames): + yield ( + ('fadeout', 'style', 'opacity', "%.4f" % easeLinear(i, 0, 1, frames)), + ) + +def pauseFrames(parameters): + frames = 15*fps + colors = ['#21A4D4', '#73BA25', '#6DA741', '#35B9AB', '#00A489', '#173F4F'] + for i in range(0, len(colors)): + z = 0 + for z in range(0,round(frames/4)): + yield ( + ('pausetext', 'attr', 'opacity', '1.0'), + ('sponsors', 'attr', 'opacity', '0.0'), + ('pause_bg_alt', 'style', 'fill', "%s" % colors[i]), + ('pause_bg_alt', 'attr', 'opacity', '%.4f' % easeLinear(z, 0.0, 1, round(frames/4))), + ) + for z in range(0,round(frames/4)): + yield ( + ('pausetext', 'attr', 'opacity', '1.0'), + ('sponsors', 'attr', 'opacity', '0.0'), + ('pause_bg_alt', 'style', 'fill', "%s" % colors[i]), + ('pause_bg_alt', 'attr', 'opacity', '%.4f' % easeLinear(z, 1.0, -1, round(frames/4))), + ) + z=0 + for z in range(0,round(frames/2)): + yield ( + ('pausetext', 'attr', 'opacity', '%.4f' % easeLinear(z, 0.9, -1, round(frames/2))), + ('pause_bg_alt', 'attr', 'opacity', '0.0'), + ('sponsors', 'attr', 'opacity', '%.4f' % easeLinear(z, 0.0, 1, round(frames/2))), + ) + for z in range(0,round(frames/2)): + yield ( + ('pausetext', 'attr', 'opacity', '%.4f' % easeLinear(z, 0.0, 1, round(frames/2))), + ('pause_bg_alt', 'attr', 'opacity', '0.0'), + ('sponsors', 'attr', 'opacity', '%.4f' % easeLinear(z, 0.9, -1, round(frames/2))), + ) + +def outroFrames(p): + # 5 Sekunden stehen bleiben + frames = 5*fps + for i in range(0, frames): + yield [] + +def debug(): +# render( +# 'intro.svg', +# '../intro.ts', +# introFrames, +# { +# '$ID': 4711, +# '$TITLE': "Long Long Long title is LONG", +# '$SUBTITLE': 'Long Long Long Long subtitle is LONGER', +# '$SPEAKER': 'Long Name of Dr. Dr. Prof. Dr. Long Long' +# } +# ) + + render( + 'pause.svg', + '../pause.ts', + pauseFrames + ) + +# render( +# 'infobeamer.svg', +# '../infobeamer.ts', +# pauseFrames +# ) + +# render( +# 'outro.svg', +# '../outro.ts', +# outroFrames +# ) + +def tasks(queue, args, idlist, skiplist): + # iterate over all events extracted from the schedule xml-export + for event in events(scheduleUrl): + if event['room'] not in ('Saal ', 'Seminarraum 1'): + print("skipping room %s (%s [%s])" % (event['room'], event['title'], event['id'])) + continue + if not (idlist==[]): + if 000000 in idlist: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + if int(event['id']) not in idlist: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + + # generate a task description and put it into the queue + queue.put(Rendertask( + infile = 'intro.svg', + outfile = str(event['id'])+".ts", + sequence = introFrames, + parameters = { + '$ID': event['id'], + '$TITLE': event['title'], + '$SUBTITLE': event['subtitle'], + '$SPEAKER': event['personnames'] + } + )) + + # place a task for the outro into the queue + if not "out" in skiplist: + queue.put(Rendertask( + infile = 'outro.svg', + outfile = 'outro.ts', + sequence = outroFrames + )) + + # place the pause-sequence into the queue + if not "pause" in skiplist: + queue.put(Rendertask( + infile = 'pause.svg', + outfile = 'pause.ts', + sequence = pauseFrames + )) diff --git a/osc22/artwork/_break.svg b/osc22/artwork/_break.svg new file mode 100644 index 0000000..0a783c2 --- /dev/null +++ b/osc22/artwork/_break.svg @@ -0,0 +1,934 @@ + + + + + + + + + + + + + + + + + + + + openSUSE Conference + BREAK TIME + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osc22/artwork/hexagons.png b/osc22/artwork/hexagons.png new file mode 100644 index 0000000..0d3b6a1 Binary files /dev/null and b/osc22/artwork/hexagons.png differ diff --git a/osc22/artwork/infobeamer.png b/osc22/artwork/infobeamer.png new file mode 100644 index 0000000..c8f5a14 Binary files /dev/null and b/osc22/artwork/infobeamer.png differ diff --git a/osc22/artwork/infobeamer.svg b/osc22/artwork/infobeamer.svg new file mode 100644 index 0000000..0858ddd --- /dev/null +++ b/osc22/artwork/infobeamer.svg @@ -0,0 +1,243 @@ + + + +image/svg+xmlConference 2022 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/osc22/artwork/intro.svg b/osc22/artwork/intro.svg new file mode 100644 index 0000000..e725991 --- /dev/null +++ b/osc22/artwork/intro.svg @@ -0,0 +1,341 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + $TITLE $SUBTITLE $SPEAKER + + openSUSE Conference 2022 + + + + + diff --git a/osc22/artwork/logo_osc-video.svg b/osc22/artwork/logo_osc-video.svg new file mode 100644 index 0000000..fd4f59b --- /dev/null +++ b/osc22/artwork/logo_osc-video.svg @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + recording by: younameitpostprocessing by: eventuallyhere openSUSE conference 2017Z-Bau, Nuremberg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osc22/artwork/logo_osc-video_preview.png b/osc22/artwork/logo_osc-video_preview.png new file mode 100644 index 0000000..f0b6686 Binary files /dev/null and b/osc22/artwork/logo_osc-video_preview.png differ diff --git a/osc22/artwork/logos/Admin_logo_Transparent_1659x588.png b/osc22/artwork/logos/Admin_logo_Transparent_1659x588.png new file mode 100644 index 0000000..4cf8018 Binary files /dev/null and b/osc22/artwork/logos/Admin_logo_Transparent_1659x588.png differ diff --git a/osc22/artwork/logos/Datto-blue-CMYK.png b/osc22/artwork/logos/Datto-blue-CMYK.png new file mode 100644 index 0000000..808febb Binary files /dev/null and b/osc22/artwork/logos/Datto-blue-CMYK.png differ diff --git a/osc22/artwork/logos/LMI_Logo_Transparent.png b/osc22/artwork/logos/LMI_Logo_Transparent.png new file mode 100644 index 0000000..26bf271 Binary files /dev/null and b/osc22/artwork/logos/LMI_Logo_Transparent.png differ diff --git a/osc22/artwork/logos/SUSE_Logo-vert_L_Green-pos_sRGB.png b/osc22/artwork/logos/SUSE_Logo-vert_L_Green-pos_sRGB.png new file mode 100644 index 0000000..29ce1c6 Binary files /dev/null and b/osc22/artwork/logos/SUSE_Logo-vert_L_Green-pos_sRGB.png differ diff --git a/osc22/artwork/logos/alma.png b/osc22/artwork/logos/alma.png new file mode 100644 index 0000000..74553c9 Binary files /dev/null and b/osc22/artwork/logos/alma.png differ diff --git a/osc22/artwork/logos/fedora.png b/osc22/artwork/logos/fedora.png new file mode 100644 index 0000000..69db4be Binary files /dev/null and b/osc22/artwork/logos/fedora.png differ diff --git a/osc22/artwork/logos/osc21.png b/osc22/artwork/logos/osc21.png new file mode 100644 index 0000000..adf53bf Binary files /dev/null and b/osc22/artwork/logos/osc21.png differ diff --git a/osc22/artwork/logos/shells.png b/osc22/artwork/logos/shells.png new file mode 100644 index 0000000..da32a72 Binary files /dev/null and b/osc22/artwork/logos/shells.png differ diff --git a/osc22/artwork/official-logo-monochrome.svg b/osc22/artwork/official-logo-monochrome.svg new file mode 100644 index 0000000..6c91bb3 --- /dev/null +++ b/osc22/artwork/official-logo-monochrome.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/osc22/artwork/outro.svg b/osc22/artwork/outro.svg new file mode 100644 index 0000000..f4e68c5 --- /dev/null +++ b/osc22/artwork/outro.svg @@ -0,0 +1,732 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + More Recordings available on media.ccc.de + + + + + + + + + + + + + Video + Team + + + + + + + + + + + + + + + + + + openSUSE Conference 2022was brought to you by: + + + + + + + + + www.ccc.de + + diff --git a/osc22/artwork/overlay_osc22_fullcam.png b/osc22/artwork/overlay_osc22_fullcam.png new file mode 100644 index 0000000..2bacc45 Binary files /dev/null and b/osc22/artwork/overlay_osc22_fullcam.png differ diff --git a/osc22/artwork/pause.svg b/osc22/artwork/pause.svg new file mode 100644 index 0000000..0531ded --- /dev/null +++ b/osc22/artwork/pause.svg @@ -0,0 +1,3472 @@ + + + +image/svg+xmlPause + + + + + + + + + + + \ No newline at end of file diff --git a/osc22/artwork/sponsors.png b/osc22/artwork/sponsors.png new file mode 100644 index 0000000..4fdc938 Binary files /dev/null and b/osc22/artwork/sponsors.png differ diff --git a/osc22/artwork/sponsors.svg b/osc22/artwork/sponsors.svg new file mode 100644 index 0000000..c0f57ad --- /dev/null +++ b/osc22/artwork/sponsors.svg @@ -0,0 +1,953 @@ + + + +image/svg+xmlConference 2022 + + + + + +Thanks to our sponsors + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/osc22/artwork/video-team.png b/osc22/artwork/video-team.png new file mode 100644 index 0000000..ceb962d Binary files /dev/null and b/osc22/artwork/video-team.png differ diff --git a/osc22/artwork/video-team.svg b/osc22/artwork/video-team.svg new file mode 100644 index 0000000..6733672 --- /dev/null +++ b/osc22/artwork/video-team.svg @@ -0,0 +1,143 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + Video + Team + + diff --git a/osc22/artwork/zbau.png b/osc22/artwork/zbau.png new file mode 100644 index 0000000..d4ad699 Binary files /dev/null and b/osc22/artwork/zbau.png differ diff --git a/osc22/artwork/zbau.svg b/osc22/artwork/zbau.svg new file mode 100644 index 0000000..2242f8c --- /dev/null +++ b/osc22/artwork/zbau.svg @@ -0,0 +1,319 @@ + + + +image/svg+xmlVirtual Conference 2021 + + + +Since we cannot leave tips for the nice peoplefrom the Z-Bau this year we have a money pool.The money completely goes to the Z-Bau beergarden.https://t1p.de/zbauIf you like this online event, feel free to leave a tip and support cultural events in Nuremberg. + + + + + + + + + + + + + \ No newline at end of file diff --git a/osc22/intromusic.flac b/osc22/intromusic.flac new file mode 100644 index 0000000..b9be5f2 Binary files /dev/null and b/osc22/intromusic.flac differ diff --git a/osc22/intromusic.mp3 b/osc22/intromusic.mp3 new file mode 100644 index 0000000..1222d1d Binary files /dev/null and b/osc22/intromusic.mp3 differ diff --git a/osc22/outromusic.mp3 b/osc22/outromusic.mp3 new file mode 100644 index 0000000..48d9111 Binary files /dev/null and b/osc22/outromusic.mp3 differ diff --git a/osmocon17/__init__.py b/osmocon17/__init__.py index e95bd94..7de75fa 100644 --- a/osmocon17/__init__.py +++ b/osmocon17/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/osmocon18/__init__.py b/osmocon18/__init__.py index 70f3d96..036ab8e 100644 --- a/osmocon18/__init__.py +++ b/osmocon18/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/osmodevcon18/__init__.py b/osmodevcon18/__init__.py index ecede30..7187ae3 100644 --- a/osmodevcon18/__init__.py +++ b/osmodevcon18/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/osmodevcon19/__init__.py b/osmodevcon19/__init__.py index d6129ea..846be3a 100644 --- a/osmodevcon19/__init__.py +++ b/osmodevcon19/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/osmodevcon24/__init__.py b/osmodevcon24/__init__.py new file mode 100644 index 0000000..4264294 --- /dev/null +++ b/osmodevcon24/__init__.py @@ -0,0 +1,148 @@ +#!/usr/bin/python3 + +from renderlib import * +from schedulelib import * +from easing import * + +# URL to Schedule-XML +scheduleUrl = 'https://pretalx.sysmocom.de/osmodevcon2024/schedule/export/schedule.xml' + +def introFrames(args): + #fade in title + frames = 3*fps + for i in range(0, frames): + yield( + ('title', 'style', 'opacity', easeInQuad(i, 0, 1, frames)), + ) + # fade in subtitle and names + frames = 1*fps + for i in range(0, frames): + yield( + ('title', 'style', 'opacity', 1), + ('subtitle', 'style', 'opacity', easeInQuad(i, 0, 1, frames)), + ('personnames', 'style', 'opacity', easeInQuad(i, 0, 1, frames)), + ) + #show whole image for 2 seconds + frames = 2*fps + for i in range(0, frames): + yield( + ('title', 'style', 'opacity', 1), + ('personnames', 'style', 'opacity', 1), + ('subtitle', 'style', 'opacity', 1), + ) + +def backgroundFrames(parameters): + frames = 5*fps + for i in range(0, frames): + yield( + ('logo', 'style', 'opacity', 1), + ) + +def outroFrames(args): + frames = 2*fps + for i in range(0, frames): + yield( + ('logo', 'style', 'opacity', 1), + ('sublogo', 'style', 'opacity', 1), + ('cclogo', 'style', 'opacity', 1), + ) + # fade out + frames = 3*fps + for i in range(0, frames): + yield( + ('logo', 'style', 'opacity', "%.4f" % easeInCubic(i, 1, -1, frames)), + ('sublogo', 'style', 'opacity', "%.4f" % easeInCubic(i, 1, -1, frames)), + ('cclogo', 'style', 'opacity', "%.4f" % easeInCubic(i, 1, -1, frames)), + ) + +def pauseFrames(args): + #fade in pause + frames = 4*fps + for i in range(0, frames): + yield( + ('pause', 'style', 'opacity', "%.4f" % easeInCubic(i, 0.2, 1, frames)), + ) + + # fade out + frames = 4*fps + for i in range(0, frames): + yield( + ('pause', 'style', 'opacity', "%.4f" % easeInCubic(i, 1, -0.8, frames)), + ) + +def debug(): + render('intro.svg', + '../intro.ts', + introFrames, + { + '$id': 7776, + '$title': 'Configuring + running GPRS/EDGE data services with OsmoPCU, OsmoSGSN and OpenGGSN', + '$subtitle': 'With some subtitle!', + '$personnames': 'Alexander Chemeris + Harald Welte' + } + ) + + render('outro.svg', + '../outro.ts', + outroFrames + ) + + render( + 'background.svg', + '../background.ts', + backgroundFrames + ) + + render('pause.svg', + '../pause.ts', + pauseFrames + ) + + +def tasks(queue, args, idlist, skiplist): + # iterate over all events extracted from the schedule xml-export + for event in events(scheduleUrl): + if not (idlist==[]): + if 000000 in idlist: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + if int(event['id']) not in idlist: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + + # generate a task description and put them into the queue + queue.put(Rendertask( + infile = 'intro.svg', + outfile = str(event['id'])+".ts", + sequence = introFrames, + parameters = { + '$id': event['id'], + '$title': event['title'], + '$subtitle': event['subtitle'], + '$personnames': event['personnames'] + } + )) + + # place a task for the outro into the queue + if not "out" in skiplist: + queue.put(Rendertask( + infile = 'outro.svg', + outfile = 'outro.ts', + sequence = outroFrames + )) + + # place the pause-sequence into the queue + if not "pause" in skiplist: + queue.put(Rendertask( + infile = 'pause.svg', + outfile = 'pause.ts', + sequence = pauseFrames + )) + + # place the background-sequence into the queue + if not "bg" in skiplist: + queue.put(Rendertask( + infile = 'background.svg', + outfile = 'background.ts', + sequence = backgroundFrames + )) diff --git a/osmodevcon24/artwork/background.svg b/osmodevcon24/artwork/background.svg new file mode 100644 index 0000000..3a87e75 --- /dev/null +++ b/osmodevcon24/artwork/background.svg @@ -0,0 +1,946 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + Pause Pause + o + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osmodevcon24/artwork/intro.svg b/osmodevcon24/artwork/intro.svg new file mode 100644 index 0000000..2a8b797 --- /dev/null +++ b/osmodevcon24/artwork/intro.svg @@ -0,0 +1,1372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + Pause Pause $title $personnames $subtitle + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osmodevcon24/artwork/outro.svg b/osmodevcon24/artwork/outro.svg new file mode 100644 index 0000000..1fbdc0e --- /dev/null +++ b/osmodevcon24/artwork/outro.svg @@ -0,0 +1,1479 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + Pause Pause + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osmodevcon24/artwork/pause.svg b/osmodevcon24/artwork/pause.svg new file mode 100644 index 0000000..e8d1e7b --- /dev/null +++ b/osmodevcon24/artwork/pause.svg @@ -0,0 +1,1208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + Pause Pause + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ppw15b/__init__.py b/ppw15b/__init__.py index 37af179..d7f8772 100644 --- a/ppw15b/__init__.py +++ b/ppw15b/__init__.py @@ -2,6 +2,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'https://frab.sendegate.de/de/ppw15b/public/schedule.xml' diff --git a/pwb18/__init__.py b/pwb18/__init__.py index 93ccaea..9ac2be2 100644 --- a/pwb18/__init__.py +++ b/pwb18/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/pycon14/__init__.py b/pycon14/__init__.py index cd41564..d11cda4 100644 --- a/pycon14/__init__.py +++ b/pycon14/__init__.py @@ -2,13 +2,14 @@ import subprocess from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'https://ep2014.europython.eu/schedule.frab.xml' # For (really) too long titles titlemap = { - + } def pyconFrames(): diff --git a/pydata14/__init__.py b/pydata14/__init__.py index fef1e70..67cab88 100644 --- a/pydata14/__init__.py +++ b/pydata14/__init__.py @@ -3,13 +3,14 @@ import subprocess import os.path from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'file://' + os.path.join(os.path.dirname(os.path.abspath(__file__)), 'schedule.xml') # For (really) too long titles titlemap = { - + } def introFrames(): diff --git a/pydata15/__init__.py b/pydata15/__init__.py index ad40689..ed2fb4a 100644 --- a/pydata15/__init__.py +++ b/pydata15/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * # URL to Schedule-XML scheduleUrl = 'https://raw.githubusercontent.com/pydataberlin/pydataberlin.github.io/master/utils/pydata_berlin_voc.xml' diff --git a/qtcon2016/__init__.py b/qtcon2016/__init__.py index a2b1b17..80c42bf 100644 --- a/qtcon2016/__init__.py +++ b/qtcon2016/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/qtws2017/__init__.py b/qtws2017/__init__.py index 0027c3b..4a0ef95 100644 --- a/qtws2017/__init__.py +++ b/qtws2017/__init__.py @@ -3,6 +3,7 @@ import subprocess import os.path from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/renderlib.py b/renderlib.py index 57c9366..c8e5e84 100644 --- a/renderlib.py +++ b/renderlib.py @@ -17,7 +17,8 @@ fps = 25 debug = True args = None -scheduleTree=None +scheduleTree = None + def loadProject(projectname): sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), projectname)) @@ -45,7 +46,7 @@ class Rendertask: self.parameters = parameters self.outfile = outfile self.workdir = workdir - self.sequence = sequence # deprecated, use animated() + self.sequence = sequence # deprecated, use animated() def animated(self, sequence): atask = self @@ -70,6 +71,8 @@ class Rendertask: return None # try to create all folders needed and skip, they already exist + + def ensurePathExists(path): try: os.makedirs(path) @@ -83,6 +86,7 @@ def ensureFilesRemoved(pattern): for f in glob.glob(pattern): os.unlink(f) + def renderFrame(infile, task, outfile): width = 1920 height = 1080 @@ -93,50 +97,57 @@ def renderFrame(infile, task, outfile): converted.save(filename=outfile) elif args.resvg: # invoke inkscape to convert the generated svg-file into a png inside the .frames-directory - cmd = 'resvg --background white --width={1} --height={2} "{4}" "{3}" 2>&1 >/dev/null'.format(task.workdir, width, height, outfile, infile) - errorReturn = subprocess.check_output(cmd, shell=True, universal_newlines=True, stderr=subprocess.STDOUT, cwd=task.workdir) + cmd = 'resvg --background white --width={1} --height={2} "{4}" "{3}" 2>&1 >/dev/null'.format( + task.workdir, width, height, outfile, infile) + errorReturn = subprocess.check_output( + cmd, shell=True, universal_newlines=True, stderr=subprocess.STDOUT, cwd=task.workdir) if errorReturn != '': print("resvg exited with error\n" + errorReturn) # sys.exit(42) else: # invoke inkscape to convert the generated svg-file into a png inside the .frames-directory - cmd = 'inkscape --export-background=white --export-background-opacity=0 --export-width={1} --export-height={2} --export-filename="{3}" "{4}" --pipe 2>&1 >/dev/null'.format(task.workdir, width, height, os.path.abspath(outfile), os.path.abspath(infile)) - errorReturn = subprocess.check_output(cmd, shell=True, universal_newlines=True, stderr=subprocess.STDOUT, cwd=task.workdir) + cmd = 'inkscape --export-background=white --export-background-opacity=0 --export-width={1} --export-height={2} --export-filename="{3}" "{4}" --pipe 2>&1 >/dev/null'.format( + task.workdir, width, height, os.path.abspath(outfile), os.path.abspath(infile)) + errorReturn = subprocess.check_output( + cmd, shell=True, universal_newlines=True, stderr=subprocess.STDOUT, cwd=task.workdir) if errorReturn != '': print("inkscape exited with error\n" + errorReturn) # sys.exit(42) + def cachedRenderFrame(frame, frameNr, task, cache): - skip_rendering = False - # skip first n frames, to speed up rerendering during debugging - if 'only_rerender_frames_after' in task.parameters: - skip_rendering = (frameNr <= task.parameters['only_rerender_frames_after']) + skip_rendering = False + # skip first n frames, to speed up rerendering during debugging + if 'only_rerender_frames_after' in task.parameters: + skip_rendering = (frameNr <= task.parameters['only_rerender_frames_after']) - if args.skip_frames: - skip_rendering = (frameNr <= args.skip_frames) + if args.skip_frames: + skip_rendering = (frameNr <= args.skip_frames) - if args.only_frame: - skip_rendering = (frameNr != args.only_frame) + if args.only_frame: + skip_rendering = (frameNr != args.only_frame) - # print a line for each and every frame generated - if debug and not skip_rendering: - print("frameNr {0:3d} => {1}".format(frameNr, frame)) + # print a line for each and every frame generated + if debug and not skip_rendering: + print("frameNr {0:3d} => {1}".format(frameNr, frame)) - frame = tuple(frame) - if frame in cache: - if debug: - print("cache hit, reusing frame {0}".format(cache[frame])) + frame = tuple(frame) + if frame in cache: + if debug: + print("cache hit, reusing frame {0}".format(cache[frame])) - framedir = task.workdir + "/.frames/" - shutil.copyfile("{0}/{1:04d}.png".format(framedir, cache[frame]), "{0}/{1:04d}.png".format(framedir, frameNr)) + framedir = task.workdir + "/.frames/" + shutil.copyfile("{0}/{1:04d}.png".format(framedir, + cache[frame]), "{0}/{1:04d}.png".format(framedir, frameNr)) - return - elif not skip_rendering: - cache[frame] = frameNr + return + elif not skip_rendering: + cache[frame] = frameNr - svgfile = '{0}/.frames/{1:04d}.svg'.format(task.workdir, frameNr) + svgfile = '{0}/.frames/{1:04d}.svg'.format(task.workdir, frameNr) + if not skip_rendering: with SVGTemplate(task, svgfile) as svg: svg.replacetext() svg.transform(frame) @@ -145,8 +156,8 @@ def cachedRenderFrame(frame, frameNr, task, cache): outfile = '{0}/.frames/{1:04d}.png'.format(task.workdir, frameNr) renderFrame(svgfile, task, outfile) - # increment frame-number - frameNr += 1 + # increment frame-number + frameNr += 1 def rendertask_image(task): @@ -156,6 +167,7 @@ def rendertask_image(task): svg.write() renderFrame(svgfile, task, task.outfile) + def rendertask_video(task): # iterate through the animation sequence frame by frame # frame is a ... tbd @@ -170,7 +182,8 @@ def rendertask_video(task): ensureFilesRemoved(os.path.join(task.workdir, task.outfile)) if task.outfile.endswith('.png'): - cmd = 'cd {0} && cp ".frames/{1:04d}.png" "{2}"'.format(task.workdir, args.only_frame, task.outfile) + cmd = 'cd {0} && cp ".frames/{1:04d}.png" "{2}"'.format( + task.workdir, args.only_frame, task.outfile) # invoke avconv aka ffmpeg and renerate a lossles-dv from the frames # if we're not in debug-mode, suppress all output @@ -191,11 +204,14 @@ def rendertask_video(task): cmd += '-shortest -f mpegts "{0}"'.format(task.outfile) elif task.outfile.endswith('.mov'): cmd = 'cd {0} && '.format(task.workdir) - cmd += 'ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -f image2 -i .frames/%04d.png -r 25 -shortest -c:v qtrle -f mov "{0}"'.format(task.outfile) + cmd += 'ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -f image2 -i .frames/%04d.png -r 25 -shortest -c:v qtrle -f mov "{0}"'.format( + task.outfile) elif task.outfile.endswith('.mkv'): - cmd = 'cd {0} && ffmpeg -ar 48000 -ac 2 -f s16le -i /dev/zero -f image2 -i .frames/%04d.png -aspect 16:9 -c copy -shortest "{1}"'.format(task.workdir, task.outfile) + cmd = 'cd {0} && ffmpeg -ar 48000 -ac 2 -f s16le -i /dev/zero -f image2 -i .frames/%04d.png -aspect 16:9 -c copy -shortest "{1}"'.format( + task.workdir, task.outfile) else: - cmd = 'cd {0} && ffmpeg -ar 48000 -ac 2 -f s16le -i /dev/zero -f image2 -i .frames/%04d.png -target pal-dv -aspect 16:9 -shortest "{1}"'.format(task.workdir, task.outfile) + cmd = 'cd {0} && ffmpeg -ar 48000 -ac 2 -f s16le -i /dev/zero -f image2 -i .frames/%04d.png -target pal-dv -aspect 16:9 -shortest "{1}"'.format( + task.workdir, task.outfile) if debug: print(cmd) @@ -207,15 +223,16 @@ def rendertask_video(task): if r != 0: sys.exit() + def rendertask(task): global args # in debug mode we have no thread-worker which prints its progress if debug: print("generating {0} from {1}".format(task.outfile, task.infile)) - ## Hacky workaround: Fix this properly without breaking the - ## support for partially rendered intros - if True: #args.skip_frames and 'only_rerender_frames_after' not in task.parameters: + # Hacky workaround: Fix this properly without breaking the + # support for partially rendered intros + if True: # args.skip_frames and 'only_rerender_frames_after' not in task.parameters: if os.path.isdir(os.path.join(task.workdir, '.frames')): print("Removing", os.path.join(task.workdir, '.frames')) shutil.rmtree(os.path.join(task.workdir, '.frames')) @@ -234,114 +251,9 @@ def rendertask(task): # remove the generated svg ensureFilesRemoved(os.path.join(task.workdir, '.gen.svg')) -# Download the Events-Schedule and parse all Events out of it. Yield a tupel for each Event -def downloadSchedule(scheduleUrl): - print("downloading schedule") - - # download the schedule - response = urlopen(scheduleUrl) - - # read xml-source - xml = response.read() - - # parse into ElementTree - parser = etree.XMLParser(huge_tree=True) - return etree.fromstring(xml, parser) - -def getSchedule(scheduleUrl): - global scheduleTree - if not scheduleTree: - scheduleTree=downloadSchedule(scheduleUrl) - return scheduleTree - - -def persons(scheduleUrl, personmap={}, taglinemap={}, forEventId=None): - schedule = getSchedule(scheduleUrl) - # iterate all days - for day in schedule.iter('day'): - # iterate all rooms - for room in day.iter('room'): - # iterate events on that day in this room - for event in room.iter('event'): - eventid = int(event.get("id")) - if event != None and not eventid == forEventId: - continue - # aggregate names of the persons holding this talk - persons_seen = [] - if event.find('persons') is not None: - for person in event.find('persons').iter('person'): - id = int(person.get("id")) - person = re.sub(r'\s+', ' ', person.text).strip() - match = re.search(r'\((.*?)\)', person) - tagline = '' - if not match is None: - tagline = match.group(1) - person = person.split(" (")[0] - if id in taglinemap: - tagline = taglinemap[id] - if id in personmap: - person = personmap[id] - if not id in persons_seen: - persons_seen.append(id) - yield { - 'id': id, - 'person': person, - 'tagline': tagline - } - -def events(scheduleUrl, titlemap={}): - schedule = getSchedule(scheduleUrl) - # iterate all days - for day in schedule.iter('day'): - # iterate all rooms - for room in day.iter('room'): - # iterate events on that day in this room - for event in room.iter('event'): - # aggregate names of the persons holding this talk - personnames = [] - if event.find('persons') is not None: - for person in event.find('persons').iter('person'): - try: - personname = re.sub(r'\s+', ' ', person.text).strip() - except: - personnames.append(str('None')) - personnames.append(personname) - - id = int(event.get('id')) - - if id in titlemap: - title = titlemap[id] - elif event.find('title') is not None and event.find('title').text is not None: - title = re.sub(r'\s+', ' ', event.find('title').text).strip() - else: - title = '' - - if event.find('subtitle') is not None and event.find('subtitle').text is not None: - subtitle = re.sub(r'\s+', ' ', event.find('subtitle').text).strip() - else: - subtitle = '' - - if event.find('url') is not None and event.find('url').text is not None: - url = event.find('url').text.strip() - else: - url = '' - # yield a tupel with the event-id, event-title and person-names - yield { - 'day': day.get('index'), - 'id': id, - 'title': title, - 'subtitle': subtitle, - 'persons': personnames, - 'personnames': ', '.join(personnames), - 'room': room.attrib['name'], - 'track': event.find('track').text, - 'url': url - } - try: from termcolor import colored except ImportError: def colored(str, col): return str - diff --git a/requirements.txt b/requirements.txt index 57edff5..efa6214 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ -pillow +pillow>=8.0.0 cssutils==1.0.2 -lxml==4.6.3 -svg.path==4.0.2 -Wand==0.6.5 +lxml~=5.3 +svg.path~=6.0 +Wand~=0.6.5 diff --git a/schedulelib.py b/schedulelib.py new file mode 100644 index 0000000..a986498 --- /dev/null +++ b/schedulelib.py @@ -0,0 +1,127 @@ +# vim: tabstop=4 shiftwidth=4 expandtab + +import re +from lxml import etree +from urllib.request import urlopen + +scheduleTree = None + + +# Download the Events-Schedule and parse all Events out of it. Yield a tupel for each Event +def downloadSchedule(scheduleUrl): + print("downloading schedule") + + # download the schedule + response = urlopen(scheduleUrl) + + # read xml-source + xml = response.read() + + # parse into ElementTree + parser = etree.XMLParser(huge_tree=True) + return etree.fromstring(xml, parser) + + +def getSchedule(scheduleUrl): + global scheduleTree + if not scheduleTree: + scheduleTree = downloadSchedule(scheduleUrl) + return scheduleTree + + +def persons(scheduleUrl, personmap={}, taglinemap={}, forEventId=None): + schedule = getSchedule(scheduleUrl) + # iterate all days + for day in schedule.iter('day'): + # iterate all rooms + for room in day.iter('room'): + # iterate events on that day in this room + for event in room.iter('event'): + eventid = int(event.get("id")) + if event != None and not eventid == forEventId: + continue + # aggregate names of the persons holding this talk + persons_seen = [] + if event.find('persons') is not None: + for person in event.find('persons').iter('person'): + id = int(person.get("id")) + person = re.sub(r'\s+', ' ', person.text).strip() + match = re.search(r'\((.*?)\)', person) + tagline = '' + if not match is None: + tagline = match.group(1) + person = person.split(" (")[0] + if id in taglinemap: + tagline = taglinemap[id] + if id in personmap: + person = personmap[id] + if not id in persons_seen: + persons_seen.append(id) + yield { + 'id': id, + 'person': person, + 'tagline': tagline + } + + +def events(scheduleUrl, titlemap={}): + schedule = getSchedule(scheduleUrl) + # iterate all days + for day in schedule.iter('day'): + # iterate all rooms + for room in day.iter('room'): + # iterate events on that day in this room + for event in room.iter('event'): + # aggregate names of the persons holding this talk + personnames = [] + if event.find('persons') is not None: + for person in event.find('persons').iter('person'): + try: + personname = re.sub(r'\s+', ' ', person.text).strip() + except: + personnames.append(str('None')) + personnames.append(personname) + + id = int(event.get('id')) + + if id in titlemap: + title = titlemap[id] + elif event.find('title') is not None and event.find('title').text is not None: + title = re.sub(r'\s+', ' ', event.find('title').text).strip() + else: + title = '' + + if event.find('subtitle') is not None and event.find('subtitle').text is not None: + subtitle = re.sub(r'\s+', ' ', event.find('subtitle').text).strip() + else: + subtitle = '' + + if event.find('url') is not None and event.find('url').text is not None: + url = event.find('url').text.strip() + else: + url = '' + + if event.find('track') is not None and event.find('track').text is not None: + track = event.find('track').text + else: + track = '' + + # yield a tupel with the event-id, event-title and person-names + yield { + 'day': day.get('index'), + 'id': id, + 'title': title, + 'subtitle': subtitle, + 'persons': personnames, + 'personnames': ', '.join(personnames), + 'room': room.attrib['name'], + 'track': track, + 'url': url + } + + +try: + from termcolor import colored +except ImportError: + def colored(str, col): + return str diff --git a/script-Z-preroll-generator.py b/script-Z-preroll-generator.py index e95f1ef..573ea6e 100755 --- a/script-Z-preroll-generator.py +++ b/script-Z-preroll-generator.py @@ -10,17 +10,17 @@ import renderlib import c3t_rpc_client as rpc try: - from termcolor import colored + from termcolor import colored except ImportError: - def colored(str, col): - return str + def colored(str, col): + return str print("C3TT preroll generator") renderlib.debug = True if os.environ.get('CRS_TOKEN') is None or os.environ.get('CRS_SECRET') is None: - print('CRS_TOKEN or CRS_SECRET is empty. did you source the tracker-scripts-profile?') - sys.exit(1) + print('CRS_TOKEN or CRS_SECRET is empty. did you source the tracker-scripts-profile?') + sys.exit(1) ticket_type = 'recording' ticket_state = 'generating' @@ -32,45 +32,48 @@ secret = os.environ['CRS_SECRET'] filter = {} if not os.environ.get('CRS_ROOM') is None: - filter['Fahrplan.Room'] = os.environ['CRS_ROOM'] + filter['Fahrplan.Room'] = os.environ['CRS_ROOM'] projects = {} + + def generatePreroll(ticket): - print(ticket) - projectname = ticket.get('Processing.Prerolls.Slug', ticket['Meta.Acronym']) - if not projectname in projects: - projects[projectname] = renderlib.loadProject(projectname) + print(ticket) + projectname = ticket.get('Processing.Prerolls.Slug', ticket['Meta.Acronym']) + if not projectname in projects: + projects[projectname] = renderlib.loadProject(projectname) - project = projects[projectname] - task = project.ticket(ticket) - task.outfile = os.path.join(ticket['Processing.Path.Intros'], ticket['Fahrplan.ID'] + '.dv') - task.workdir = os.path.join(os.getcwd(), projectname, 'artwork') + project = projects[projectname] + task = project.ticket(ticket) + task.outfile = os.path.join(ticket['Processing.Path.Intros'], ticket['Fahrplan.ID'] + '.dv') + task.workdir = os.path.join(os.getcwd(), projectname, 'artwork') - print(colored("rendering", 'green')) - renderlib.rendertask(task) + print(colored("rendering", 'green')) + renderlib.rendertask(task) - if hasattr(project, 'deploy'): - print(colored("deploying", 'green')) - project.deploy(ticket, task) + if hasattr(project, 'deploy'): + print(colored("deploying", 'green')) + project.deploy(ticket, task) while True: - print(colored('Asking RPC for {0}-tickets which are ready for state {1}'.format(ticket_type, ticket_state), 'yellow')) + print(colored( + 'Asking RPC for {0}-tickets which are ready for state {1}'.format(ticket_type, ticket_state), 'yellow')) - ticket_id = rpc.assignNextUnassignedForState(ticket_type, ticket_state, url, token, host, secret, filter) - if ticket_id != False: - ticket = rpc.getTicketProperties(str(ticket_id), url, token, host, secret) - try: - generatePreroll(ticket) - rpc.setTicketDone(str(ticket_id), url, token, host, secret) - except: - error = str(traceback.format_exc()) - print(colored(error, 'red')) - rpc.setTicketFailed(str(ticket_id), error, url, token, host, secret) - - else: - print('No ticket found') - - print('Sleeping for 30 seconds') - time.sleep(30); + ticket_id = rpc.assignNextUnassignedForState( + ticket_type, ticket_state, url, token, host, secret, filter) + if ticket_id != False: + ticket = rpc.getTicketProperties(str(ticket_id), url, token, host, secret) + try: + generatePreroll(ticket) + rpc.setTicketDone(str(ticket_id), url, token, host, secret) + except: + error = str(traceback.format_exc()) + print(colored(error, 'red')) + rpc.setTicketFailed(str(ticket_id), error, url, token, host, secret) + else: + print('No ticket found') + + print('Sleeping for 30 seconds') + time.sleep(30) diff --git a/sendezentrum14/__init__.py b/sendezentrum14/__init__.py index e1a0c74..3440c38 100644 --- a/sendezentrum14/__init__.py +++ b/sendezentrum14/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * import math def pauseFrames(): diff --git a/smarthomeday2018/__init__.py b/smarthomeday2018/__init__.py index 57eef6e..c275929 100644 --- a/smarthomeday2018/__init__.py +++ b/smarthomeday2018/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/sonoj19/__init__.py b/sonoj19/__init__.py index 1d1d3bc..ff86d57 100644 --- a/sonoj19/__init__.py +++ b/sonoj19/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * from math import sin, pi diff --git a/sotm2019/__init__.py b/sotm2019/__init__.py index e2ce122..41e0699 100644 --- a/sotm2019/__init__.py +++ b/sotm2019/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/sotm2020/__init__.py b/sotm2020/__init__.py index df64e9a..20bfd26 100644 --- a/sotm2020/__init__.py +++ b/sotm2020/__init__.py @@ -2,6 +2,7 @@ import subprocess from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/sotmeu14/__init__.py b/sotmeu14/__init__.py index b68eea1..e94f9d8 100644 --- a/sotmeu14/__init__.py +++ b/sotmeu14/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * import math # URL to Schedule-XML diff --git a/subscribe/__init__.py b/subscribe/__init__.py index be1145f..788f31b 100644 --- a/subscribe/__init__.py +++ b/subscribe/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML @@ -15,13 +16,13 @@ def introFrames(p): nr = p['$id']; - # 9 Sekunden nix + # 9 Sekunden nix frames = 9*fps for i in range(0, frames): givenFrame += 1 yield ( ('bg', 'attr', '{http://www.w3.org/1999/xlink}href', "given-frames/frame%04d.png" % (givenFrame)), - ('layer1', 'style', 'opacity', "%.4f" % 0), # nix + ('layer1', 'style', 'opacity', "%.4f" % 0), # nix # ('text', 'attr', 'transform', 'translate(%.4f, 0)' % easeOutQuad(i, move, -move, frames)), ) diff --git a/subscribe10/__init__.py b/subscribe10/__init__.py index 2d2edcf..3c0b3a5 100644 --- a/subscribe10/__init__.py +++ b/subscribe10/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML @@ -15,13 +16,13 @@ def introFrames(p): nr = p['$id']; - # 9 Sekunden nix + # 9 Sekunden nix frames = 9*fps for i in range(0, frames): givenFrame += 1 yield ( ('bg', 'attr', '{http://www.w3.org/1999/xlink}href', "given-frames/frame%04d.png" % (givenFrame)), - ('layer1', 'style', 'opacity', "%.4f" % 0), # nix + ('layer1', 'style', 'opacity', "%.4f" % 0), # nix # ('text', 'attr', 'transform', 'translate(%.4f, 0)' % easeOutQuad(i, move, -move, frames)), ) diff --git a/suselabs18/__init__.py b/suselabs18/__init__.py index 0b4687e..e524ee0 100644 --- a/suselabs18/__init__.py +++ b/suselabs18/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/svgtemplate.py b/svgtemplate.py index 4391214..00050e1 100644 --- a/svgtemplate.py +++ b/svgtemplate.py @@ -11,6 +11,7 @@ from xml.sax.saxutils import escape as xmlescape cssutils.ser.prefs.lineSeparator = ' ' cssutils.log.setLevel(logging.FATAL) + class SVGTemplate: def __init__(self, task, outfile): self.task = task diff --git a/systemd-conf-15/__init__.py b/systemd-conf-15/__init__.py index cc64875..25d8ee1 100644 --- a/systemd-conf-15/__init__.py +++ b/systemd-conf-15/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/systemd-conf-16/__init__.py b/systemd-conf-16/__init__.py index 23ec2f5..73da313 100644 --- a/systemd-conf-16/__init__.py +++ b/systemd-conf-16/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/systemkonform/__init__.py b/systemkonform/__init__.py index 229beff..a759b9b 100644 --- a/systemkonform/__init__.py +++ b/systemkonform/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/taskforce_biometrics/__init__.py b/taskforce_biometrics/__init__.py index bf98b28..8701f4d 100644 --- a/taskforce_biometrics/__init__.py +++ b/taskforce_biometrics/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * def introFrames(p): diff --git a/vcfb/__init__.py b/vcfb/__init__.py index ca96496..92ff7a1 100644 --- a/vcfb/__init__.py +++ b/vcfb/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/vcfb15/__init__.py b/vcfb15/__init__.py index ca96496..92ff7a1 100644 --- a/vcfb15/__init__.py +++ b/vcfb15/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/vcfb16/__init__.py b/vcfb16/__init__.py index 039f102..7fd3334 100644 --- a/vcfb16/__init__.py +++ b/vcfb16/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/vcfb17/__init__.py b/vcfb17/__init__.py index 8ba8007..50c4e7c 100644 --- a/vcfb17/__init__.py +++ b/vcfb17/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/vcfb18/__init__.py b/vcfb18/__init__.py index a7ade7a..28faafb 100644 --- a/vcfb18/__init__.py +++ b/vcfb18/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * import math diff --git a/vcfb19/__init__.py b/vcfb19/__init__.py index 149c9df..762d18f 100644 --- a/vcfb19/__init__.py +++ b/vcfb19/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * import math diff --git a/vcfb22/__init__.py b/vcfb22/__init__.py new file mode 100644 index 0000000..4999dc6 --- /dev/null +++ b/vcfb22/__init__.py @@ -0,0 +1,149 @@ +#!/usr/bin/python3 + +from renderlib import * +from schedulelib import * +from easing import * +import math + +# URL to Schedule-XML +scheduleUrl = 'http://vcfb.de/2022/schedule.xml' + +# For (really) too long titles +titlemap = { + #708: "Neue WEB-Anwendungen des LGRB Baden-Württemberg im Überblick" +} +personmap = { +} + +taglinemap = { +} + +def outroFrames(p): + frames = 2*fps + for i in range(0, frames): + yield ( + ('logo', 'style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), + ('plate', 'style', 'opacity', 0), + ) + + frames = 1*fps + for i in range(0, frames): + yield ( + ('logo', 'style', 'opacity', 1), + ('plate', 'style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), + ) + + frames = 2*fps + for i in range(0, frames): + yield ( + ('logo', 'style', 'opacity', 1), + ('plate', 'style', 'opacity', 1), + ) + +def introFrames(p): + frames = math.floor(1.5*fps) + for i in range(0, frames): + yield ( + ('header', 'attr', 'y', 659), + ('text', 'style', 'opacity', 0), + ) + + frames = 1*fps + for i in range(0, frames): + yield ( + ('text', 'style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), + ) + + frames = math.ceil(3.5*fps) + for i in range(0, frames): + yield ( + ('text', 'style', 'opacity', 1), + ) + +def pauseFrames(p): + pass + + +def debug(): + render( + 'intro.svg', + '../intro.ts', + introFrames, + { + '$id': 6526, + '$title': 'Besser steuern durch Daten? - Zur Performativität soziotechnischer Systeme und der Quantifizierung der sozialen Welt', + '$subtitle': '', + '$personnames': 'Judith Hartstein und Anne K. Krüger' + } + ) + + #render( + # 'outro.svg', + # '../outro.ts', + # outroFrames + #) + + # render('pause.svg', + # '../pause.ts', + # pauseFrames + # ) + +def tasks(queue, params, idlist, skiplist): +# # iterate over all events extracted from the schedule xml-export + for event in events(scheduleUrl): + if not (idlist==[]): + if 000000 in idlist: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + if int(event['id']) not in idlist: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + + # generate a task description and put them into the queue + if int(event['id']) not in skiplist: + queue.put(Rendertask( + infile = 'intro.svg', + outfile = str(event['id'])+".ts", + sequence = introFrames, + parameters = { + '$id': event['id'], + '$title': event['title'], + '$subtitle': event['subtitle'], + '$personnames': event['personnames'] + } + )) + +# for person in persons(scheduleUrl, personmap, taglinemap, event['id']): +# queue.put(Rendertask( +# infile = 'lower-third.svg', +# outfile = 'event_{}_person_{}.png'.format(str(event['id']), str(person['id'])), +# parameters = { +# '$PERSON': person['person'], +# '$TAGLINE': person['tagline'], +# } +# )) +# +# queue.put(Rendertask( +# infile = 'lower-third.svg', +# outfile = 'event_{}_persons.png'.format(str(event['id'])), +# parameters = { +# '$PERSON': event['personnames'], +# '$TAGLINE': '', +# } +# )) +# + # place a task for the outro into the queue + if not "out" in skiplist: + queue.put(Rendertask( + infile = 'outro.svg', + outfile = 'outro.ts', + sequence = outroFrames + )) + + # place the pause-sequence into the queue + #if not "pause" in skiplist: +# queue.put(Rendertask( +# infile = 'pause.svg', +# outfile = 'pause.ts', +# sequence = pauseFrames +# )) diff --git a/vcfb22/artwork/Computerfont.ttf b/vcfb22/artwork/Computerfont.ttf new file mode 100644 index 0000000..49f1c62 Binary files /dev/null and b/vcfb22/artwork/Computerfont.ttf differ diff --git a/vcfb22/artwork/intro.svg b/vcfb22/artwork/intro.svg new file mode 100644 index 0000000..30044ab --- /dev/null +++ b/vcfb22/artwork/intro.svg @@ -0,0 +1,15584 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +   + $subtitle $title  $personnames + diff --git a/vcfb22/artwork/lower-third.svg b/vcfb22/artwork/lower-third.svg new file mode 100644 index 0000000..a70d3b4 --- /dev/null +++ b/vcfb22/artwork/lower-third.svg @@ -0,0 +1,6231 @@ + + + +$PERSON diff --git a/vcfb22/artwork/outro.svg b/vcfb22/artwork/outro.svg new file mode 100644 index 0000000..2659dde --- /dev/null +++ b/vcfb22/artwork/outro.svg @@ -0,0 +1,7956 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + More Recordings available on media.ccc.de + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vcfb22/artwork/pause.svg b/vcfb22/artwork/pause.svg new file mode 100644 index 0000000..8ef961c --- /dev/null +++ b/vcfb22/artwork/pause.svg @@ -0,0 +1,6626 @@ + + + +image/svg+xmlPause + \ No newline at end of file diff --git a/vcfb23/__init__.py b/vcfb23/__init__.py new file mode 100644 index 0000000..c638396 --- /dev/null +++ b/vcfb23/__init__.py @@ -0,0 +1,149 @@ +#!/usr/bin/python3 + +from renderlib import * +from schedulelib import * +from easing import * +import math + +# URL to Schedule-XML +scheduleUrl = 'http://vcfb.de/2023/schedule.xml' + +# For (really) too long titles +titlemap = { + #708: "Neue WEB-Anwendungen des LGRB Baden-Württemberg im Überblick" +} +personmap = { +} + +taglinemap = { +} + +def outroFrames(p): + frames = 2*fps + for i in range(0, frames): + yield ( + ('logo', 'style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), + ('plate', 'style', 'opacity', 0), + ) + + frames = 1*fps + for i in range(0, frames): + yield ( + ('logo', 'style', 'opacity', 1), + ('plate', 'style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), + ) + + frames = 2*fps + for i in range(0, frames): + yield ( + ('logo', 'style', 'opacity', 1), + ('plate', 'style', 'opacity', 1), + ) + +def introFrames(p): + frames = math.floor(1.5*fps) + for i in range(0, frames): + yield ( + ('header', 'attr', 'y', 659), + ('text', 'style', 'opacity', 0), + ) + + frames = 1*fps + for i in range(0, frames): + yield ( + ('text', 'style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), + ) + + frames = math.ceil(3.5*fps) + for i in range(0, frames): + yield ( + ('text', 'style', 'opacity', 1), + ) + +def pauseFrames(p): + pass + + +def debug(): + render( + 'intro.svg', + '../intro.ts', + introFrames, + { + '$id': 6526, + '$title': 'Besser steuern durch Daten? - Zur Performativität soziotechnischer Systeme und der Quantifizierung der sozialen Welt', + '$subtitle': '', + '$personnames': 'Judith Hartstein und Anne K. Krüger' + } + ) + + #render( + # 'outro.svg', + # '../outro.ts', + # outroFrames + #) + + # render('pause.svg', + # '../pause.ts', + # pauseFrames + # ) + +def tasks(queue, params, idlist, skiplist): +# # iterate over all events extracted from the schedule xml-export + for event in events(scheduleUrl): + if not (idlist==[]): + if 000000 in idlist: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + if int(event['id']) not in idlist: + print("skipping id (%s [%s])" % (event['title'], event['id'])) + continue + + # generate a task description and put them into the queue + if int(event['id']) not in skiplist: + queue.put(Rendertask( + infile = 'intro.svg', + outfile = str(event['id'])+".ts", + sequence = introFrames, + parameters = { + '$id': event['id'], + '$title': event['title'], + '$subtitle': event['subtitle'], + '$personnames': event['personnames'] + } + )) + +# for person in persons(scheduleUrl, personmap, taglinemap, event['id']): +# queue.put(Rendertask( +# infile = 'lower-third.svg', +# outfile = 'event_{}_person_{}.png'.format(str(event['id']), str(person['id'])), +# parameters = { +# '$PERSON': person['person'], +# '$TAGLINE': person['tagline'], +# } +# )) +# +# queue.put(Rendertask( +# infile = 'lower-third.svg', +# outfile = 'event_{}_persons.png'.format(str(event['id'])), +# parameters = { +# '$PERSON': event['personnames'], +# '$TAGLINE': '', +# } +# )) +# + # place a task for the outro into the queue + if not "out" in skiplist: + queue.put(Rendertask( + infile = 'outro.svg', + outfile = 'outro.ts', + sequence = outroFrames + )) + + # place the pause-sequence into the queue + #if not "pause" in skiplist: +# queue.put(Rendertask( +# infile = 'pause.svg', +# outfile = 'pause.ts', +# sequence = pauseFrames +# )) diff --git a/vcfb23/artwork/Computerfont.ttf b/vcfb23/artwork/Computerfont.ttf new file mode 100644 index 0000000..49f1c62 Binary files /dev/null and b/vcfb23/artwork/Computerfont.ttf differ diff --git a/vcfb23/artwork/intro.svg b/vcfb23/artwork/intro.svg new file mode 100644 index 0000000..30044ab --- /dev/null +++ b/vcfb23/artwork/intro.svg @@ -0,0 +1,15584 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +   + $subtitle $title  $personnames + diff --git a/vcfb23/artwork/lower-third.svg b/vcfb23/artwork/lower-third.svg new file mode 100644 index 0000000..a70d3b4 --- /dev/null +++ b/vcfb23/artwork/lower-third.svg @@ -0,0 +1,6231 @@ + + + +$PERSON diff --git a/vcfb23/artwork/outro.svg b/vcfb23/artwork/outro.svg new file mode 100644 index 0000000..2659dde --- /dev/null +++ b/vcfb23/artwork/outro.svg @@ -0,0 +1,7956 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + More Recordings available on media.ccc.de + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vcfb23/artwork/pause.svg b/vcfb23/artwork/pause.svg new file mode 100644 index 0000000..8ef961c --- /dev/null +++ b/vcfb23/artwork/pause.svg @@ -0,0 +1,6626 @@ + + + +image/svg+xmlPause + \ No newline at end of file diff --git a/vcfb24/Computerfont.ttf b/vcfb24/Computerfont.ttf new file mode 100644 index 0000000..49f1c62 Binary files /dev/null and b/vcfb24/Computerfont.ttf differ diff --git a/vcfb24/SourceSansPro-Semibold.ttf b/vcfb24/SourceSansPro-Semibold.ttf new file mode 100644 index 0000000..bf69cc2 Binary files /dev/null and b/vcfb24/SourceSansPro-Semibold.ttf differ diff --git a/vcfb24/config.ini b/vcfb24/config.ini new file mode 100644 index 0000000..712eff6 --- /dev/null +++ b/vcfb24/config.ini @@ -0,0 +1,37 @@ +[meta] +schedule = http://vcfb.de/2024/schedule.xml +# ffmpeg -loop 1 -i intro.png -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -c:v libx264 -tune stillimage -pix_fmt yuv420p -c:a aac -r 25 -t 10 intro.mp4 +template = intro.mp4 +alpha = false +prores = false +inout_type = t +fade_duration = 0.5 + +[title] +in = 1 +out = 9.5 +fontfile = Computerfont.ttf +fontsize = 100 +fontcolor = #ffffff +x = 85 +y = 122 + +[speaker] +in = 2 +out = 9 +fontfile = SourceSansPro-Semibold.ttf +fontsize = 65 +fontcolor = #ffffff +x = 85 +y = 861 + + +[text] +in = 0 +out = 0 +fontfile = Computerfont.ttf +fontsize = 0 +fontcolor = #ffffff +x = 0 +y = 0 +; text = diff --git a/vcfb24/intro.svg b/vcfb24/intro.svg new file mode 100644 index 0000000..30044ab --- /dev/null +++ b/vcfb24/intro.svg @@ -0,0 +1,15584 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +   + $subtitle $title  $personnames + diff --git a/vcfb24/lower-third.svg b/vcfb24/lower-third.svg new file mode 100644 index 0000000..a70d3b4 --- /dev/null +++ b/vcfb24/lower-third.svg @@ -0,0 +1,6231 @@ + + + +$PERSON diff --git a/vcfb24/outro.svg b/vcfb24/outro.svg new file mode 100644 index 0000000..45f706d --- /dev/null +++ b/vcfb24/outro.svg @@ -0,0 +1,1668 @@ + + + + + + + + + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  +More Recordings available on media.ccc.de + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vcfb24/pause.svg b/vcfb24/pause.svg new file mode 100644 index 0000000..8ef961c --- /dev/null +++ b/vcfb24/pause.svg @@ -0,0 +1,6626 @@ + + + +image/svg+xmlPause + \ No newline at end of file diff --git a/voc/__init__.py b/voc/__init__.py index 9c7cd7d..ae4277d 100644 --- a/voc/__init__.py +++ b/voc/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * def pauseFrames(p): diff --git a/wikidatacon2017/__init__.py b/wikidatacon2017/__init__.py index abeabc4..5283710 100644 --- a/wikidatacon2017/__init__.py +++ b/wikidatacon2017/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML diff --git a/wikidatacon2019/__init__.py b/wikidatacon2019/__init__.py index 0d30ed1..c580af6 100644 --- a/wikidatacon2019/__init__.py +++ b/wikidatacon2019/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 from renderlib import * +from schedulelib import * from easing import * # URL to Schedule-XML