From 06297c3976c36e2bc78b1eb00babbe955abd6f21 Mon Sep 17 00:00:00 2001
From: Evennia docbuilder action ON_DEMAND_HANDLER.set_dt(key, category, dt) and
.set_stage(key, category, stage) to allow manual tweaking of task timings,
for example for a spell speeding a plant’s growth (Griatch)
Feature: Add ON_DEMAND_HANDLER.get_dt/stages(key,category, **kwargs), where
+the kwargs are passed into any stage-callable defined with the stages. (Griatch)
Feature: Add use_assertequal kwarg to the EvenniaCommandTestMixin testing
class; this uses django’s assertEqual over the default more lenient checker,
which can be useful for testing table whitespace (Griatch)
The get_state(key, category=None, **kwargs) methoid is used to get the current stage. The get_dt(key, category=None, **kwargs) method instead retrieves the currently passed time.
You could now create the rose and it would figure out its state only when you are actually looking at it. It will stay a seedling for 10 minutes (of in-game real time) before it sprouts. Within 12 hours it will be dead again.
If you had a harvest command in your game, you could equally have it check the stage of bloom and give you different results depending on if you pick the rose at the right time or not.
The on-demand handler’s tasks survive a reload and will properly account for downtime.
@@ -210,7 +212,7 @@The key can be a string, but also a typeclassed object (its string representation will be used, which normally includes its #dbref). You can also pass a callable - this will be called without arguments and is expected to return a string to use for the key. Finally, you can also pass OnDemandTask entities - these are the objects the handler uses under the hood to represent each task.
The category allows you to further categorize your demandhandler tasks to make sure they are unique. Since the handler is global, you need to make sure key + category is unique. While category is optional, if you use it you must also use it to retrieve your state later.
stages is a dict {dt: statename} or {dt: (statename, callable)} that represents how much time (in seconds) from the start of the task it takes for that stage to begin. In the flower example above, it was 10 hours until the wilting state began. If a callable is also included, this will be called the first time that state is checked for (only!). The callable takes a evennia.OnDemandTask as an argument and allows for tweaking the task on the fly. The dt can also be a float if you desire higher than per-second precision. Having stages is optional - sometimes you only want to know how much time has passed.
stages is a dict {dt: statename} or {dt: (statename, callable)} that represents how much time (in seconds) from the start of the task it takes for that stage to begin. In the flower example above, it was 10 hours until the wilting state began. If a callable is included, it will fire the first time that stage is reached. This callable takes the current OnDemandTask and **kwargs as arguments; the keywords are passed on from the get_stages/dt methods. See below for information about the allowed callables. Having stages is optional - sometimes you only want to know how much time has passed.
.get_dt() - get the current time (in seconds) since the task started. This is a float.
.get_stage() - get the current state name, such as “flowering” or “seedling”. If you didn’t specify any stages, this will return None, and you need to interpret the dt yourself to determine which state you are in.
If you define one or more of your stages dict keys as {dt: (statename, callable)}, this callable will be called when that stage is checked for the first time. This ‘stage callable’ have a few requirements:
The stage callable must be possible to pickle because it will be saved to the database. This basically means your callable needs to be a stand-alone function or a method decorated with @staticmethod. You won’t be able to access the object instance as self directly from such a method or function - you need to pass it explicitly.
The callable must always take task as its first element. This is the OnDemandTask object firing this callable.
It may optionally take **kwargs . This will be passed down from your call of get_dt or get_stages.
Here’s an example:
+from evennia DefaultObject, ON_DEMAND_HANDLER
+
+def mycallable(task, **kwargs)
+ # this function is outside the class and is pickleable just fine
+ obj = kwargs.get("obj")
+ # do something with the object
+
+class SomeObject(DefaultObject):
+
+ def at_object_creation(self):
+ ON_DEMAND_HANDLER.add(
+ "key1",
+ stages={0: "new", 10: ("old", mycallable)}
+ )
+
+ def do_something(self):
+ # pass obj=self into the handler; to be passed into
+ # mycallable if we are in the 'old' stage.
+ state = ON_DEMAND_HANDLER.get_state("key1", obj=self)
+
+Above, the obj=self will passed into mycallable once we reach the ‘old’ state. If we are not in the ‘old’ stage, the extra kwargs go nowhere. This way a function can be made aware of the object calling it while still being possible to pickle. You can also pass any other information into the callable this way.
++If you don’t want to deal with the complexity of callables you can also just read off the current stage and do all the logic outside of the handler. This can often be easier to read and maintain.
+
Normally, when a sequence of stages have been cycled through, the task will just stop at the last stage indefinitely.
evennia.OnDemandTask.stagefunc_loop is an included static-method callable you can use to make the task loop. Here’s an example of how to use it:
evennia.OnDemandTask.stagefunc_loop is an included static-method stage callable you can use to make the task loop. Here’s an example of how to use it:
from evennia import ON_DEMAND_HANDLER, OnDemandTask
ON_DEMAND_HANDLER.add(
diff --git a/docs/latest/_modules/evennia/commands/default/building.html b/docs/latest/_modules/evennia/commands/default/building.html
index 25b370037d..a4b72d9e41 100644
--- a/docs/latest/_modules/evennia/commands/default/building.html
+++ b/docs/latest/_modules/evennia/commands/default/building.html
@@ -94,11 +94,10 @@
import re
import typing
+import evennia
from django.conf import settings
from django.core.paginator import Paginator
from django.db.models import Max, Min, Q
-
-import evennia
from evennia import InterruptCommand
from evennia.commands.cmdhandler import generate_cmdset_providers, get_and_merge_cmdsets
from evennia.locks.lockhandler import LockException
@@ -3418,14 +3417,23 @@
string = f"|w{header}|n(#{low}-#{high}{restrictions}):"
res = None
for res in results:
- string += f"\n |g{res.get_display_name(caller)} - {res.path}|n"
+ string += (
+ "\n "
+ f" |g{res.get_display_name(caller)}"
+ f"{res.get_extra_display_name_info(caller)} -"
+ f" {res.path}|n"
+ )
if (
"loc" in self.switches
and nresults == 1
and res
and getattr(res, "location", None)
):
- string += f" (|wlocation|n: |g{res.location.get_display_name(caller)}|n)"
+ string += (
+ " (|wlocation|n:"
+ f" |g{res.location.get_display_name(caller)}"
+ f"{res.get_extra_display_name_info(caller)}|n)"
+ )
else:
string = f"|wNo Matches|n(#{low}-#{high}{restrictions}):"
string += f"\n |RNo matches found for '{searchstring}'|n"
diff --git a/docs/latest/_modules/evennia/scripts/ondemandhandler.html b/docs/latest/_modules/evennia/scripts/ondemandhandler.html
index f40c39add0..124e8c0a85 100644
--- a/docs/latest/_modules/evennia/scripts/ondemandhandler.html
+++ b/docs/latest/_modules/evennia/scripts/ondemandhandler.html
@@ -93,10 +93,10 @@
actually needs the information. This is a very efficient way to handle gradual changes, requiring
not computer resources until the state is actually needed.
-For example, consider a flowering system, where a seed sprouts, grows and blooms over a certain time.
-One _could_ implement this with e.g. a Script or a ticker that gradually moves the flower along
-its stages of growth. But what if that flower is in a remote location, and no one is around to see it?
-You are then wasting computational resources on something that no one is looking at.
+For example, consider a flowering system, where a seed sprouts, grows and blooms over a certain
+time. One _could_ implement this with e.g. a Script or a ticker that gradually moves the flower
+along its stages of growth. But what if that flower is in a remote location, and no one is around to
+see it? You are then wasting computational resources on something that no one is looking at.
The truth is that most of the time, players are not looking at most of the things in the game. They
_only_ need to know about which state the flower is in when they are actually looking at it, or
@@ -118,8 +118,8 @@
since too long time has passed and the plant has died.
With a system like this you could have growing plants all over your world and computing usage would
-only scale by how many players you have exploring your world. The players will not know the difference
-between this and a system that is always running, but your server will thank you.
+only scale by how many players you have exploring your world. The players will not know the
+difference between this and a system that is always running, but your server will thank you.
There is only one situation where this system is not ideal, and that is when a player should be
informed of the state change _even if they perform no action_. That is, even if they are just idling
@@ -159,6 +159,7 @@
_RUNTIME = None
ON_DEMAND_HANDLER = None
+ONDEMAND_HANDLER_SAVE_NAME = "on_demand_timers"
[docs]class OnDemandTask:
@@ -166,10 +167,10 @@
Stores information about an on-demand task.
Default property:
- - `default_stage_function (callable)`: This is called if no stage function is given in the stages dict.
- This is meant for changing the task itself (such as restarting it). Actual game code should
- be handled elsewhere, by checking this task. See the `stagefunc_*` static methods for examples
- of how to manipulate the task when a stage is reached.
+ - `default_stage_function (callable)`: This is called if no stage function is given in the
+ stages dict. This is meant for changing the task itself (such as restarting it). Actual
+ game code should be handled elsewhere, by checking this task. See the `stagefunc_*` static
+ methods for examples of how to manipulate the task when a stage is reached.
"""
@@ -190,7 +191,7 @@
return _RUNTIME()
[docs] @staticmethod
- def stagefunc_loop(task):
+ def stagefunc_loop(task, **kwargs):
"""
Attach this to the last stage to have the task start over from
the beginning
@@ -221,7 +222,7 @@
task.start_time = now - current_loop_time
[docs] @staticmethod
- def stagefunc_bounce(task):
+ def stagefunc_bounce(task, **kwargs):
"""
This endfunc will have the task reverse direction and go through the stages in
reverse order. This stage-function must be placed at both 'ends' of the stage sequence
@@ -251,7 +252,8 @@
stages = task.stages
task.stages = {abs(k - max_dt): v for k, v in sorted(stages.items())}
- # default fallback stage function. This is called if no stage function is given in the stages dict.
+ # default fallback stage function. This is called if no stage function is given in the stages
+ # dict.
default_stage_function = None
[docs] def __init__(self, key, category, stages=None, autostart=True):
@@ -329,13 +331,14 @@
return False
return (self.key, self.category) == (other.key, other.category)
-[docs] def check(self, autostart=True):
+[docs] def check(self, autostart=True, **kwargs):
"""
Check the current stage of the task and return the time-delta to the next stage.
- Args:
+ Keyword Args:
autostart (bool, optional): If this is set, and the task has not been started yet,
it will be started by this check. This is mainly used internally.
+ **kwargs: Will be passed to the stage function, if one is called.
Returns:
tuple: A tuple (dt, stage) where `dt` is the time-delta (in seconds) since the test
@@ -358,7 +361,7 @@
if stage_func:
try:
- stage_func(self)
+ stage_func(self, **kwargs)
except Exception as err:
logger.log_trace(
f"Error getting stage of on-demand task {self} "
@@ -392,16 +395,17 @@
return dt, stage
-[docs] def get_dt(self):
+[docs] def get_dt(self, **kwargs):
"""
Get the time-delta since last check.
Returns:
int: The time since the last check, or 0 if this is the first time the task is checked.
+ **kwargs: Will be passed to the stage function, if one is called.
"""
- return self.check()[0]
+ return self.check(autostart=True, **kwargs)[0]
[docs] def set_dt(self, dt):
"""
@@ -420,16 +424,17 @@
"""
self.start_time = OnDemandTask.runtime() - dt
-[docs] def get_stage(self):
+[docs] def get_stage(self, **kwargs):
"""
Get the current stage of the task. If no stage was given, this will return `None` but
still update the last_checked time.
Returns:
str or None: The current stage of the task, or `None` if no stages are set.
+ **kwargs: Will be passed to the stage function, if one is called.
"""
- return self.check()[1]
+ return self.check(autostart=True, **kwargs)[1]
[docs] def set_stage(self, stage=None):
"""
@@ -476,14 +481,14 @@
This should be automatically called when Evennia starts.
"""
- self.tasks = dict(ServerConfig.objects.conf("on_demand_timers", default=dict))
+ self.tasks = dict(ServerConfig.objects.conf(ONDEMAND_HANDLER_SAVE_NAME, default=dict))
[docs] def save(self):
"""
Save the on-demand timers to ServerConfig storage. Should be called when Evennia shuts down.
"""
- ServerConfig.objects.conf("on_demand_timers", self.tasks)
+ ServerConfig.objects.conf(ONDEMAND_HANDLER_SAVE_NAME, self.tasks)
def _build_key(self, key, category):
"""
@@ -494,7 +499,8 @@
called without arguments. If an Object, will be converted to a string. If
an `OnDemandTask`, then all other arguments are ignored and the task will be used
to build the internal storage key.
- category (str or callable): The task category. If callable, it will be called without arguments.
+ category (str or callable): The task category. If callable, it will be called without
+ arguments.
Returns:
tuple (str, str or None): The unique key.
@@ -527,7 +533,8 @@
Returns:
OnDemandTask: The created task (or the same that was added, if given an `OnDemandTask`
- as a `key`). Use `task.get_dt()` and `task.get_stage()` to get data from it manually.
+ as a `key`). Use `task.get_dt()` and `task.get_stage()` to get data from it
+ manually.
"""
if isinstance(key, OnDemandTask):
@@ -553,9 +560,10 @@
Remove an on-demand task.
Args:
- key (str, callable, OnDemandTask or Object): The unique identifier for the task. If a callable, will
- be called without arguments. If an Object, will be converted to a string. If an `OnDemandTask`,
- then all other arguments are ignored and the task will be used to identify the task to remove.
+ key (str, callable, OnDemandTask or Object): The unique identifier for the task. If a
+ callable, will be called without arguments. If an Object, will be converted to a
+ string. If an `OnDemandTask`, then all other arguments are ignored and the task
+ will be used to identify the task to remove.
category (str or callable, optional): The category of the task.
Returns:
@@ -607,10 +615,10 @@
Clear all on-demand tasks.
Args:
- category (str, optional): The category of the tasks to clear. What `None` means is determined
- by the `all_on_none` kwarg.
- all_on_none (bool, optional): Determines what to clear if `category` is `None`. If `True`,
- clear all tasks, if `False`, only clear tasks with no category.
+ category (str, optional): The category of the tasks to clear. What `None` means is
+ determined by the `all_on_none` kwarg.
+ all_on_none (bool, optional): Determines what to clear if `category` is `None`. If
+ `True`, clear all tasks, if `False`, only clear tasks with no category.
"""
if category is None and all_on_none:
@@ -628,9 +636,9 @@
Args:
key (str, callable, OnDemandTask or Object): The unique identifier for the task. If a
- callable, will be called without arguments. If an Object, will be converted to a string.
- If an `OnDemandTask`, then all other arguments are ignored and the task will be used
- (only useful to check the task is the same).
+ callable, will be called without arguments. If an Object, will be converted to a
+ string. If an `OnDemandTask`, then all other arguments are ignored and the task
+ will be used (only useful to check the task is the same).
category (str, optional): The category of the task. If unset, this will only return
tasks with no category.
@@ -641,22 +649,23 @@
"""
return self.tasks.get(self._build_key(key, category))search_index_entry = {'aliases': 'pemit remit', 'category': 'admin', 'key': 'emit', 'no_prefix': ' pemit remit', 'tags': '', 'text': '\n admin command for emitting message to multiple objects\n\n Usage:\n emit[/switches] [<obj>, <obj>, ... =] <message>\n remit [<obj>, <obj>, ... =] <message>\n pemit [<obj>, <obj>, ... =] <message>\n\n Switches:\n room - limit emits to rooms only (default)\n accounts - limit emits to accounts only\n contents - send to the contents of matched objects too\n\n Emits a message to the selected objects or to\n your immediate surroundings. If the object is a room,\n send to its contents. remit and pemit are just\n limited forms of emit, for sending to rooms and\n to accounts respectively.\n '}¶search_index_entry = {'aliases': 'remit pemit', 'category': 'admin', 'key': 'emit', 'no_prefix': ' remit pemit', 'tags': '', 'text': '\n admin command for emitting message to multiple objects\n\n Usage:\n emit[/switches] [<obj>, <obj>, ... =] <message>\n remit [<obj>, <obj>, ... =] <message>\n pemit [<obj>, <obj>, ... =] <message>\n\n Switches:\n room - limit emits to rooms only (default)\n accounts - limit emits to accounts only\n contents - send to the contents of matched objects too\n\n Emits a message to the selected objects or to\n your immediate surroundings. If the object is a room,\n send to its contents. remit and pemit are just\n limited forms of emit, for sending to rooms and\n to accounts respectively.\n '}¶
search_index_entry = {'aliases': 'batchcmd batchcommand', 'category': 'building', 'key': 'batchcommands', 'no_prefix': ' batchcmd batchcommand', 'tags': '', 'text': '\n build from batch-command file\n\n Usage:\n batchcommands[/interactive] <python.path.to.file>\n\n Switch:\n interactive - this mode will offer more control when\n executing the batch file, like stepping,\n skipping, reloading etc.\n\n Runs batches of commands from a batch-cmd text file (*.ev).\n\n '}¶search_index_entry = {'aliases': 'batchcommand batchcmd', 'category': 'building', 'key': 'batchcommands', 'no_prefix': ' batchcommand batchcmd', 'tags': '', 'text': '\n build from batch-command file\n\n Usage:\n batchcommands[/interactive] <python.path.to.file>\n\n Switch:\n interactive - this mode will offer more control when\n executing the batch file, like stepping,\n skipping, reloading etc.\n\n Runs batches of commands from a batch-cmd text file (*.ev).\n\n '}¶
search_index_entry = {'aliases': '@del @delete', 'category': 'building', 'key': '@destroy', 'no_prefix': 'destroy del delete', 'tags': '', 'text': '\n permanently delete objects\n\n Usage:\n destroy[/switches] [obj, obj2, obj3, [dbref-dbref], ...]\n\n Switches:\n override - The destroy command will usually avoid accidentally\n destroying account objects. This switch overrides this safety.\n force - destroy without confirmation.\n Examples:\n destroy house, roof, door, 44-78\n destroy 5-10, flower, 45\n destroy/force north\n\n Destroys one or many objects. If dbrefs are used, a range to delete can be\n given, e.g. 4-10. Also the end points will be deleted. This command\n displays a confirmation before destroying, to make sure of your choice.\n You can specify the /force switch to bypass this confirmation.\n '}¶search_index_entry = {'aliases': '@delete @del', 'category': 'building', 'key': '@destroy', 'no_prefix': 'destroy delete del', 'tags': '', 'text': '\n permanently delete objects\n\n Usage:\n destroy[/switches] [obj, obj2, obj3, [dbref-dbref], ...]\n\n Switches:\n override - The destroy command will usually avoid accidentally\n destroying account objects. This switch overrides this safety.\n force - destroy without confirmation.\n Examples:\n destroy house, roof, door, 44-78\n destroy 5-10, flower, 45\n destroy/force north\n\n Destroys one or many objects. If dbrefs are used, a range to delete can be\n given, e.g. 4-10. Also the end points will be deleted. This command\n displays a confirmation before destroying, to make sure of your choice.\n You can specify the /force switch to bypass this confirmation.\n '}¶
aliases = ['@typeclasses', '@type', '@update', '@parent', '@swap']¶aliases = ['@parent', '@update', '@typeclasses', '@swap', '@type']¶
search_index_entry = {'aliases': '@typeclasses @type @update @parent @swap', 'category': 'building', 'key': '@typeclass', 'no_prefix': 'typeclass typeclasses type update parent swap', 'tags': '', 'text': "\n set or change an object's typeclass\n\n Usage:\n typeclass[/switch] <object> [= typeclass.path]\n typeclass/prototype <object> = prototype_key\n\n typeclasses or typeclass/list/show [typeclass.path]\n swap - this is a shorthand for using /force/reset flags.\n update - this is a shorthand for using the /force/reload flag.\n\n Switch:\n show, examine - display the current typeclass of object (default) or, if\n given a typeclass path, show the docstring of that typeclass.\n update - *only* re-run at_object_creation on this object\n meaning locks or other properties set later may remain.\n reset - clean out *all* the attributes and properties on the\n object - basically making this a new clean object. This will also\n reset cmdsets!\n force - change to the typeclass also if the object\n already has a typeclass of the same name.\n list - show available typeclasses. Only typeclasses in modules actually\n imported or used from somewhere in the code will show up here\n (those typeclasses are still available if you know the path)\n prototype - clean and overwrite the object with the specified\n prototype key - effectively making a whole new object.\n\n Example:\n type button = examples.red_button.RedButton\n type/prototype button=a red button\n\n If the typeclass_path is not given, the current object's typeclass is\n assumed.\n\n View or set an object's typeclass. If setting, the creation hooks of the\n new typeclass will be run on the object. If you have clashing properties on\n the old class, use /reset. By default you are protected from changing to a\n typeclass of the same name as the one you already have - use /force to\n override this protection.\n\n The given typeclass must be identified by its location using python\n dot-notation pointing to the correct module and class. If no typeclass is\n given (or a wrong typeclass is given). Errors in the path or new typeclass\n will lead to the old typeclass being kept. The location of the typeclass\n module is searched from the default typeclass directory, as defined in the\n server settings.\n\n "}¶search_index_entry = {'aliases': '@parent @update @typeclasses @swap @type', 'category': 'building', 'key': '@typeclass', 'no_prefix': 'typeclass parent update typeclasses swap type', 'tags': '', 'text': "\n set or change an object's typeclass\n\n Usage:\n typeclass[/switch] <object> [= typeclass.path]\n typeclass/prototype <object> = prototype_key\n\n typeclasses or typeclass/list/show [typeclass.path]\n swap - this is a shorthand for using /force/reset flags.\n update - this is a shorthand for using the /force/reload flag.\n\n Switch:\n show, examine - display the current typeclass of object (default) or, if\n given a typeclass path, show the docstring of that typeclass.\n update - *only* re-run at_object_creation on this object\n meaning locks or other properties set later may remain.\n reset - clean out *all* the attributes and properties on the\n object - basically making this a new clean object. This will also\n reset cmdsets!\n force - change to the typeclass also if the object\n already has a typeclass of the same name.\n list - show available typeclasses. Only typeclasses in modules actually\n imported or used from somewhere in the code will show up here\n (those typeclasses are still available if you know the path)\n prototype - clean and overwrite the object with the specified\n prototype key - effectively making a whole new object.\n\n Example:\n type button = examples.red_button.RedButton\n type/prototype button=a red button\n\n If the typeclass_path is not given, the current object's typeclass is\n assumed.\n\n View or set an object's typeclass. If setting, the creation hooks of the\n new typeclass will be run on the object. If you have clashing properties on\n the old class, use /reset. By default you are protected from changing to a\n typeclass of the same name as the one you already have - use /force to\n override this protection.\n\n The given typeclass must be identified by its location using python\n dot-notation pointing to the correct module and class. If no typeclass is\n given (or a wrong typeclass is given). Errors in the path or new typeclass\n will lead to the old typeclass being kept. The location of the typeclass\n module is searched from the default typeclass directory, as defined in the\n server settings.\n\n "}¶
search_index_entry = {'aliases': '@exam @ex', 'category': 'building', 'key': '@examine', 'no_prefix': 'examine exam ex', 'tags': '', 'text': '\n get detailed information about an object\n\n Usage:\n examine [<object>[/attrname]]\n examine [*<account>[/attrname]]\n\n Switch:\n account - examine an Account (same as adding *)\n object - examine an Object (useful when OOC)\n script - examine a Script\n channel - examine a Channel\n\n The examine command shows detailed game info about an\n object and optionally a specific attribute on it.\n If object is not specified, the current location is examined.\n\n Append a * before the search string to examine an account.\n\n '}¶search_index_entry = {'aliases': '@ex @exam', 'category': 'building', 'key': '@examine', 'no_prefix': 'examine ex exam', 'tags': '', 'text': '\n get detailed information about an object\n\n Usage:\n examine [<object>[/attrname]]\n examine [*<account>[/attrname]]\n\n Switch:\n account - examine an Account (same as adding *)\n object - examine an Object (useful when OOC)\n script - examine a Script\n channel - examine a Channel\n\n The examine command shows detailed game info about an\n object and optionally a specific attribute on it.\n If object is not specified, the current location is examined.\n\n Append a * before the search string to examine an account.\n\n '}¶
search_index_entry = {'aliases': '@channels @chan', 'category': 'comms', 'key': '@channel', 'no_prefix': 'channel channels chan', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}¶search_index_entry = {'aliases': '@chan @channels', 'category': 'comms', 'key': '@channel', 'no_prefix': 'channel chan channels', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}¶
search_index_entry = {'aliases': '@channels @chan', 'category': 'comms', 'key': '@channel', 'no_prefix': 'channel channels chan', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}¶search_index_entry = {'aliases': '@chan @channels', 'category': 'comms', 'key': '@channel', 'no_prefix': 'channel chan channels', 'tags': '', 'text': "\n Use and manage in-game channels.\n\n Usage:\n channel channelname <msg>\n channel channel name = <msg>\n channel (show all subscription)\n channel/all (show available channels)\n channel/alias channelname = alias[;alias...]\n channel/unalias alias\n channel/who channelname\n channel/history channelname [= index]\n channel/sub channelname [= alias[;alias...]]\n channel/unsub channelname[,channelname, ...]\n channel/mute channelname[,channelname,...]\n channel/unmute channelname[,channelname,...]\n\n channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n channel/desc channelname = description\n channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n channel/ban channelname (list bans)\n channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]\n channel/unban[/quiet] channelname[, channelname, ...] = subscribername\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n\n # subtopics\n\n ## sending\n\n Usage: channel channelname msg\n channel channel name = msg (with space in channel name)\n\n This sends a message to the channel. Note that you will rarely use this\n command like this; instead you can use the alias\n\n channelname <msg>\n channelalias <msg>\n\n For example\n\n public Hello World\n pub Hello World\n\n (this shortcut doesn't work for aliases containing spaces)\n\n See channel/alias for help on setting channel aliases.\n\n ## alias and unalias\n\n Usage: channel/alias channel = alias[;alias[;alias...]]\n channel/unalias alias\n channel - this will list your subs and aliases to each channel\n\n Set one or more personal aliases for referencing a channel. For example:\n\n channel/alias warrior's guild = warrior;wguild;warchannel;warrior guild\n\n You can now send to the channel using all of these:\n\n warrior's guild Hello\n warrior Hello\n wguild Hello\n warchannel Hello\n\n Note that this will not work if the alias has a space in it. So the\n 'warrior guild' alias must be used with the `channel` command:\n\n channel warrior guild = Hello\n\n Channel-aliases can be removed one at a time, using the '/unalias' switch.\n\n ## who\n\n Usage: channel/who channelname\n\n List the channel's subscribers. Shows who are currently offline or are\n muting the channel. Subscribers who are 'muting' will not see messages sent\n to the channel (use channel/mute to mute a channel).\n\n ## history\n\n Usage: channel/history channel [= index]\n\n This will display the last |c20|n lines of channel history. By supplying an\n index number, you will step that many lines back before viewing those 20 lines.\n\n For example:\n\n channel/history public = 35\n\n will go back 35 lines and show the previous 20 lines from that point (so\n lines -35 to -55).\n\n ## sub and unsub\n\n Usage: channel/sub channel [=alias[;alias;...]]\n channel/unsub channel\n\n This subscribes you to a channel and optionally assigns personal shortcuts\n for you to use to send to that channel (see aliases). When you unsub, all\n your personal aliases will also be removed.\n\n ## mute and unmute\n\n Usage: channel/mute channelname\n channel/unmute channelname\n\n Muting silences all output from the channel without actually\n un-subscribing. Other channel members will see that you are muted in the /who\n list. Sending a message to the channel will automatically unmute you.\n\n ## create and destroy\n\n Usage: channel/create channelname[;alias;alias[:typeclass]] [= description]\n channel/destroy channelname [= reason]\n\n Creates a new channel (or destroys one you control). You will automatically\n join the channel you create and everyone will be kicked and loose all aliases\n to a destroyed channel.\n\n ## lock and unlock\n\n Usage: channel/lock channelname = lockstring\n channel/unlock channelname = lockstring\n\n Note: this is an admin command.\n\n A lockstring is on the form locktype:lockfunc(). Channels understand three\n locktypes:\n listen - who may listen or join the channel.\n send - who may send messages to the channel\n control - who controls the channel. This is usually the one creating\n the channel.\n\n Common lockfuncs are all() and perm(). To make a channel everyone can\n listen to but only builders can talk on, use this:\n\n listen:all()\n send: perm(Builders)\n\n ## boot and ban\n\n Usage:\n channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]\n channel/ban channelname[, channelname, ...] = subscribername [: reason]\n channel/unban channelname[, channelname, ...] = subscribername\n channel/unban channelname\n channel/ban channelname (list bans)\n\n Booting will kick a named subscriber from channel(s) temporarily. The\n 'reason' will be passed to the booted user. Unless the /quiet switch is\n used, the channel will also be informed of the action. A booted user is\n still able to re-connect, but they'll have to set up their aliases again.\n\n Banning will blacklist a user from (re)joining the provided channels. It\n will then proceed to boot them from those channels if they were connected.\n The 'reason' and `/quiet` works the same as for booting.\n\n Example:\n boot mychannel1 = EvilUser : Kicking you to cool down a bit.\n ban mychannel1,mychannel2= EvilUser : Was banned for spamming.\n\n "}¶
search_index_entry = {'aliases': ': emote', 'category': 'general', 'key': 'pose', 'no_prefix': ' : emote', 'tags': '', 'text': "\n strike a pose\n\n Usage:\n pose <pose text>\n pose's <pose text>\n\n Example:\n pose is standing by the wall, smiling.\n -> others will see:\n Tom is standing by the wall, smiling.\n\n Describe an action being taken. The pose text will\n automatically begin with your name.\n "}¶search_index_entry = {'aliases': 'emote :', 'category': 'general', 'key': 'pose', 'no_prefix': ' emote :', 'tags': '', 'text': "\n strike a pose\n\n Usage:\n pose <pose text>\n pose's <pose text>\n\n Example:\n pose is standing by the wall, smiling.\n -> others will see:\n Tom is standing by the wall, smiling.\n\n Describe an action being taken. The pose text will\n automatically begin with your name.\n "}¶
search_index_entry = {'aliases': 'hierarchy groups', 'category': 'general', 'key': 'access', 'no_prefix': ' hierarchy groups', 'tags': '', 'text': '\n show your current game access\n\n Usage:\n access\n\n This command shows you the permission hierarchy and\n which permission groups you are a member of.\n '}¶search_index_entry = {'aliases': 'groups hierarchy', 'category': 'general', 'key': 'access', 'no_prefix': ' groups hierarchy', 'tags': '', 'text': '\n show your current game access\n\n Usage:\n access\n\n This command shows you the permission hierarchy and\n which permission groups you are a member of.\n '}¶
Test the batch processor.
red_button = <module 'evennia.contrib.tutorials.red_button.red_button' from '/tmp/tmplcp4h0sa/34b5f1133cd6ff4cd29f6d909ef3387fce667288/evennia/contrib/tutorials/red_button/red_button.py'>¶
search_index_entry = {'aliases': 'conn con co', 'category': 'general', 'key': 'connect', 'no_prefix': ' conn con co', 'tags': '', 'text': '\n connect to the game\n\n Usage (at login screen):\n connect accountname password\n connect "account name" "pass word"\n\n Use the create command to first create an account before logging in.\n\n If you have spaces in your name, enclose it in double quotes.\n '}¶search_index_entry = {'aliases': 'co conn con', 'category': 'general', 'key': 'connect', 'no_prefix': ' co conn con', 'tags': '', 'text': '\n connect to the game\n\n Usage (at login screen):\n connect accountname password\n connect "account name" "pass word"\n\n Use the create command to first create an account before logging in.\n\n If you have spaces in your name, enclose it in double quotes.\n '}¶
search_index_entry = {'aliases': 'l look', 'category': 'general', 'key': '__unloggedin_look_command', 'no_prefix': ' l look', 'tags': '', 'text': '\n look when in unlogged-in state\n\n Usage:\n look\n\n This is an unconnected version of the look command for simplicity.\n\n This is called by the server and kicks everything in gear.\n All it does is display the connect screen.\n '}¶search_index_entry = {'aliases': 'look l', 'category': 'general', 'key': '__unloggedin_look_command', 'no_prefix': ' look l', 'tags': '', 'text': '\n look when in unlogged-in state\n\n Usage:\n look\n\n This is an unconnected version of the look command for simplicity.\n\n This is called by the server and kicks everything in gear.\n All it does is display the connect screen.\n '}¶
search_index_entry = {'aliases': 'h ?', 'category': 'general', 'key': 'help', 'no_prefix': ' h ?', 'tags': '', 'text': '\n get help when in unconnected-in state\n\n Usage:\n help\n\n This is an unconnected version of the help command,\n for simplicity. It shows a pane of info.\n '}¶search_index_entry = {'aliases': '? h', 'category': 'general', 'key': 'help', 'no_prefix': ' ? h', 'tags': '', 'text': '\n get help when in unconnected-in state\n\n Usage:\n help\n\n This is an unconnected version of the help command,\n for simplicity. It shows a pane of info.\n '}¶
search_index_entry = {'aliases': 'conn con co', 'category': 'general', 'key': 'connect', 'no_prefix': ' conn con co', 'tags': '', 'text': '\n Connect to the game.\n\n Usage (at login screen):\n connect <email> <password>\n\n Use the create command to first create an account before logging in.\n '}¶search_index_entry = {'aliases': 'co conn con', 'category': 'general', 'key': 'connect', 'no_prefix': ' co conn con', 'tags': '', 'text': '\n Connect to the game.\n\n Usage (at login screen):\n connect <email> <password>\n\n Use the create command to first create an account before logging in.\n '}¶
search_index_entry = {'aliases': 'l look', 'category': 'general', 'key': '__unloggedin_look_command', 'no_prefix': ' l look', 'tags': '', 'text': '\n This is an unconnected version of the `look` command for simplicity.\n\n This is called by the server and kicks everything in gear.\n All it does is display the connect screen.\n '}¶search_index_entry = {'aliases': 'look l', 'category': 'general', 'key': '__unloggedin_look_command', 'no_prefix': ' look l', 'tags': '', 'text': '\n This is an unconnected version of the `look` command for simplicity.\n\n This is called by the server and kicks everything in gear.\n All it does is display the connect screen.\n '}¶
search_index_entry = {'aliases': 'h ?', 'category': 'general', 'key': 'help', 'no_prefix': ' h ?', 'tags': '', 'text': '\n This is an unconnected version of the help command,\n for simplicity. It shows a pane of info.\n '}¶search_index_entry = {'aliases': '? h', 'category': 'general', 'key': 'help', 'no_prefix': ' ? h', 'tags': '', 'text': '\n This is an unconnected version of the help command,\n for simplicity. It shows a pane of info.\n '}¶
search_index_entry = {'aliases': '@callbacks @callback @calls', 'category': 'building', 'key': '@call', 'no_prefix': 'call callbacks callback calls', 'tags': '', 'text': '\n Command to edit callbacks.\n '}¶search_index_entry = {'aliases': '@callbacks @calls @callback', 'category': 'building', 'key': '@call', 'no_prefix': 'call callbacks calls callback', 'tags': '', 'text': '\n Command to edit callbacks.\n '}¶
search_index_entry = {'aliases': 'aliaschan chanalias', 'category': 'comms', 'key': 'addcom', 'no_prefix': ' aliaschan chanalias', 'tags': '', 'text': '\n Add a channel alias and/or subscribe to a channel\n\n Usage:\n addcom [alias=] <channel>\n\n Joins a given channel. If alias is given, this will allow you to\n refer to the channel by this alias rather than the full channel\n name. Subsequent calls of this command can be used to add multiple\n aliases to an already joined channel.\n '}¶search_index_entry = {'aliases': 'chanalias aliaschan', 'category': 'comms', 'key': 'addcom', 'no_prefix': ' chanalias aliaschan', 'tags': '', 'text': '\n Add a channel alias and/or subscribe to a channel\n\n Usage:\n addcom [alias=] <channel>\n\n Joins a given channel. If alias is given, this will allow you to\n refer to the channel by this alias rather than the full channel\n name. Subsequent calls of this command can be used to add multiple\n aliases to an already joined channel.\n '}¶
search_index_entry = {'aliases': '; shout whisper', 'category': 'general', 'key': 'say', 'no_prefix': ' ; shout whisper', 'tags': '', 'text': '\n Perform an communication action.\n\n Usage:\n say <text>\n whisper\n shout\n\n '}¶search_index_entry = {'aliases': '; whisper shout', 'category': 'general', 'key': 'say', 'no_prefix': ' ; whisper shout', 'tags': '', 'text': '\n Perform an communication action.\n\n Usage:\n say <text>\n whisper\n shout\n\n '}¶
search_index_entry = {'aliases': ': pose', 'category': 'general', 'key': 'emote', 'no_prefix': ' : pose', 'tags': '', 'text': '\n Perform a free-form emote. Use /me to\n include yourself in the emote and /name\n to include other objects or characters.\n Use "..." to enact speech.\n\n Usage:\n emote <emote>\n :<emote\n\n Example:\n emote /me smiles at /peter\n emote /me points to /box and /lever.\n\n '}¶search_index_entry = {'aliases': 'pose :', 'category': 'general', 'key': 'emote', 'no_prefix': ' pose :', 'tags': '', 'text': '\n Perform a free-form emote. Use /me to\n include yourself in the emote and /name\n to include other objects or characters.\n Use "..." to enact speech.\n\n Usage:\n emote <emote>\n :<emote\n\n Example:\n emote /me smiles at /peter\n emote /me points to /box and /lever.\n\n '}¶
search_index_entry = {'aliases': 'ex e examine unfocus', 'category': 'evscaperoom', 'key': 'focus', 'no_prefix': ' ex e examine unfocus', 'tags': '', 'text': '\n Focus your attention on a target.\n\n Usage:\n focus <obj>\n\n Once focusing on an object, use look to get more information about how it\n looks and what actions is available.\n\n '}¶search_index_entry = {'aliases': 'unfocus ex examine e', 'category': 'evscaperoom', 'key': 'focus', 'no_prefix': ' unfocus ex examine e', 'tags': '', 'text': '\n Focus your attention on a target.\n\n Usage:\n focus <obj>\n\n Once focusing on an object, use look to get more information about how it\n looks and what actions is available.\n\n '}¶
search_index_entry = {'aliases': 'inv give inventory i', 'category': 'evscaperoom', 'key': 'get', 'no_prefix': ' inv give inventory i', 'tags': '', 'text': '\n Use focus / examine instead.\n\n '}¶search_index_entry = {'aliases': 'i inventory inv give', 'category': 'evscaperoom', 'key': 'get', 'no_prefix': ' i inventory inv give', 'tags': '', 'text': '\n Use focus / examine instead.\n\n '}¶
search_index_entry = {'aliases': 'fly dive', 'category': 'general', 'key': 'fly or dive', 'no_prefix': ' fly dive', 'tags': '', 'text': '\n Fly or Dive up and down.\n\n Usage:\n fly\n dive\n\n Will fly up one room or dive down one room at your current position. If\n there is no room above/below you, your movement will fail.\n\n '}¶search_index_entry = {'aliases': 'dive fly', 'category': 'general', 'key': 'fly or dive', 'no_prefix': ' dive fly', 'tags': '', 'text': '\n Fly or Dive up and down.\n\n Usage:\n fly\n dive\n\n Will fly up one room or dive down one room at your current position. If\n there is no room above/below you, your movement will fail.\n\n '}¶
search_index_entry = {'aliases': 'turnbased combat hit', 'category': 'general', 'key': 'attack', 'no_prefix': ' turnbased combat hit', 'tags': '', 'text': '\n Start or join combat.\n\n Usage:\n attack [<target>]\n\n '}¶search_index_entry = {'aliases': 'hit turnbased combat', 'category': 'general', 'key': 'attack', 'no_prefix': ' hit turnbased combat', 'tags': '', 'text': '\n Start or join combat.\n\n Usage:\n attack [<target>]\n\n '}¶
search_index_entry = {'aliases': 'inv i', 'category': 'general', 'key': 'inventory', 'no_prefix': ' inv i', 'tags': '', 'text': '\n View your inventory\n\n Usage:\n inventory\n\n '}¶search_index_entry = {'aliases': 'i inv', 'category': 'general', 'key': 'inventory', 'no_prefix': ' i inv', 'tags': '', 'text': '\n View your inventory\n\n Usage:\n inventory\n\n '}¶
aliases = ['break lid', 'smash lid', 'smash']¶
search_index_entry = {'aliases': 'break lid smash lid smash', 'category': 'general', 'key': 'smash glass', 'no_prefix': ' break lid smash lid smash', 'tags': '', 'text': '\n Smash the protective glass.\n\n Usage:\n smash glass\n\n Try to smash the glass of the button.\n\n '}¶
aliases = ['ex', 'examine', 'get', 'listen', 'feel', 'l']¶
search_index_entry = {'aliases': 'ex examine get listen feel l', 'category': 'general', 'key': 'look', 'no_prefix': ' ex examine get listen feel l', 'tags': '', 'text': "\n Looking around in darkness\n\n Usage:\n look <obj>\n\n ... not that there's much to see in the dark.\n\n "}¶
search_index_entry = {'aliases': 'light burn', 'category': 'tutorialworld', 'key': 'on', 'no_prefix': ' light burn', 'tags': '', 'text': '\n Creates light where there was none. Something to burn.\n '}¶search_index_entry = {'aliases': 'burn light', 'category': 'tutorialworld', 'key': 'on', 'no_prefix': ' burn light', 'tags': '', 'text': '\n Creates light where there was none. Something to burn.\n '}¶
search_index_entry = {'aliases': 'move shiftroot pull push', 'category': 'tutorialworld', 'key': 'shift', 'no_prefix': ' move shiftroot pull push', 'tags': '', 'text': '\n Shifts roots around.\n\n Usage:\n shift blue root left/right\n shift red root left/right\n shift yellow root up/down\n shift green root up/down\n\n '}¶search_index_entry = {'aliases': 'shiftroot pull move push', 'category': 'tutorialworld', 'key': 'shift', 'no_prefix': ' shiftroot pull move push', 'tags': '', 'text': '\n Shifts roots around.\n\n Usage:\n shift blue root left/right\n shift red root left/right\n shift yellow root up/down\n shift green root up/down\n\n '}¶
aliases = ['defend', 'pierce', 'slash', 'fight', 'kill', 'hit', 'stab', 'chop', 'bash', 'thrust', 'parry']¶aliases = ['parry', 'hit', 'defend', 'kill', 'thrust', 'stab', 'chop', 'slash', 'fight', 'bash', 'pierce']¶
search_index_entry = {'aliases': 'defend pierce slash fight kill hit stab chop bash thrust parry', 'category': 'tutorialworld', 'key': 'attack', 'no_prefix': ' defend pierce slash fight kill hit stab chop bash thrust parry', 'tags': '', 'text': '\n Attack the enemy. Commands:\n\n stab <enemy>\n slash <enemy>\n parry\n\n stab - (thrust) makes a lot of damage but is harder to hit with.\n slash - is easier to land, but does not make as much damage.\n parry - forgoes your attack but will make you harder to hit on next\n enemy attack.\n\n '}¶search_index_entry = {'aliases': 'parry hit defend kill thrust stab chop slash fight bash pierce', 'category': 'tutorialworld', 'key': 'attack', 'no_prefix': ' parry hit defend kill thrust stab chop slash fight bash pierce', 'tags': '', 'text': '\n Attack the enemy. Commands:\n\n stab <enemy>\n slash <enemy>\n parry\n\n stab - (thrust) makes a lot of damage but is harder to hit with.\n slash - is easier to land, but does not make as much damage.\n parry - forgoes your attack but will make you harder to hit on next\n enemy attack.\n\n '}¶
search_index_entry = {'aliases': 'h ?', 'category': 'tutorial world', 'key': 'help', 'no_prefix': ' h ?', 'tags': '', 'text': '\n Overwritten help command while on the bridge.\n '}¶search_index_entry = {'aliases': '? h', 'category': 'tutorial world', 'key': 'help', 'no_prefix': ' ? h', 'tags': '', 'text': '\n Overwritten help command while on the bridge.\n '}¶
aliases = ['feel', 'search', 'l', 'fiddle', 'feel around']¶aliases = ['feel around', 'feel', 'fiddle', 'search', 'l']¶
search_index_entry = {'aliases': 'feel search l fiddle feel around', 'category': 'tutorialworld', 'key': 'look', 'no_prefix': ' feel search l fiddle feel around', 'tags': '', 'text': '\n Look around in darkness\n\n Usage:\n look\n\n Look around in the darkness, trying\n to find something.\n '}¶search_index_entry = {'aliases': 'feel around feel fiddle search l', 'category': 'tutorialworld', 'key': 'look', 'no_prefix': ' feel around feel fiddle search l', 'tags': '', 'text': '\n Look around in darkness\n\n Usage:\n look\n\n Look around in the darkness, trying\n to find something.\n '}¶
directory = '/tmp/tmp66rtn6r2/6e6ab208a6b53fc30dd91a6f83124e641d851601/evennia'¶directory = '/tmp/tmplcp4h0sa/34b5f1133cd6ff4cd29f6d909ef3387fce667288/evennia'¶
directory = '/tmp/tmp66rtn6r2/6e6ab208a6b53fc30dd91a6f83124e641d851601/evennia/game_template'¶directory = '/tmp/tmplcp4h0sa/34b5f1133cd6ff4cd29f6d909ef3387fce667288/evennia/game_template'¶
Helper to handle on-demand requests, allowing a system to change state only when a player or system actually needs the information. This is a very efficient way to handle gradual changes, requiring not computer resources until the state is actually needed.
-For example, consider a flowering system, where a seed sprouts, grows and blooms over a certain time. -One _could_ implement this with e.g. a Script or a ticker that gradually moves the flower along -its stages of growth. But what if that flower is in a remote location, and no one is around to see it? -You are then wasting computational resources on something that no one is looking at.
+For example, consider a flowering system, where a seed sprouts, grows and blooms over a certain +time. One _could_ implement this with e.g. a Script or a ticker that gradually moves the flower +along its stages of growth. But what if that flower is in a remote location, and no one is around to +see it? You are then wasting computational resources on something that no one is looking at.
The truth is that most of the time, players are not looking at most of the things in the game. They _only_ need to know about which state the flower is in when they are actually looking at it, or when they are in the same room as it (so it can be incorporated in the room description). This is @@ -154,8 +154,8 @@ up after a long time, it may not show as a “wilted” state or be outright del since too long time has passed and the plant has died.
With a system like this you could have growing plants all over your world and computing usage would -only scale by how many players you have exploring your world. The players will not know the difference -between this and a system that is always running, but your server will thank you.
+only scale by how many players you have exploring your world. The players will not know the +difference between this and a system that is always running, but your server will thank you.There is only one situation where this system is not ideal, and that is when a player should be informed of the state change _even if they perform no action_. That is, even if they are just idling in the room, they should get a message like ‘the plant suddenly blooms’ (or, more commonly, for @@ -186,11 +186,11 @@ handling instead.
Bases: object
Stores information about an on-demand task.
Default property: -- default_stage_function (callable): This is called if no stage function is given in the stages dict.
+- default_stage_function (callable): This is called if no stage function is given in the-This is meant for changing the task itself (such as restarting it). Actual game code should -be handled elsewhere, by checking this task. See the stagefunc_* static methods for examples -of how to manipulate the task when a stage is reached.
+stages dict. This is meant for changing the task itself (such as restarting it). Actual +game code should be handled elsewhere, by checking this task. See the stagefunc_* static +methods for examples of how to manipulate the task when a stage is reached.
- @@ -202,7 +202,7 @@ It’s a callable to allow easier unit testing.
- -static
+staticstagefunc_loop(task)[source]¶stagefunc_loop(task, **kwargs)[source]¶Attach this to the last stage to have the task start over from the beginning
Example
@@ -216,7 +216,7 @@ can an idea to mark that end state with a _ just to indicate th
- -static
+staticstagefunc_bounce(task)[source]¶stagefunc_bounce(task, **kwargs)[source]¶This endfunc will have the task reverse direction and go through the stages in reverse order. This stage-function must be placed at both ‘ends’ of the stage sequence for the bounce to continue indefinitely.
@@ -273,12 +273,15 @@ time will not start counting until the first call of get_dt or
- -
+check(autostart=True)[source]¶check(autostart=True, **kwargs)[source]¶Check the current stage of the task and return the time-delta to the next stage.
-
- Parameters
-autostart (bool, optional) – If this is set, and the task has not been started yet, -it will be started by this check. This is mainly used internally.
+- Keyword Arguments
++
- +
autostart (bool, optional) – If this is set, and the task has not been started yet, +it will be started by this check. This is mainly used internally.
- +
**kwargs – Will be passed to the stage function, if one is called.
- Returns
tuple – A tuple (dt, stage) where dt is the time-delta (in seconds) since the test @@ -291,11 +294,12 @@ current stage. If no stages are defined, stage will always be <
@@ -319,12 +323,13 @@ as normal, next time the state is checked and the stage is found to have changed
- -
+get_dt()[source]¶get_dt(**kwargs)[source]¶Get the time-delta since last check.
- Returns
-int – The time since the last check, or 0 if this is the first time the task is checked.
+int – The time since the last check, or 0 if this is the first time the task is checked. +**kwargs: Will be passed to the stage function, if one is called.
@@ -399,7 +404,8 @@ check and start the timer.
- -
+get_stage()[source]¶get_stage(**kwargs)[source]¶Get the current stage of the task. If no stage was given, this will return None but still update the last_checked time.
- Returns
-str or None – The current stage of the task, or None if no stages are set.
+str or None – The current stage of the task, or None if no stages are set. +**kwargs: Will be passed to the stage function, if one is called.
- Returns
OnDemandTask –
-
@@ -425,9 +431,10 @@ check and start the timer.- The created task (or the same that was added, if given an OnDemandTask
as a key). Use task.get_dt() and task.get_stage() to get data from it manually.
+- The created task (or the same that was added, if given an OnDemandTask
as a key). Use task.get_dt() and task.get_stage() to get data from it +manually.
- Parameters
- @@ -482,10 +489,10 @@ manually.
-
- +
key (str, callable, OnDemandTask or Object) – The unique identifier for the task. If a callable, will -be called without arguments. If an Object, will be converted to a string. If an OnDemandTask, -then all other arguments are ignored and the task will be used to identify the task to remove.
key (str, callable, OnDemandTask or Object) – The unique identifier for the task. If a +callable, will be called without arguments. If an Object, will be converted to a +string. If an OnDemandTask, then all other arguments are ignored and the task +will be used to identify the task to remove.
category (str or callable, optional) – The category of the task.
@@ -499,9 +506,9 @@ clear all tasks, if False, only clear tasks with no category.
- Parameters
-
- -
category (str, optional) – The category of the tasks to clear. What None means is determined -by the all_on_none kwarg.
- +
all_on_none (bool, optional) – Determines what to clear if category is None. If True, -clear all tasks, if False, only clear tasks with no category.
- +
category (str, optional) – The category of the tasks to clear. What None means is +determined by the all_on_none kwarg.
all_on_none (bool, optional) – Determines what to clear if category is None. If +True, clear all tasks, if False, only clear tasks with no category.
- Parameters
@@ -514,14 +521,17 @@ tasks with no category.
- +callable, will be called without arguments. If an Object, will be converted to a +string. If an OnDemandTask, then all other arguments are ignored and the task +will be used (only useful to check the task is the same).
key (str, callable, OnDemandTask or Object) – The unique identifier for the task. If a -callable, will be called without arguments. If an Object, will be converted to a string. -If an OnDemandTask, then all other arguments are ignored and the task will be used -(only useful to check the task is the same).
category (str, optional) – The category of the task. If unset, this will only return tasks with no category.
- -
+get_dt(key, category=None)[source]¶get_dt(key, category=None, **kwargs)[source]¶Get the time-delta since the task started.
diff --git a/docs/latest/objects.inv b/docs/latest/objects.inv index f2a584d2b67f57f92682dad1d1e2ae5f54a61e13..f311508a62902a0062629f810fc8b75c37cdff78 100644 GIT binary patch delta 69213 zcmV(;K-<65m
- Parameters
-key (str, callable, OnDemandTask or Object) – The unique identifier for the task. If a -callable, will be called without arguments. If an Object, will be converted to a string. -If an OnDemandTask, then all other arguments are ignored and the task will be used -to identify the task to get the time-delta from.
++
- +
key (str, callable, OnDemandTask or Object) – The unique identifier for the task. If a +callable, will be called without arguments. If an Object, will be converted to a +string. If an OnDemandTask, then all other arguments are ignored and the task +will be used to identify the task to get the time-delta from.
- +
**kwargs – Will be passed to the stage function, if one is called.
- Returns
int or None – The time since the last check, or None if no task was found.
@@ -539,9 +549,9 @@ somehow (like using a potion that speeds up the growth of a plant).- Parameters
- +callable, will be called without arguments. If an Object, will be converted to a +string. If an OnDemandTask, then all other arguments are ignored and the task will +be used to identify the task to set the time-delta for.
key (str, callable, OnDemandTask or Object) – The unique identifier for the task. If a -callable, will be called without arguments. If an Object, will be converted to a string. -If an OnDemandTask, then all other arguments are ignored and the task will be used -to identify the task to set the time-delta for.
category (str, optional) – The category of the task.
- @@ -555,14 +565,18 @@ as normal, next time the state is checked and the stage is found to have changed
dt (int) – The time-delta to set. This is an absolute value in seconds, same as returned by get_dt.
diff --git a/docs/latest/api/evennia.utils.evmore.html b/docs/latest/api/evennia.utils.evmore.html index 180e4d92b1..63ad995db0 100644 --- a/docs/latest/api/evennia.utils.evmore.html +++ b/docs/latest/api/evennia.utils.evmore.html @@ -149,7 +149,7 @@ the caller.msg() construct every time the page is updated.
- -
+get_stage(key, category=None)[source]¶get_stage(key, category=None, **kwargs)[source]¶Get the current stage of an on-demand task.
diff --git a/docs/latest/api/evennia.utils.evmenu.html b/docs/latest/api/evennia.utils.evmenu.html index 28d4574a61..39b826883a 100644 --- a/docs/latest/api/evennia.utils.evmenu.html +++ b/docs/latest/api/evennia.utils.evmenu.html @@ -951,7 +951,7 @@ single question.
- Parameters
-key (str, callable, OnDemandTask or Object) – The unique identifier for the task. If a -callable, will be called without arguments. If an Object, will be converted to a string. -If an OnDemandTask, then all other arguments are ignored and the task will be used -to identify the task to get the stage from.
++
- +
key (str, callable, OnDemandTask or Object) – The unique identifier for the task. If a +callable, will be called without arguments. If an Object, will be converted to a +string. If an OnDemandTask, then all other arguments are ignored and the task +will be used to identify the task to get the stage from.
- +
category (str, optional) – The category of the task.
- +
**kwargs – Will be passed to the stage function, if one is called.
- Returns
str or None – The current stage of the task, or None if no task was found.
diff --git a/docs/latest/api/evennia.utils.eveditor.html b/docs/latest/api/evennia.utils.eveditor.html index d7f3ebe5ed..c04eb366df 100644 --- a/docs/latest/api/evennia.utils.eveditor.html +++ b/docs/latest/api/evennia.utils.eveditor.html @@ -348,7 +348,7 @@ indentation.
- -
+aliases= [':uu', ':h', ':q!', ':dd', ':=', ':A', ':q', '::', ':f', ':', ':w', ':fi', ':::', ':s', ':I', ':wq', ':j', ':!', ':r', ':fd', ':i', ':DD', ':<', ':x', ':>', ':u', ':p', ':dw', ':S', ':echo', ':UU', ':y']¶aliases= [':I', ':i', ':', ':f', ':h', ':>', ':uu', ':A', ':y', ':S', ':fd', ':j', ':x', ':<', '::', ':::', ':echo', ':=', ':p', ':fi', ':dw', ':UU', ':q', ':u', ':r', ':w', ':dd', ':s', ':!', ':q!', ':DD', ':wq']¶@@ -376,7 +376,7 @@ efficient presentation.
- -
+search_index_entry= {'aliases': ':uu :h :q! :dd := :A :q :: :f : :w :fi ::: :s :I :wq :j :! :r :fd :i :DD :< :x :> :u :p :dw :S :echo :UU :y', 'category': 'general', 'key': ':editor_command_group', 'no_prefix': ' :uu :h :q! :dd := :A :q :: :f : :w :fi ::: :s :I :wq :j :! :r :fd :i :DD :< :x :> :u :p :dw :S :echo :UU :y', 'tags': '', 'text': '\n Commands for the editor\n '}¶search_index_entry= {'aliases': ':I :i : :f :h :> :uu :A :y :S :fd :j :x :< :: ::: :echo := :p :fi :dw :UU :q :u :r :w :dd :s :! :q! :DD :wq', 'category': 'general', 'key': ':editor_command_group', 'no_prefix': ' :I :i : :f :h :> :uu :A :y :S :fd :j :x :< :: ::: :echo := :p :fi :dw :UU :q :u :r :w :dd :s :! :q! :DD :wq', 'tags': '', 'text': '\n Commands for the editor\n '}¶+
aliases= ['y', 'abort', 'n', 'a', 'no', '__nomatch_command', 'yes']¶@@ -977,7 +977,7 @@ single question.
+
search_index_entry= {'aliases': 'y abort n a no __nomatch_command yes', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' y abort n a no __nomatch_command yes', 'tags': '', 'text': '\n Handle a prompt for yes or no. Press [return] for the default choice.\n\n '}¶
- -
+aliases= ['abort', 'quit', 'e', 'q', 'next', 'p', 'previous', 'n', 'top', 'end', 'a', 't']¶aliases= ['t', 'p', 'e', 'abort', 'n', 'a', 'previous', 'next', 'q', 'top', 'end', 'quit']¶@@ -175,7 +175,7 @@ the caller.msg() construct every time the page is updated.
- -
+search_index_entry= {'aliases': 'abort quit e q next p previous n top end a t', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' abort quit e q next p previous n top end a t', 'tags': '', 'text': '\n Manipulate the text paging. Catch no-input with aliases.\n '}¶search_index_entry= {'aliases': 't p e abort n a previous next q top end quit', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' t p e abort n a previous next q top end quit', 'tags': '', 'text': '\n Manipulate the text paging. Catch no-input with aliases.\n '}¶!v#j_q3{iSn~&-ksGlBan^3fA0cRK4`^Wg~ zPFJTnoWF)?Iy7x8dU2XXV*f^i!=>e-gF#Cog2P$w9FBYAN`efo-DAF%Q!3jKK?%WH zBE`Xiq^*VQ1`MV|7;>1U o{)7K;pttolpuHPW=wdhY%h ?SmL(nv(!f6Ib2zUR0k#g66%Fa((Wc$+m|2V_P6tH}nDG ~tn$lyokmtT-o=>;lNQb-st|V>Em|MFE@qmEs<# zNP{mH$gsj_qjTmuR>y^c!zNmdrEjA6+Ew!(sU51(OI(`{%Z`8HnXX^Ra~y{vCcP8* z3}NFJh~oLUV9&@L?3^vD5h;K4CAN%N#AE9j!Z>?86E7O= +i4@GO!Ki1y1rS@3HJtzE0R{slgN``gEZ31L38{Wb_|wM=JC)vf#TPD{ zyx#X2i`Qp5akhVT3h2lB1N=FX!<}vkVA8aQ-~mTKH|wU@S=SA@FYlDthe4XJmIe&h zRKS4 H7&ejj5eq}=O9eF4G{SHjnIqv!c)lT`|bF+#7L($hQ9Tb0C{= tc@(E60ruT<9zP2MYsEKZeV3K1sN_>6Wz}Ncz=w~YemeiS zy1Dp#d3}F-V`0{s@+fAbq}BtNvXnU2WP~?wf5~|2BtsaE{ O(%V4HC7X|u)a6z(|}#gmzFKK9S05;sE8Zmv+!kh zF}O7d?rT$vd-EmQ&=eU;-RR#QvPhQJo3?sAj3a+B%j%WbL|<&G%=$tM_vLk%eHf&1 zJLfSga8WvK6-cAr3aCNsT(~5ylQ4=#1a`+kPs12|qokhrW9HjzV@r7OVyO o3G}z)cIoE3xWi#bX0haPa2bh+-fZ zPUtqJX&_<(zYgtYj(~B45Vi*SGoh1X<_3SljYZf} yjn#`Ph1w)GAc zBpkbXo(LYoN&&;Oze8wY;3LENb|-uzxNHd0NJxgWcIn~JCNJ*qNkhQQfG}v*^&!#_ zoBkvHA~4^|pwd>F5;U;Z0`!lkgewpR_bU&Th){is^l!2_lzuA8GA+<1f4%SUfZ1I`?j!WH zBK!ugpk0F5et5 i+|yso4Nf8KG^ z$b$`ebTZ;7H+;n@Us%cQx~90>yY77JOl}N*I98k-r6ZJc>1oyKZeNtSa#eqtuvd#i z6|#x{#NEZkYT`*8JO@n>pes6dIW1ZlHwd1kCa4Sg3X>a|Td_gGho=MLl(GU0>kswu zD6?rYxWNmH`>nj0Q^zNi7v}>6NLT=V-$$&Bxiu_{3fns>Q}4m@Dh{dq4-O9$^uc^& z{>eG_$KjayWnxXeNjazsg;js{fHtTnaI``{)pZB2gYVM!O|~U+*l2E(453*IB|X4` zY1I)p(kns)P_h%p!dXD1_nJz!h}x8LBhI36ll#h?Lpdh=6Z;!Vx$ipH5|o>g3;)Fa z22!rGCZ9;iL@(g~P_nvo+`)E}q38wtA4mqq{U^qZiNZ4rp)tGPH@JVRO6RG$>)48$ zb^!98eJA`oP?Zg-NCTU4-7{{%lag$m@7y?bvZ8%p9?1>!NQ6hImQ9iSF15N9Qvg2D z--a8k4*I|Cw|8~d)YUZdUi^QEUxCE!E?ZA7AVT 1dd%kJz_aMN59u=lGKdwA$>8@J#W-r4$abhAVl+0xCsFBX(v_eC<;t z0$Q=BhP{0%EqZ_PQWMN(lmCr*^!C7bxg2QHx~>>Vf7vLvqtpC-7;KY8qsiMHf6^%g zR`GM$u<|y`*ktu;++}UC26=uw2G4}RZOl+b>;ON3PoEO(KneI*m3h( 0D^|jgH|*x@JX2bUZ4^Aub76l(2X=sV pJGr30_GYijsF_)--5qcZlZ>`v7%BPVLaUR)h1^7HN0M>jt^ zeacG?Vzp5^nB=)0?AR*zLVa4dF3imCrjAlT3MngsAL+M;3Re_i9qO*!H+ON216fXd zi_4I(bcKJ;Zho37m~S|bW(#6`N*ASy1BPqGLnJIj!mjE*m*eS*P*9vihvinZ%&=uc zID`u<8y<{z;^=#Q&x}88+31vcTlCt%Q)W*}i|ExtlL%-aw{>3JKZ~KX7zajCx*@KF zFBVc^^YS;RQhT&)?^`?RHBiF;3U?vz4XY+SHnV?okaaN?e >61BCR7tx~1e zwBPtl)}$Cs68+)11v$A2ma$ViJ6tShL4tU(Syx`9v80Dj6CL9mKEU`1yQmzdMP5+F z4_9Oe^Ok?ds?)DYvZRFr&1s|N)&%9;p!4LWa;dzUtfz{9A?~67Kk$Y3Xu}ktn%5h? zLBR&fO ;Mcg&@Q)@5v2J%2a z6ix8;Q-Y>{kZCCP1USr2c&ISNaX^vscWowVsv}6%;J{m!aA&_R=v2y_icvxljmbN1 zQaXxH%G~fD3Im(A8jBfv@zRCAhho^BRBeIN<9%b*sRz=7pZ{`mneY!2Hb09EU2y<( zA6gvVhCcd#|92yDA8ijP3uur3S2~W~zW(9Ih%^{~iTo#bK$<~XupcQL7=A3slO?AH zp+u(9rd;?rFxjZUG0QXK3z_q^KDRUCuc41wbDuaGT{I?A 2I7ij?Uc7ZA5q{ z9QjSvM(?mqnuucs(^6n0Ee<2B!_tAh^2VlRj^5ZzJ`}#iH{s;BMqLqHmQCT11hKU$ zgHUIGVriAXG`W@ma3PJf4hGGxEMKUk-A+sAO{B6%)1ZI@Mp~6+uaDtl73kwvj72H! zqm;IN%EYK<1v)6*1S(D|@i~J$&Gxi&-0gQe(m9KYM^Oi)qB0MKV>dmNPx;Z~ak#JQ z9uHWQc0!F`pToV{(fGim Jp{CF@QWp!t!OK7dT=xLC3~Loz4oZWP{m;&@q83MU8z2& zU<;4W+n}5E^#&K!SlGo)3p{(0E-Q=Q`$z7^ks1dS5gYrs3AE;s@4uGxb8pxo^wHaY zfn@v0yGP;S*X^Nz!^*Hn-OzDiX?*$5tCtbvXK=(_?%vU_PhrcX7=4T&)ACL#-&@0q zR>y>K+q;SLLA^43V!O+@edJ*QRs8$=9NaMhS0faE#FTG%q*+<>=2r5IBQ<1l0Q7q) z3Ho4L?Np|y*31mGcpSCc@9aJENEMrZ_$7B2T|~m%9cpZ9dp}^HWx+4mUmvVERTq`Y zMp;fM&fNLZ*7jzYozwhem>GZDZc(n$nGn5^oTEXa - _j_lQ+UIK|hlsgX`lk*em7j(g0Q5@`F3*=qqofn$(fj=kNgC zwohue7Dh2?v<}bQZLN7B^$uZD0=sj#<`ZDN536NS2#rfxF5|$3S}lW(il|G;@+L8h z0uKEhmuwA+#h|H6)$(>SPdw~@*0ejgBgJ)7EO7
0p 3YrxR{PtWN)WvyaZ0?k2x#R^x-UN;6)Upoww z+&zz%C@dH_^F#z@q>dq^ch8>16NgGZz+jC5<6Xrb@iSLVJqTY~0c`1JgOjF{>QpRd zlay#=hDeX;Tp(yQsZOL H>~G zf3F=U3VW6~G(Kj392m$_pM!t_E(>hX{C62`r%EiCE&AvShcw)kV~D3pu;ec)wY-A~ z72LppAL;pTH#frcvzAM?VEl;kZ#U9nw7BMM7lDrIsg;JOjhC$5ga-L&74U^7I#tLz zcy w+%HAAEjLCNU?%Pkeewzp{JF;B qjEBUbcirXlRoW5vlf)819f_oREJR;i*GMfuRo79`zdR>(b;cP5OL9g1-JA* zJSg6JfL~!9pF%K@3#Kb_lC?ORsdnp>f%tP+CAJ}dT!K3eeSW#VNTj<{nedvbX%ODx z_gsC`QdIYK1lvHcZ;;^A#b~sP j!>ttM(N`HK-_#)Gg`dl^1o~(pW;N zODdhL&-wV(utOc9UsyVim2szcoj>1O4zM^vs&68RNO-_;C#3HD={e%zV!za#F` N0=t&5hMm-@J=qkE&1l0JO06^K-)E>+Tep^MNOxx&r_9g z0HI B087|FAL!w&`7eC|qoyC~}l1|hZSoeKw_Ds`cJ zxS4PfD~1FGF4$iewAf;XRp7{+G04h2Y1qH@<{4kB3K| lat z;U5PsJNhklYTF5Q&5H0rdO&$>!)n)t&haAiu^0J3XM?_6dmtrTle4@&XJ;A6{fwV~ z$(4L{&c-*PPWK`q^%#%d?&zF9!<*Qc5)-n~4RfXWvP2HcP&g9|w&*wjc-X)Jop zU6Qxl#X0~iBkv}n fozao=I7rSMDU;YGQ;o^BDg$unus$qG?#7;97?GJVIkCoVn z;XF@Nz6*iBu)ii~ZYKPSRC~|(R|zS`!Q7VkmO6Q`nV~W4A&PZM*rJE^8ikMA0d<~m zpM?9US17y+@~0&sLZNdHlX4~)ur`T5z|}Pq87h_MtMx-&tVvq$%r^)88iCz^FCC+Y zO}JBlF3iMQ&>VKGgeuG|ve~AyBU<6G6{R$eSQC#ewfu=++67f%z1E0-guvekmJUH$ zRO@ozPUM%e7xHHar*dCOOT!5z(1E31e7aLJC!|D@N76iZc!m$ou-wr(r@SQ-ucZ_1 zo%F=>Fn5H`&xL1zruX}@Oxyi`9cvY`Hf_l+qhl9hdo9VYt{?I}4Uvct2}~P!2<43= zpW>pWWv#^oHHQEncmvJ9BUHe6PHqK_C_))bpzxNEFYCrDAq4qSZ~#?BS~&lQT7MzW z6CyrB_yrwUoWUVL3plKEUo>quu@N4~f7&+*eug%~q7bvye7K)elCM*LTO$|Pjqt ed@K3{oq2-_NQ~@D`v^ z1HK?bcn3O7i6IDI$H4+ptV7EM>mXD98f`H(hsH3Uc5GxUT>=%t1sdh)t!es 9iUxce>hfV&=&?!#gv~hUrZtD zZ?e0ySp*Zdp2W9*3sS#@?~R8>p$f*ZRq;F(Ze4n@aiSes26PTh6sO~kqM&l}Bl2Mr z%^~YRn4hUHY;#VX`AY@2GK#j{lh_p1ME@szB$xQ%
iMEEkGg)Bk+f?2RR9&|%F2 zMY35ypqsu>iz_;tG~%y1`6` RwT+wHp*JiQXM z(K*oIzkzM=hNQ5ys^Fp @^LK%>G#wc}})3(J|mv|^q zmH4Lvk7d1o3hvTag;&Hvi9-7mjV53`p-@ESw#E~a*-duuJ?bq2@w|{CmNURIcz-n% z&gL{^UF`gwlFDTg=XXQlW+-=ZYp~|O!wx>{^h4RGsON;hQ4{T;5L}|4k`6wsx9Fef zhmz|1uoQy(J1JUsjyVgZD`>-jn?MP;>$-Uq3Oo0IJJ3J~y|bR^RXMcN`p_>1HFO%I z1wyTG*pJ#8LPeYQOHr02PqDxSbX=MqBjFq7kO&6@H+x44USq+7IL_Lyhvkg`dvprk zb}5VtlLH~SBbjm$UknYTLxc%B#I&g<4Psi>F?&!EGtnv?s$oI)tyovI T zgJzn$C=+ _kwoF>4ThhR#J_-E#v zfOCRV3UIb-5mGmLQg?-Tx1~v&eq=Uy9rZ$g3CF4ja{y~gxiH~t>F8Ba=&^c1VHG%J zv@uk`jx$-ah+;I-CZe?)u!dYS8PO@1OiY>jnB{aZ(ZT& Zk1d_Dlcuh>o{W;=L`I>*XX@ZYWrOQ~ zw%AnZ?x85_w%$EFdn2Ti835j*OL8q;yh@NkOe5%3(U^Eg<>7#HS{`zXw@sbz*V9-P z*-Pca%eu|JXr^WkNNyL@75epdYZO1Pifl}?Z^`|>Os#Kjc$71Pe8S-nb4^<1MGmJz z+;%sfQr`H_A&hhx$zOAW;c&=#V?2X@Fwj8WVvVKl1?A0G0~xNB(cba1w|P-R@&<-G zC6=nDNvKA#cUi;U7on{NUPgo&AM2&j#(vg$6MCdg9J;igje*fFWFI(T;{vRkSw{k5 z7B-$WC@lov+J>(qDk2<0>g||N7mv+Bygwxl_q3DPRe8LJB@PCKL_V~0A2Wx4bnip9 zn9gC$7}GrrnH!oObmUL#Z9OHjy7*`OO4wHbITrd H$fpk o{Ptb)Ki~cJ=Fc8I*ij{KS2Q4(QlIz_A5BC4 zzAqZ@HN63il={qn_-I0=$O8`NPRs`=x=p*kbCyRLia+upJ{@@c)VBg|S6GKv#6pQ8 z8odEmM1!X>hUCM5%AF5Im%_^oo5u9shcm1+h=^k~>X|5>UZzMJTqf>+7(-kJ_JV1i zZi)^cBHjcY_A)ABgE}N}V#=0Tr|=RsW*38gm>T3$=yd?`svkT^o(CxqRM1Vt?&4nO zbq8;;*Xu9by0NviYe9Jf1aA0RJ39LChbMqi)=m3jH6}KqsAqz>ostlRHsF%#X%MH( z5Me^9#1w9W1~FxO#2s;eO3B0>aZ+i_9aO3fq|QS9Gs(*C0jw-J3v?fh6=wDgMzvg! z%-{ij-DSQlj{$`$7|s@wMnfWJ`dn7nIA3ME^lj0?DuXkf#=(VkDY$w{okJM#{6V`e zigZgIVGD{|s!X|IcG@s@_vxQfc{8Pzp;EG~|5o_QrbW$zS 0pjdXjG=%ha z-_=c#l~m`ftT%gq63#xB6+7qb3k?}VRWr@-eMo4gfL){%1Bs`CwxPmN*66TYacUgO zbk47Gio ODqDJ;6OD5lR1HZ*Km2TL LzvY%E4MO=_Iv zP7(Q9bm9?zq*?OIf-HBNz*#(~G%Y`*c|K@DU=N3nb}4X6=dWo+NIpwULU^QMK-kU1 zKy2g;fs!YZK%hyngc3lDY|$t!B)ka%S3=bm;=o9T(139U7N&27X(5Cdi!hU;$j1%~ z$I!#lTc4Ocer>nUpDDA~R)26@6hzP)KNI+zq~qa#ouIDaL7gD$S)Q^6pJi;wCTnu` z@bh|)c32}66upN7?L7JI{PQoDzkEnOzx#0h`7Qjqd3W*a=gZr_hG^Q~B*5Oq{6?u? zMI(%IC!u$ppwtWsjg^T|1n +EiSUuMmOLgv9^>lo4-`-k2;KwpU73KKqFH%u}n+rtEMLPOZHNgh~<+LC~K1Qr#{ zP#407O%Z#aKn3|bju )%VV)TSN2;!Bx)|VbSC6_5JXF{Z?N*^p}FC47!a^4ojfHW5a=iYE3nk zDKpd)51>?)7mD~glap#f^M+FJUkF3dW_PSMiFT)j`@wa!o=`KLXm5ol-hkj~l66U4 ztwU<4FcivOh27TdQP=}Ym=EwBw?E2Wm}UO7)J2py!9b_D+oEj)Zq7K=R6&Glid%?( zI(!pCY?JTUz%b~Vf=Mwa+#!p%;sPLh?Yr-e#2(3%2HJ!7PI$}w?RQjy8gO<@P>iN0 zDX0UmgNE`uK!pvNFx~*64G9@x#BZ9YJP~`vBj%P6c;^n<6nNJzo_q*!LkK*Q2kj7i zho~SdOfeHr(3J+AA}}dqg_2gQa3;%t#*dZ*1tSHSeG4#DOWTIHiMVPYqX&S6TpU%g z??4p}nOF_vZ$%=6PNmSod_zjM>Nv5TFoE1EZs9G$)P+^m(m0p?HGD~Q$UJ?RZA4Ku zi5On@cGC}=TUu~>BkYkgOT21&SF){{zU7bB%YyS4;fzTooX2{7EZr9ws6X3(A^4az z8$$oDHhVZ}aYa+VOuqT&KmN}Jyajq!cggwXKmYN6|Bw`}V{QPaj0c#hG*6_33PUN; z&$CY}S48I_nIgIj&Qe11q$N)tc*TU2u+ND}lV(N40Yj-p6y~h?Q TV$~lsQ-j}8(Jg FkuVX< zL=1x~$FlK;cF+`25*cM9$%A_fl{NfC)>XE{rwTletoFfJ3SPk}H|F5NlzT0K;4-|h zuEf`k*!Cnh#+KlTLO2nB7(}hTy8*Quk0Lh2`}CMiEgPDAj{}BZa10QggLUj5x0tM$ z3ei815urlA)CkdHHiRcDV+2!HEujoCtHkjNvQ2Gn$1jyfOb^!8hC5qHlr2J06$dCh zgb^1z_;;{6@N!F~6y>S MYD>}|0!8&NRu252c+&=hJkx;_!sh&s( zl7jH|sSYG;r?I(AdFeb+U53sTG0)IBp@OU3NI0b`8Q7_Wj$wvWZaX<(pgh1#P9KbS zgzz0=ibfHP%p{#LDw8zMtyDF}EYFbMhB7fBLX6`KRd7DQd{s1!=LjMT!tzfvW6aG4 z7n@~0K~#20F0t5uz3n3t#x@Z2#tz<2fZN)>;a?w4Kas9@IMLNrmhFJl5wiiU5n_re zF?l)EAtpn0)}TgfNavh@UG2YueP=pkx!C5dCkxe}d=ZUovh{Pqob8qz2BNX)H{y*; z!XbBwN~5}Ms5J|d5@wvhB!L%bQvMpSr?t_8vV`YW9e%-oyST#3$D*7~lD2!`WgK7R z4GLIr_`xJ;{Rdrx)Ow_oPqdK`c$LPe(-`DjILWIuA=-d7{JP5gyA38S6yg475GylQ zc~8TG)d)ztwC$d0beerRDU*DN+~((d=FdtK`X}fgqBJS92JCp`&rMO0j1J#vKSAee z1;l)U%5J=Wcg#1*|M`#q`YQ(bm*f^g(0L$+2vJ#ioLfzqDG6+aQr`JiQ@4%Ok4_rP zIh0dy6wN+U*KoBWnrxFc5l!}(yCl`7dziq=1=*hvCL9>R)^>hy;jlts7oGk_J>m;T zm3{fLPurq=Bu%?5CMC)k X_!Se)4aHnRvJ$`!i;`-v9o)=yPr3G9HEv$b`U+Wzs4F2b+si z(fx*h;uQFZc3R_zXrL9g9s3!!6rk}9BqI_qq-<$a&O-J1`li?2me(Q>AAQ#);kF&o zS|DGl!26keHfiUH%p;9CYG=kqNLivN^H-kYpc2X5eP}wL9*P!TTBz^t_wAaI2Ne`u zgHTL)SO6Mo9xhSBSyz;d5ePrvV9{1T&A?TEbDmaE^=SGshO1&cl6X~Eny`paD+KT0 za;=h(ZNSQ$T}Ljis>Gb!8nm$V5y#3!Zt#yAJ*4H)!GoF}2_0QEUt5=>*~lrqp&v9g z!&VwBGQ5Xt$v&@BHcm_WAsRc>y(!wxbeP2k32o9A?63IGJGit`KrY3vC?$4ktong} zCqK&0Vs(gqLHM&LEh|i6&nh|9*MYFC*&kf`O!D-neb;&Hlk~xOZ%XonixEFGI}enn zclZ?=N1f6H5U)k3ZRR0)kZI-{9CGKir^fcdSX#30x3y`Kq=bzdf(%Ha1|d3WtH&yw zQV|S~Vn}N}By#WZ-IVoH`VOw~J2ORpgyMNZKNI+L;Kk;M#t@ewDrLy#*?`Oau7rl( z!Uqwl70l3!Ia2O6E71u3FT1rfFO+b6zm7W4w0R^69LTd)byY4dZ-$I96RQDhCv;8W zG+|g%H=;L#geF6i6`ogdSrDGM_}d1fS`_JDChoxRfp$Wr|LUN^ 217)Iy;dMCWu zElj!B 2l(Fw8&fwG^q6WXx#)~??Z1q!(g=w&{^OfJxbPeQ;bs*a zgP%3VW6V7$*k3Q!EdL_FHL)9i{7CS_#T84!!runL;yvp&7Mx3=J6^$Vy+r(N+#;S# zkwm|1`Ryf*=4u0~91F-Qvf4aGa~U9b-+--v+O)d#;kS-r X84*}kdnvaTzC-8LHgVB!o@ zBc44G(tP0uZrGdebt)Km-l!3;tT0Epyd)5OsiCVB0ys@;ZlmY7x+!x{BB??3Q%mwx zI{Nu&*pOno4YT}ianMN`C3=z(j$^j~O;3r3f<_@^;$hMTg;OT|GyMM6 zHWL{W$BYvU)G_0Q5x1UydU#4a;Iyd!67Y+ zF9ZuB6Mr^M8dS-+bRTlYB>I4LFSHehu-M6$SOsh_!HMx39w4qr>z+mR!B}FeVwPPC zMMRz+D%y}_9*_-WFVrs|ZP=uANa%gLT_?dc8fg01c2C#_>X6fa0&=N2+h39$XcS(i zM|y-8X`M4 qAqx8zLTt)eHKup&wQxW=F4U z_9T6i2Q;xN_(1SHfv@DvTXQ?A65iGO4sWjPvhLx&sQlL$bY7GEIXL3&muu 0 z=g9mW3%}(qa2M-8|9a)g=dgxnK oKK_L}gBhdxLm7=}5){hC>30$u0L>dFU z1}E-y;l4ASB6oGjOnyM?0(vKWvA*Eeb?@s`P`BzHo$@As@%Neqcz-UiEzGRy=(si~ zQ0>y-1qe+U9Vi_lT?+36yuStSWan6)P*n`??sSd9`#KAocSl_3%U{RPbfjtayDq-P z9Ex7*-+{D{4HIdZ=%xPcq=kEO@eQ>i1()kee*+B?(Glx~faRB<$h5d&9m~R{fQIdO zdwIGht6JQDLYNk>kvu&AaVs4IVp~@veafEWi>WU7iG2lh?Cj0PI4Ul}UU~GuKY|Gc z@)U(HWIpj9PKIfHj3RX%)_XK`h(? rvxG34Pg?2i|}B`dansMW@@$g|gNqQZC?yY&Mdp{z;U*3mK3 zWc5!UZ=FAb+0cLy;fPif)xLbB`}_M?G8Do8z2MBu(u!@V#*uKtO(?1Xc}V5kZ!0tv z6q|!mJQd<2K%W9-4ff(9>$sE>KYT28SvRX~)_mFTA~O(0Qz5DWc}cfBI@R&+u8tXh zrCk5h%T;yoAVCw&CFS~`0bC&?h%pmN1vdV4R9?c6Ihsa@$zMLACcBUCWu%n&;bXzw zs}&ft0t3X6WbDGc6dr(isB^Ey!XY0@ C6%d=GF$S9IDP zzyX+#T6;7-l3AD4KYhI3b%zlfNEp`~bY%8+`pWz0`Ve1vbG?V~aKUcr*Ekw~CUOb? zd%>}+ZnNDgSDs&wVB$7icd3vcLx$ z{*;rRSm=ke4)c8)(cKx)G!^mStoM4FdF^ z2X-q={RZQr1pMbk-UZn)9OFy5{-=+NPCKRy3h<06lj|XTTmgpUMm$VrYqlLXzz? 03w+;(#L%OdkG~BgXZ}T>Pmhr1F`USE&l!q70o2&xOqzrinrcrb#5ARN~XAw*& zg!o?%1-revVjFBzyqHAaseJC*YL`FZL!GdRa8t6^>2#5wQ$?etoGQGSOj? z@$Y-<4Ui$Q8vdvLw*_3T(8E{|Y}w&q?|L1`WfzyPGpJrkZp}x32~}6+GdF8rAlAM= zZXTtR3rK1Qf%pRw1*+Ev^5_Z35FI)-fCsjo g3UZ$SHO3Ld^8ir9; SW>hcg@2L74 z@+U|^2mZzSuC@$EM+_J|#qgK-``e%DGB;y~E6zfGw5wTv7Ht;_1tCAe|7NJ|vsymG zK!-9{&o{SyfwmCA?ad%`3<&o-%{Xn56We0)5K4r-VSg=v>}kCF0&W|3&3 lx;)qNkghNdq@*b0`JOf9TpvsPi+9dQqONc zOHX)@6JE}LK~J+fbgV?DfyFlMXv-9&fG+VD{*}O&l>$d<>xZn`5cVE*PIj~)X7+ ptJb>*uH2Buz0qkAiy$DH*O z4CdtEju~yGSsavW9%;|~oDULH7^o{VbH$m>$-)0-zujidvnnH|ye;$6bsd6eAsv9` z_eDm3XfoJ^crj#zBhqS=g$6J+?1lO@f`zkVwBs@#@Eao!gX6Pyw2PDH`Ud!UM!PFG z@wkRX3HF{WHZQnHk>!sW?L*)psCs;0Y{VW3_Lc`vAUJ=^Hu(mcEnEf>;S(PI4@2EI zWqn7-j9_i1Bw#AiY@}?Yrd{p>`XtgP5k5nIYMic`9+MuCsUfd2d`28!j~)QFBx}|W z!TCH2euED7d~P4;kbS-HyudQtjrcW$f?GHEPA>6*sUdIs-$OuH)GWq#DMxU9xL?ID z33XYe*9DH>T2s@ac #hY1UtoQ^kU7X60Us=&GYX+xJ*D@YfLuZalj7B{4S z^KnGt8``=NE^WE$vJ{Ir*?QbHJ6Mdu7risC^)P3f24YQu*0G(M{eF6rWJICB2SjCi zN4rGRK@TgrP5M2&Ix5^@S>>9Y`miWbRJ0P%x$N&E4e{K_eLX(iVAaG4aryrf_jXHi z }1 zNBn(z9&DcEAQJ!ylK4n~VEbZ5T|gr9mze;F&xDpK?nS{fA0pF+>BySB7_tV}Yh%&( zB9T | zJ`?tOiSPP9Us?rhiz+Yqe6{WJvdi20$Q~b Shm33d zHY<*qqy}Y>+NZ|xNy%%w^Zh;cqEoSF{+XK|DDmnNz*s7De3IH^SOR e_Y zxIg4msFGSpwKt5GHDB!C jTD@NbHhB zSmF)IUCj*)v|w8F0sj|&y9->0kdiz)lx-AFt(dy4Nsz}oXV3?SU?Cp>L&=}<|6E~w zEnal{Kh%$1-G2KW $j5bqt&5PLw75wFKRANxFr0qtyycLDwh+YA0- ((UUuN+2XGC6d zL0CK$Aa46*{iDr)i UO`G`1Cyi`eU7W-G9blB>Kf|Vg + zF*AdgHe_oZGLvX)-117Jm}0H=$AY=4gKzm?&*k>Bc!_t(7r?+z# 2Rld0(*sCwHk3&jIr7R~-lImkQsgg u)H vFfoHp*;7nJ)GOw#$6J`I`_-|&osFEQOp+KLu^-pKNHfs;6kRP zRR#`!`&R6*t}?xlUYSdol2#cpxLj8kC8JkG3||v#0x_4`ypMv{%F`9)%E~#!_WDAs z+V&6NK}m#N8APp3Y=d^&l&6&yRx*0+u0%pwO}dBq?W4qsND*sv*l _{N&$J_)aR2}u;M)rgGe9!4fQQ+Aik;f5t}4` zdIbV_BgwHR?8(Jtc}cFng_FQS2gdtlSODwbEXgBl*kgUT&sQ*oSyJ|nb-(@k-)+Wo zGRVpLoZo)^|59iu{}iWo#GX2D&nqZs5%gEtLE=fE51(NB{>Km3sWf|nJs1qSX}+D3 zOf!R^zsh70^iy3>3D-=WHhNdyHAV9s6m}vgl&ScR_af?hT&z*2M-PHJoettt)jz#e z- QHVIu&ANwrm%~*Y+}!@MxK3LYvPiqgL@J+2 zXMJiy6)kt8Q|e{BO`S}Gbfa;*3du&|RwdL5wA_Eg6;UA49BOr_<&@g5<6~|%&Rtpc z+a#yKLN%Wr4AT{th|=k;PKT%aT-wz&$x=_kYia3}g9*8K2tLiit6jCZq}M7Xi(Zbk ztJO6H)RtYjs!F<)*YFGK x$$GES))?TxRQbMy$e@Gi z@|C|XE}0+r U4D^Y zm7RFg_ruUqW2cZdrt;dgI{#Qe(8;oa>aWd;z_6klc~%2iAWZG^r`|qbp1#LRZJt!i89o~% zTGDVSlXAY~R>w4F+Q!bATq^OAI?K;3oR7#ctE=;4{e|U^4;Y)e?B*} 4wbRGYY@`Lx^U|56D^H^4No&eALQaPGRTF=8soskCs}{f)==Io z>HR3su}n>)nq=0S8k@~3s+lFN*lZidKSU{KLPoXbQa;I)Auw(tb?|Kly(J{sxv{Bb zllDpEXiY78x5lJqniv*lr4|RVFacHpk}#Y}eGrj)+Q+(C$1x6Z5SmE^*@G qA3#eOexGLZv)3*_*BQ!8FK$71C^M9O#}{{80n ziB%Bq`}MC)Vb}}t!sU^Z9oWj1(=Yz5q7d)mV(<;|$fl%7Z4me^VoU=p8H(BfOhB{0 z9#uKHMf~!g{fk+eqGKmlTndqY|0Y&JuJ=Ktei3nY-xQ~Za=UW `-(i@AFx)eGo&pg}yRsM3UPtNJ`Hsnha>f z_%V$U@R>*VtHO!YHcP^{j@#+0#7R_>vhJSp;!qaL59piKnoE&yEZ-PCWilnXI_iGw z+6wh@29^4|wW*cb-8Jl&iedpOe}3)ek0J(5u8V#0hTmTVT3eM~j;4=FOQ{s3@y~ji znT|`ViJ 0^&`*uirhpRCmF9>lv_GVHvz_TFfhTt zW714)2bE(L4XncO;0-J$+_6k$Ky3`yvH#=e{@_FG5PZx^48Y;hZ S6hac*5DEJU0pFa-TzSRa#q#n z{lf|>`6PaTWmLE($MfM8ZHCWjbAn6|{62-+_@2E=O>s2Hq^Uv3I?d)>;gaj&kUxuF zPH{h}Ogv`VziLW2`Sd4Cf1IfN VZf1;0fjL&{{>{zdW z-X!I+-l<6D*E}(U#3UM3d)`N!4-jigy`r{;N+vOvT56_J|1p79YOypgJ9b>5ekuNf zy?p5=`!>VhDezbMN&d_WjHtST4s#i+eE3fKS30Q%J!h4i5G}sR+Ye#Z@qj~C?*@pQ z+YgrZX*_~-vwAf3U>|XA*#HpW1cWu3~&8{!IWCuT*vHv;x?HHOvt3uLOW`(4DV0 zT$u0|D-H2O2TTvYTjpn_-7WjmaJlK{!WYPlz&Yw}84+>V-7*?jy!G{`{?^xH5foUC z3fv?mk@;0$%G=4fZZ4}YR<^S4Bf7S=9)3(j`C0-`}<;+?b zj@-jm{zLtk?`m91;nTnEXOYXh5kAsdTpQi?_+289w^zs~Lq4$P`QyjSHWPd@!RKZ6 zmXA~GKV+O!wySYv2syz!DlJrA;Pf)J8qNO!@!<5=Id`L4Xb=k~8U zctO5|Cz6!gf4E jAz@aFF*<9{F5evf#Ej6?f&K z?4F*(Ezh6@x({B#8{~+N16It0oIV;V@8QMASjx$yoDAfM!_87oHkGrAmzA2RAqK$d z9?)!Te+ZM8^Z&ycIX=uR@~%AMUQ&Ui431tM>PHb0L)<0{+**wF>{`gdo60HZ58w^2 z|ACX)umYM1-f#(_$bdIEw?I+`$Ip;AMr7-Gui`-%^xc>Hhfdr(RUtA#(fl4j;NQnH z9}fcQxrMkg?TKx1H;EM|-Xnc3;VA39XbsQcf4lUU!D}#RMXus{tqKMTZpj2!_#3z) zDd);FBv-i6DH#9u>wjm!TRcg|d8hYUs 8Ry> zF? >a31KWu&Jf1*Vyv66U%qoyy)x+&7$+RD( ze*n`A3*(dkW{sljt5H{Ann|W&pn?Z(TJ~}UXF(5vuRY_VY4~7TeSe?h!;*Y{hcC{b z_PJQ8#C`>%Yn}u>Tzy^LIm;ow5_58Vs2ZPt!-Z|m1cDDLCfTQtZ!*CIdpZmcdJ^=U z$y&x2m$l%;$%)suL-`pe4QKHzwY X)SxvDZS<~bam$KdNg zm#)Ee%>wV@%V*0JAyjf;4xe#ko(bl%4ZO@gG+9+=f_tV4!GP^>Sk;UC!&~ive{z4Q z@5GP=Ll6wp43&bm!Sjh7Z}iofBYT2wxTz2983xiTfz~~z*#03Cd^5>Kn+vHF^d+9j z>@vj{J|Bwj3O>VYT FZJQfd+N4U@#Y~M^R{T3Cn&@FgR ?Yfti3~<3pI0$a#k=69KDRh^6O#ftz0<$oe1^t* zi$l#j{X+@6gL1V?(c*U-e?F$T8igTpn)>t{)pK3^;20$V=b>W8Bd=DEMk6R98$_r@ zJ2kPzAqa@bq=*bftm4$iQXcM>Cp;J~EqBl04x3~!B;;WY7bneOrw8(qTcErb>wdBo zVbl+~F;a+46a4J8p8+cZ-mxtb+{@)#xY@uu?zYu;$ jqwjf_Kbuw?kflfP{zhkxvY;z_DnbVShgzPHE|3 z)et#BtyY}yL3Z4NQCB{A0&)@sB&YPgNOE( F8PSMVeP4Sti(b-@2XEt*{*(gJuTLe zUwUpZrV!j-W*-&14B5TR{tEmu$?s)$4ciTTMkW}p pT z7Gm77uiOqL?9#*cp3i^c8+bJp;&yQkAdOY*2!?CxgMN*IQ>abG^-sY4FDr-6@7J-# zA`^%gF_l5QI&M6yQGxtykPpKgDgR~m-BTt3WD>y3>`EZ$Z 8>g6JFe_w{yYl|K~R2% z_NC1O^d&+d=Ei#@hJlSV8rGaK+|L!f1OegZ9$4ArRUwW><7xRm_4M%6mRruPIGq?T zz5e;F #_Me@oc+PO4GAyq8FiV;x`3aV`k7d-6%I3-l}dk>*`!We=Z~1o zzXxTGH31sS$_}$iy{chnYg{w`0F5nq{p=?%49=dhb@hLp3cFU59q~J{YW++A`$-(W ztz1`)68k9x_O2rF +Y}RNfnS+F8$@2bC4UCZ#l`pT$B&otZgK_7P}#-X7${)U>a>-&qmfhCc7Ow- ziE#?lm*aoSM6re(*z} BwLEHmx|wpGdn9&r@M-@xKB zeW_A+#r89XNeEjsplC8;{hjt>DQ4{$OJF!_3hXI&?U;){fHeVp&2zW%$sGNxUgVpf zB$Y@qFMBGSSr2;CpZfHx53e-9>vni_7~W}2?LL2lfbaXHOeQVWLVKzU9yva5yK}=5 zD`J-McJzRmOkJwZK?GzumS4+il{RG%@J #uH*U@=tF3xMdPQ_?Sfz4^-H*EIV;1H}EQf7w?QWY-yIAII;@~ zi;%;$DxOsS9hdIE99eZv3Ess1t(L~eEbn>RA{Fr6sR|y8-#*kezLA0R>8|F}$dt;s z1>r+iKl0oSZwew?oUra{K6_oHp_D0aPU3$eK^1lq(5stGgi=Ukh?R%Rd*Y9z4=%1w z$GhouGK-OV$;|O+dbw`xBk$fZN-sv$f$h?wsn69exq5a @g+noX3nm;jc{mS_HV|y{M`L?E_<7O3-uWS0Y7he?rPK@Q}p$!%;LQFVuhL zse5X>kSmdcC*hd9dYc`W_S)T(G8xokct?EC0$*hG>SUF1{iM8u8JWt6(5OD%@lU{a zD*Q_HICkJ8$Fi6pVsYFzyvL3F)N6cUKr0SWC0ZAoV4iZn5NE97m%)tKcV*b#dkAvD zTjItaiBPWuSYb^7Q(WXw$Kn!$9Wj5u5cfa?^2NZn;wJ{a>Dx(a1 8(h(O|)X-RE1AOyIgun$-C4EUd#cdSGaC&MI^@C=W`-zUN k@sbV#<~Fo&ON(P0evp+4+Z>a=y%Kk&a(b=ZGx2lp=5 z!93!91wT@uPPCXh1+3V{uc3}%LJ&)M(Pkz4PTBv&zkF{Y5L_ZFKbCB@`aI(OGyGVJ z`uf~d@bTZJ82R_i aVx!c!#^4~R$L*;lqbcTBrAhz~QuT{UqX_`Fh&NfP{85NWp%!GS;| zFCm{(^{)2^#*&VvChF?^zvq7^8&F|LKiow=z-_{6E8;`1pu${=*u6evA5}^!bvoRJ zf-phyPu!78zfdsKkRX5fjmW{EL-J3IKbK^Uz-R~DEGc*5dg+SaeV4p9nyQ!wyBjIT z0LS7p?x~#Rom$v6!STmBovK6J`$8NaJUbRad3HU4gkROSp_^W47p_*t>B~_$h%^7Yl!~TEWDq4&Le1acYfxCri z@V6bjtGHql840+8A4wYmylZ+A{c3~vficiy`S+sPt)z}!-j&SDWS$5tiFs+1O}h9u zQ7qL8;21D;{%~3eJIdACh(QcoOM@iwfl1e1)FysjRy+1}HElEz*Yb2ghCdT&A+J~D z#qLW{b;X|T%C>+1dmXK2BJ+{VYjyqOLM46sO3P2A_j3#iW GWD*$y3v2h4s!Jxnb&?uQ1=%v SaL*BoATES5H-Ogb0s^r%Ya#XS+<2MB~H9 zDhGegdCxiDX$r*KSy#a$D6xXCM{P9L1w9wx1iU7ItB3JTZD1)5oesx8myRUHV5hua z@ZZ=?ybuWskxwEG^?gs8kL^SipRh?lqrP DH5B1`cdNZ})o`GQeLX)x( z@6 WVjJ{ThB{^4CJp_Ymc28hk9py7oi^hn(**YZBQka+Q0e8(fiNUs&@bB8Ml{XTtjp z>$2hJLfjAXtCeirI>Bz>pZr64EWWPM19P^j|Lr9#MJn!bpyLw7>zINzNq8^rhlqc~ z=-?b9P14-Boq%5)qHF{);hcDaGvR!Ag!oHwD0gsi7V6sVxm~`1Gy$#zV7< hSR!Cafa9#_2U7iCxWSf5pc-7u7MrLewolk%@#@EVx1pL!w^>Xz>=;z>T;r0{W@0 zkIQU^9L94VOp3&!$K4Uns~?M{ho}dL2G%O1j(DS;rz{74DDUw#O(7*Y_z8Qd0Hi{w z5~0WfC5DxjbjUTH!{UF<0*q>|(e%|f3CuCuRMq+P<&?N0^c+8a`MA{GX%>+*aEn)w z254%`n$~(_w*5dj(vD}f JZN?A##oDd;F2%j|E8U)2W6Ft!?o|-RFNyhuFydgGkIo zB8CZgT%Z9o81XbGE4qht*e85H@t@*pPxzSv?*l6iNo)3ubC3B4k+2XoxDflOq= ;H=+5m6Db|KiGI`sn6 z665t;)H5+V4yb>76ndhbVgW?4!m!hxHO0Q~JW?Uv#A7Agl2+6(#rEGs6~Quc<8K7+ zzCP@DW~#SqCpc%^zsH2Z& ${1t!}@L-SnN#ylIyRYK7t`uKyMZ0^~UQjjE@Hk zT%1IFRenC_Keg)M__$V>35CyP9xiA?UWR#Y5n|@lK;V!2d)BaOYnd%M1kV{<@&pc{ zPw-=4$MZp)Xl0V7t3|{Zm|oqNZhZkqfA5PUACnf1yzv!`$;jl2CuZNvMBZIOq6yFY zpRRr&)%t;OUh5&xuCi7V<5S+3O$#CK*eRF0cJiv*5$dy2#A}8LAUflV3<)zJ%mksj zR|kZdA|&Xt?aD8rau+$Tv|X9+Si5Br;H{i4`W!wI(sTUqw)KHys2jl-_XcpCe=5&U zPu&Cm{iV&@`o7!RB0swj+n5_zU+Sb{LjqUG^6VoLXJ4Sc3Sxp*=eDbl<=<6Tk2Vn| z$=j!@E53&7;%9j|kcgKN29ivW_>u2;?{TP4{1=!<+$d^;!J4_e>Qlj*;$9M=HR}D@ z@!UQTyTvIc3!B(JqGDe~I}S&pe--_a|A~#9AdwFtSk-|+;WRtmI})KsPsL*u48qOr z-$XX}>EHT%{IvZW5}437^?`w_@x~+{r1jVF>>akL$h_;;s4_)G1%UBw&*ed$!W%B? zi|6fqR-PB|@cpNQLpG{shgS>dBfaLJw}tcPK8WHc#kRu_UA2CjlSfx05J=Ki>* zsstIMaGr18r%};&rj4eA&gIqo&>95@qjb7)=)9~`_RDZ?pZjo^lz#z8f3`oKE8fyw zA!uoM1+#p_4K6nR+y40Nzd`CW&MXCCeS%L_amagXaPC;ev}nT%K-2htkW`z&@NeGt zWHEZ3j!W7gl>YcWsAbuY)zd_Z@}qO}6tNh$9;b%qCEukHn=APv<3B>Mz?=>zr^lj& z4;j!cz+_|xE7Ev-=RGE3e+M3lap*hqhmti#vwe74h||atunrknpAm$&Wb@& gwOcR-Q#6xrRA z1e{5VF>pD| D9W^EFw?nnq^O?$Q-9of`Uux{XRV5uZF+#92T7a#}**%}e z!4u9s!*F0mE*DkSr)DbE52;tLsoS>xVrld)ICBolGJT342LFm l;t_5>E7o$w zB@`KnDIXX>FEl1ne Xf0J z8DcEZ4(!sEN4&^*Ush%N;FdO;>SCx-V37k0==cQ-f 02pki@?kkF{8NAw-d_<1l ztGl}Cf>C=J%37ydiXs5e7eGM5EXKWe2YK_zHK_K0wQ%YOf6XdqI%2lNI~C`42-z(r zL2#C<-7!932*zk-mkWL$AwTOQgyXyl^Iu?o9Ns4g<(>qp;A8@cIc9htoBDX_yp33p zjXs-0#S)n={%TY2E8FGV%cw|x8brHQ*MwWSz=oZko}GxG1f7~dGd?V#SMf10JEseY zMtB4B+?8Ad6R7U5_su-YY8Eb$uEd369FXtWmui9mV1H_VV1#C2#ct*GGoNTeR3A9M z2N}x8FUJsJ&YWMDM`rbGPa#Jcu-FXx;vVw0IIwD0G`N3;pY8U wP^RWV@-;d#*y4f&^9l8Prv1*uRANS!+L4CS3URe5@Q1Yq~_ zx)?yoyMK797Alf3tZi37p O`YhjBA5Y!RTPL{Q6K9Oc9s?MACKpcX1jGcI2Z+msaC{Zi(ivO9tDz*1A3^K%) zTYvynfMhy&=CJE6PL?q)_JPk!dbc@*wNI@zNU2ebDsUzKb+GQiV4oUnGjs8Xs`$w6 z+J6#G|A*UjUi4>?GPmtpI2sSZ$mOmT#yEnYC&FNcrsgRj@7QWY>VO`GO%X&y>7yef zM)fIRG#0aUd dsXKr}P;I_0s)h4S@intjew|cn9m8 z0h7?oSxH!Z#&lW8g>UjOm2BMM;LLo+?^?-J3anaww1$_gRjYuYfb7)8xRb!NAAd*o zuVkzCrbsC0MRXQN8*}3v6&E30Xw6G)?-Smubt5n^fvtS=Q?yPrL*B^ZF_>(umh=&7 z7?jug1R@mJl!qEhWh!NWB1yj+4j#W}+XrL6XeJf?qINoYU&3j)BhT_lnH;0Wg85O2 zpDXPEVBr%D>;8 fr;G60F6Wn35?bfP#NKNR3-+Ni``PY^{ `5p1f{UF9X6cU+=XuRgYYu`}k `1!5Ll_ipa_aZ;%fenSaXg;ewk(7#4mP zT0QlW*L9};o(X& #8M@7BX}0Wi8U8{fo4A7$XR z;o@|%&g(p2jGX#`1@!OlF^vjL&Wj_#sM43>U#d`EyLl#jh^(7pe%TWy-@{Kl!=mqt z`H)QZ{ 3&9p@`+Y>?G+~p2h4!4 zKg1i$N^Z!a+_{C}5TI@A1~zP~y7P7Ua{$xg7xHI@KmF3H(|=Z;rxo~Nh=cLc$~Fi5 z!Faq3qb&BGHE{N#YkltN348ZsN0sE}EVr9fwSfq*C-}iTtFzw UdapvLu- *T1|ebmJ&U5#I+jKiRdb3{!&-<3 U+S}Ii(#g;eQdT?JA$4S&Hjvoia$Wzg)2#rdIw=*Pq61) zZVi3mjJ5xfB{wYhb4otBe7?}-y&_=b>U_Mjg>dmBv48Ws6q$q7z-2O%gjQXDr_EE$ z2xmOhm3iyr#DrvjsPD)VCNq#Ji#PZ?3 Q};e}B bLk7ReT3Gj1a8f1nje3(ty^@=l)3)wOq6e ztefM{B3m4oRx43qt#>S;Ypmf6gOEx-V|*fUj%v92_=C31ZW|}esKrR3zqY2`n3S6+ zKTJ2-?W|yV2wtX>`|`9kTMHyJr|;mYJEf;>Ie*uTOtBIsE+BYZ0Y|w{#hnO{9))to zHJ`FoXoVL!#kW9_4HQKDxS=Z^P31MDZmc0!yqJxga8tN{=~X1sk%?Ur?HaCpJl%cr z!;jO)H(9;aM4 U_l6|U?2D)NSO{-dP?3=9}av(yJz@# zeV4k50j_`VA>JOosN>diCf>wCy&cVyzRg4$4NAZB*PTy}u&X{e1~wPN_Td#I^TE0n zj@5zcz+DDAgM1`W?dnHp%G}Sq)7_s--@c*=o`>Is%Flil`I*emFy9Y&dtgNcn?rJ+ zDBOZ`4wsMuyGkm>4?}5HG+*-_J2Boqs%^=_(O6y?y_I(1)R~?^#)e}Ut;I#4(pkLi zlT Bb z@^=_4I2gjZQ~k)A6qV4(56+kTlS+-MT-}@q-*Fj_31cyPnUlwjKeM}BJQ4U ?M;OCE@U+4l&c3Pn#6JecyyP25p@|i@+z-PWT7CPZ zh&GpgtEKi;!UdsUlfj|VsXPS$n3vTSbZ~UV)9k|4Q{%^Sm%okyN`LR08XiFrOEBV{ zu@EqBULzBI54qV#o(s{3_*mp?7lag7(R`mS0?HAeXeW+X9_oD!pT@BfmVmTy9Ki(| z`0B#nNHcoq*arOm+~C3+pDtQ2l-fZ~OMfqZXY%(%xLnqGGhQY#Hn16~Xk @$1E^lAg^6HVGYq)YmZ*y;0OjN!<>D$m5%{E0e`-)>-~X6pb8WKr-8CRZn6(Z z&xb!(oc`aLxJe=CVTgXr-XJ|$#XsevnhKH0s{3+(Zqz(s$9C`*F5Bh1zwz;U9oZfh z2t(EXw8=`n0qruatT>mU%4V;yY*x^k7$W;~t}VC8VQ5!ltQPCTngoS?Y*Dp8Z}hc1 zIh5^c41Wo8uf4MAQlkIrEN!m?BaKb}5esj(FdSWq33+H7U|1WDgipv*O xkMkcl{4Na34Y9+$b1Y(it4w2g%8h2>12Zjtzl0KfS)X&M!W`wb;i@ zEFW)IdDyTZFXMTBQRAsF*FX#;tp;&mF!C9uuz%bFB8>)WI90$u5e=^QT6X$ zV+pXoC{qKW;mjREaN#VBb<5z*xb+Zmq7MPRWDXG~#^4u==f#P(2jK+j;CDIXLA|pr z5!=DCQBDJQEV+y*oEBC~T1drtI*vg55NXAKgq7UUac8&W$*E1}dWj2yiO=M)C#2Cp zi7i8!SYH>mO*1EPvJ-24Yiyf8u)|44b@hEzOr*mX1#;zSFJu2~EG>2&nv&g@e3AiH zfA)Nm!6#nl))oQ6jmOIB2bq!e85w3!@EsUjtYi$X&B4Xq2wXE3?^uVsVLT1)-9Z`! zirRB zM18}p0iT7|%1 N0`m+00hk4x(KtGah*gsVo|VX7u`k&tl{J@m zJO{`c5i2S0fBL_(#x9^a?UzrK0bhUL- 77=dOk|gnPct; z9B=eR_(!DK@exwfJ@rDx@pl^=dx`5IX9)BKIhwe-KG@Y4x!3UjNfAzGt!2AE$|87W z`CB;AQ?UbHwR=^<<%FHytyziWakrYMZ@V7 G|XmIHBee^+;Xs6TPMKMbRrm0V=R1p}VlM-3F&Zj}1A%ue$o6`HC1rM6u| z^5#}lhrXh3HL^%hUVe+KpcEpveJ7&C4OCU3WMYgCA?z>vBCzc|QB2%;Rh3vKdNdqX zj+H2=eS8LfD7S_U6`w|acG`ccv_kqFuh16*i5syxQK;5x!$F!ksFR78da4@=ZVKK# z;ksw9FGhg~!sB2A%c%KxPdV-^Dsv$_1F| I?3-qD1>v33p%;1PHxv8Mj^v`WwQS`rA|&re$?@5}xn!>qd}{MUbg`R%7mcTM92 z{yN5q%)F=ds%*ACy_LXOIlUJ71X{fu2*AlF+9H}SIiH|f(SvjG&}ssw_tt?=S6A*j zzzO_yfD@T{PwPN4jZkeDI4h^u0iQst?*aih`9xbp^B?CER0n!+E*@GP;Pl=)aQ#?z z-8kN)mB?HdxWY2u&R&1N2_u$;jF(E?k}VuA _KAQMs`Zlw|zxwP=gqW_wmvihAd}k9Ch7_QSd7jUdYfmW<=_q zn8<*aN@Rweuez~&d}@C=9E+wbc6a?bJRHJ;lFmu98OFdh_p%~|OTF)(uKxP&+xI~F z>bq=23YBI$owg|QrKq-Sm!Imk+m}n10aJgyCNl^!m8S~n2A=>)mx*~-eXprQQ-HJP zJj;ISQ**T*2ZXuKtQiBn0Xd?o4C7Z-~L>W~{o0@rihYK}S7=TO+|ZkHI{~gfg>l zGm=zX*6o{J8zgpG78i&6=GwXiM^ 2iE(Y(6NN z6UjjdW@Iu0A1br+6>&i^dEb=g0lG!dsGJl^7S_t-SfQix!5WusduDmZ4i%qSRCWJM z9zOlqp7^l7KDV}zULJs zkzg;t_!CDb$f9N!8s zfbXYs-!Dj7n43U*R8_vG^(s?|dm@<5zr%&-h2U&~2*JWZxK>^q>I8pqRuPk=QvCB? zWTH1LD;eg6D>zwyF{{)aS|KP!N7FO2_A%G*t_0G5B6Tl6T)4mWGJpP=ml;NG(=XFQ z;rk-#VvI#YMDOLiVauAXyvGZ#EmgL$>>D}l&=alF9oKgQ?Lgr4)_&jDXQk6wXzDyg zZU<*8{!ygQj*yQy{kS+UtFP8Nhq?0__v4$lKmI3 jN;$t*0}v{&MR<46332+D(3%0*f8xHx$9imglXfwB!S73P2z=O{w24!rcX*2F z{54GCq^uhEU*k`jT )b!S | @H-Z6N)_H<-b7lbr|JuI5^MMPjK ztbY^tYDK&nR{d=Ul#7cT!e$Z8g~CsDo`PDv^F7G$64EHauCm%fXV}1MeC4QB{V- z@Cu0faV< ABKMlt2Pcc_~LhYpS|s;e|A6fTzKW= z-Np6mtLxu>{hya6jBm=$^SR&@=5NKDx7QYqruMuq{kkeq#=>FZIo JTCSQ zeks8YVaH+{E=n)-zSt7PwCCfoXrAaIRDmn;uY>iMvg!ETiB(_d+_f_Q(f{d?F?s!x zE@)a%J(KCM7|h7 U}r-Z1z;`NtI|JXU5Hy-s{vK56Mxh;?;;hEP(luz#q< zH7MwK9PfIN5z}~IDl*tDP-NLRyrUbv2J(BNMtYe%bS7fd!^ts0e>D-kZxX0xR-!|X z1jik6fSqL62<5}GbG3_vW?=MArNM4$hG|4t@EJ*BF%u*BF2z}E_&CV3iuXl%h-~l{ zUjLzev#?XdWFkKGO-W)p8#DExBAD=})4nNoz7Lh8l8=Dn4|&dleJw={g3_~ys90!A zzhD0OU;hGU$^ZDze_r)<09yI{Uvt4B|L1<3{N V@<2H&UGNsJ z)FrIv9YG`TTWr2ThQ7^xDDN7|Ak6~T#A-mQ?~%(~GRR?KHhUqN4sXn405;6%;9+FL z0=NE3lL`Yjf7;EmGHxl_KhXq{(|%-+xaD9KE|zi4k2Bfje@;rN<=_5ICZ{w~#hrgz zeH#J(%RO`cu3J4*-VNLH*1%`&{r=K?n KZ&ian z(o`t55}q-ncC1HjxwlHYN(4%opz>4EYvl^F7OG z3({E4cSPxS#Mqv!+BQ!oVw)M2P?11ii{CaO_4e})>L ?F10<;3+F4jrgyqmIDBZPj 3)#kDFTzm+_Pk#gL ze9WPSwSv|P|G>V$dOVzV5@#;OTvZE3N5xIx^hpxo*(q@*Q+&3xXm=K*+6C*r=j3z$ z2Oz>Nn~)|-Wv1QQ?)za$C-#7x&9r|glzlCZrvnSZHk9h07L^G$X|1@n3b!zbRef9p zd;*;%+|szR2oZ T#C;)uFAqfBY*$+JdwqY zO6Ps?e;3KwH@K?%Ev!{S`tR*98g^%2<}->ON_ S8#o;?4I(ExLK(p#*RAuIgRZ1WqS4l-Z%q8_Y_w4{Zr5K@K)PC;3(8&1B+mD zd3;`39{b{nIGlB&*p+Q@cNm#&$L{zPN}G0tpfd2w=L}y7D%};|_6$^$kAoYxJhCrV z0`8Z~q5&O$J-7q={S1m^qR8)^>ftw<;p-B7;0oOnyee_TH_&mWuq_%Eq7scEzGK0% z5tTUf)QU+5P&t8ruIfioCvA&gHiVOs|IUAkdVCm`zsxdQm5P@;vF|&L8Zr@qlTUOz z=U+9LdldOSpPxNiPL 6=Z&H|v|#1nRt!qc!) z?_LCd83VC0$|sz};tUePg;nTg1>v_qI9vMA!IC{SnUW* H>>ynH?#H5gEdt@$XUyB #tgeiqOHX%|c z(}Wo@*j5Zkq>1=9-E%VCDA3L2tr)=cnPMa`I#WzXW;tUU0t-*t8Zq&lU_h3Q_7Fh0 z>uv-zY`>cT`GRYiF&ILZO`>R-WVr)pnI*X*hnZvy0j_Wu=Zb7-7HDHI#L2<|;Uv6& zp$Q5hRF)Y6HBOdE=vk#X)(Ol~XC(uA06cNehvmJw@?*Id{eDYF;N*fQ_hEj}dt}Ib z`42x;B`j6LB#w=4evUHK%SPiwu-dG64|vXCLOmk*heAANhM|$}V1FtzF2?guW7m{- zXEegAdaIt45>KOH#3d} @3V*R^D!vizab_b &OO4+#On@nRt@VjHZJ0JR;Hv_{!h<7!? z2tZ^p0A$%YZ|w5iO7{}23L~QcILD$Y_T$@}E;@_4GS?|$ PBguy)Ttzod*&dT<((T5O?84CP=8Lf|I*S2hu2Y2iP>@AQdbdbLMH0OsVRQS! zgwE=dDf@+5?2ctcHy=>@j0ZFXp&J4wqS<;>exo7lCD`wZZu=k)%8>1UrWf* )~x8eP$0lL@P6Dy_EbR5P#!1hDPb&~aa@-S3>4_M;RhpRyK!XPlM&MohC zCNb^;iqX6vi9_)CJ)i@B53;`wooan0ETyLB>QL|ZY*z*we<(?_|3DuI% 8dYLCiqNMyYP`<_*-krzlQCX@6Yqe&`~=nV-Q z&2&0CukjT7Wm-J2!-+l{ VKn3|BqO0`cddHL8-#$#HIk_=-*#!9p96s_01x|k%Ib?g{oTTbpbD<`7J z-B56m?WmAZObE;uDF8w7=yejQJ!V51g3t{C6U}A=s{UxBqUp~#3Z6?qM+_m!V@K-P zi85M@8YPAf4=Lk+LZVU|=K?PA6G^}vw#2(JZu_~>xKQ{v1f8wW(C7>tD12<(+&nin zIaZ6bo pJp2~AD-#BDC^c+bwtJ<@oV{-24>oi7X=bPqw#>Ohk zrKWuof5e7{WHYb&4%t?r&K7|utn4Pl?5XuI(ZuHk967sx6`$1B$5f{^N*Gai#l0vV z+qSD46>FF(c_`)wp%I7Rfj@8CKi_V5RV=iDLl8=>TqNL)smP6`3{U^_O|Pb vxqK)Gf9CC e;L8p;RzoY-R+3WfPNrUSL<7vWMuH@e&|K^9qLi#RJJ?ZCG6p>A%EMf3T53ahrG zl7tF7q7MX?4CW%x303gaF{Hg27rhy&Pp@)51CT0zpvxQ2Wx(*B)lfdz=fobwP$ 5-#Wi@QW11CUWxFDtMT);DXwWbC$UJ9a7#Xz6 z!J47%b^!sR>7Sv_3I3=0*;LqvqY;?}JqtwDw)tWI>RfUvi<1%l7E_^uCSD24S5RGB zS%-N4h}56O`u^fAUOZuX%ak`J!pwE5KaU>eoK>q`zMXu-PCu9WTFE8mk@F?{*z`Zy z)2ET*UO&EMyZk3RB4a29Hq0xAPXRkEAMl~G-!oUFUeGC~*6G3@#n8NQf?DR;^*z~e zf4Ifyk8wL>wxx7aPE{ryArIUo59!4E>FnnFHCNi9bjV@&2&y~?B4~!DbVPRAW+A+1 zagexBK+y+NrCxDc(ydLMzi315)H_L&YK8;02E`_BP>+xo<8b#;@p__8luVmj1VCRZ z4 al#r>aHQ;}=#9ft+g5 zXOs_UE@;qI%+2zPHS`dRw<4{R4(c#S3)bbshW~0zfEQFsGT2(%$MJ6J1_G;_COHx? zq `T5-t-ByB~zP3Zrf7?OdHfmtEcID?|s2@&jOO%Gm7!8wrZhY zKY#MZTNkY}Pg_bmyn(Sq-N+dBu*x!Ep1AkNY%}SZ;PLlzc4cPxH+2eXtdsx2PlxFA zpu&mcn;b%oG0EYZmOh{bCQ?sTE*1o6$cq12Y- z^(<_C)o-TCifU+&-SwJuyBZ%rVKjL${4}nhDmN0qZ;E<2$~O=LT+sJ4T4dwJF;+?H zI4E o8Mhpulu=!MjxyxhyE-J6 zHdbW#-mrIEF0VZe6wur}n1r%P>mQHTTA&H%e!zyc$8%X`r9wICPBJZ(qps=%C!C|e z&bY-b^N4K+6K4JemUW^j++YJ@2CR3>sY(!HVS y8?}qiSTVbSQf6h<@{@6NgW0BDa6WD| zjz4)SZb99Z1Dczvu7By6q@%It+=T7X!50fFQ3x8)a%)Q^q!z8F>}1MrB7J`MG_CIq zW_AdCi&z?eF*;cgjvwtj*8gTiw5ij-rHrc*f!iDSXIx5UR$cTRLw}VcSt{;Ne*i&~ zgquq$)D0dzP@ZE@Vi<=lx=!9C>i5Lia=Dk4O-Fdbs6_)~?Z51LxQAC(g?YhC{!_1! z?rdtH^B!~eo#&0Q&!$_%iQ!xg<`EM{e->fTg}mo3;KMm5{RSQ82IqwfTDseCdo?zZ zj6+t#m2L}A =-Fxz9&u=}lK9fOGLWt%-esh7Vgc&SXRyro3=(E$(ivRo12&|4Y z(hfF5<}7XKyTbfx!}JiJe_<5HihK@{6`=`*R0KmF0$op+a=??}s!ElF*AaJFv4b3v z1`LdBggXQ;@^ER{r*H=uYjr}94AOfWqueO0aLX+6L#?#m9u++hgAG%LMS{Icq)w$U zL?ZiIAd1TbzHrol|H4t51+zPox! `6%9f0CjtA70I3dfGH z#I9xV8#SuISzz&mPNKqz-w7%gVul1zV)%YhMXyc{UKy)4wTjHg=Uf}R13$QyXQM+= zsFQ_;;6l{wq#!f1iLuz7p-RFVHP=ed1fuoeSt7b1zgn>HU!i1(x}a91>NS}iNcvD+ zAqYe8Sq-WAp$JWs7XMn>EYVN-#=(25q6XnyQqB`4(1ww{e~s-t0l6e@*7X2IJ`G`w zdt3i0Phx4?b)bcN15(MJv@%a(NIXd$J!t#sY^s_>)Vf&TJMRN6V-;Sz{*OVr5SZfA z0+Qv4h;*#-Tnvk9nkaVS=Dv)Rhbm32W<4h^G)GB>m{QVMhh{?N8=Mw;g=+aAIp$Zg z5BR=;9*mLsfXy? t1Nesw+o*we7{ zg$L{0RoRL!l_XtBy{&npaOVD~LE9)NgW47UKR6aaoTn@CfxNN2>p&VkgGj|~@2?`c zC?j!DU8qGBaoh1(n<#mH gL%4L{?%gJ_~Y;zFJ=FW`t+^I;ve~CQ14n@(B l5Ic z(5go68BkALflkza$%^vOJj0fl#Ttq3J_4?XvCZp!tR~vrGW F1Et2x%)*|G95mQF_{Kr_38?(2 z^EOk9P P-j6Q@Q7;vDr0cWPoH zd>uZD;Rfpr@=BMh|37bbyF}s3&ci@(C9t#QrAOXr2`}hYDlr6JzCX)e2(<`xT_I~z z;u?1@0 =b0k^6Tz zVYFeVwY8T((h;3n)Hn<5*P3B!AKOz)x@Q#8HX *FLb3BiA;SZKxDyf0Fs-xI7e(D(-7CD984T)L`sxBv_(l# z`%#9i^!1x<$bjzkDW)ws7#`jnDUVy`Hrj#s!mD(b6hqWO><{J;$dir{8+;|Jv?rzP zlPg^U_u%d~=Juj-crmngSR#nRi0>`X3%{>{PK+ZOK_n}nR6TtQSsr%w;@ZkxWgH$K zaESlyw;5$_BiV{lv>ZD3Ey%UN5_wx@9fbk+;w*EC?Ypz2A67V(Go}!f7%HMIYI)H1 zZ+H4^La4^kLGO9q2rJ@DT)r49nf8Kx_y%4lYYx<8xo-Fp@oyDq`ICXAKIMcCtIG{V zYRKZ3mAH|iL~Po=NbyoqxU{=dLSC%-043LQ;P$0iQ2o+uYjwjuYP5LoV(!*EM#CCr zSy>5B|9 Nw%vh}U}faYX^As`j_Xlo{tB@jbkY>JGf)(+OL7 z;O-&TM8qKo=Ij;TG2(J`@$dJlBNZA={0@@Y_iNHvQre|C>tUg*ax`#caeJX|ARB|k z=%(G_Km8wG=fYP`=Q8qL&xT%kW-bfZ4WC^a`M*eCIvwi;NY0t _H;|2MeQat@*RG$8ILN$y z+^ES?{N0oVYg(zq=@~B_DbTy2(JA&O`1E6gGIBUm2t(~_0=98R^5u-;OwJ0pAm*t4 z8TMz))`|7sl`35M*xfV+$k?m@Vnrg$2_S{-tOoCt>i7j_e^s|>vWNqxE}=@$f$jVQ zr^u_J;R*Hzdt^p*Bq0LDWzI+BP~Vz+!B{ERk(lS;&w$HeqOS#myx1Y?(R|H7L&aiJ zu$BLoc=E}xRl}vqrbR{zpMj5MpN7G8@Sr;4-P~lz3WSscqjIRL?pbuGri@y!&2^a_ zZJwa-B~Sv7UkMeESKK_YNc*GxImbqKJIhq*CUn|#lojXSq{K%ju?al$j(@5qdvLmG zW t1uNK#;e&tHdgeY5#4iz(hqn&~BaBf ?@mrH6hWyHTm+Zbr4&)8D6 zg_qv{ikHh^R5slIpg|Q*+L7>WYef`SvE^Obu*X$*{YXk37I7Dx{t8l*jdTJz=s#i_ zH>SFFrledP)C$h7Dy7gk-yG7faz9<{HM3Sw_}8z2L&7K_6i%BUq<`-AQ ><$jcTSm!>@9xtA*|D>vW!=T7)~faD#EqA?ZJO4nZcj_paC1h=%+` zfb9Vap>JvNX*QKWzYWXUp?Z$4g0SA0{?+9BxxaT{ohKPb=FG{X=tGm+*@-2^0U^iM zZIzQh><#)D(-@b(TS5eXEl!~6bV6W%4Ko*QnBUUrlK=7@Cd=|gSg}ya?jo5J=T!bz zz;cE=zU~%#)>lq;Ai+;B>g?Z{AP3!Tj%W#7O0 *LZzKY{L#d_IgpCkTX;`yvQvHtqC4a znaZgi>g&eJs|LR@mk*GMLHY^z|H>6SQy6hV5!>Dc^!3QKsk3Qky}a^V#<*qvC;^VO z5XZVq0(5D9ilYXSBu|;;Ja(eic$7~XoIk`8&TB1UuvRZ%a7rRU|B~ax3!?JZuUlVj zHI}VB-^Ndhze2!87a2L|zEeZffSNjnt!Ilh@kWB9*K7ij{j{;4PE?ie?JJE$W1`H0 zP%&H(ab1VW72AUyra@E=+=t+u69Dulkt4B0%*aK#DTR@ZXMpeUb_LX-b`rdBUu2`2 zfLVwZE#54~X$(ubTcjX|YZo!c91?0(Cfb)%x}&tw4Ky@<(lC^3AvP}7NqwZx3YW^C z{%SN^a4sZH`1F37Sy v-%xOb32$xpU3U@_tml@QIw;uaNIsJRy=B`e>9NFUMH_A z)_Zh}NHL`s?GvSBu2L6{Kx6_5OnLFg e7wgx)I`e8!bn8$v;Y5;1 |TjY1hue zcbh4oKOgZw@W4~bl+qr^@8~KG?~;aR!HxH^2bAh(c#guIwuar8`+#2C>rk z4r Xg8$d4=N;zZToZlC<$&0^luw| zh7}B1GYy=DH&cet7MpO*Ll;sS(?o= R0oKebZNJzC%-Y^@( b=J_AafuVjrGFCcKweV4tC&$|S@z;qX* z_Ggm5VmymH+McW|>$f+uTc)MpNS)?>>iNc9t`0-nVfbHQ6*+74v3a3s7k>n*zrzld zz_aag< Ee;YrsCjAVIiIrCt+n zjmZN6M&i}^s}F5mhBb!%JjeTC_UQGyqQGFB=odkeMYT!d%Qed|8It*&Qqy3e*7fAM ztGIkivJ1tz`%lbU&I;{{0jVn!dyoiR0x#hY4i*HrEfq$XJF4;*o5nQkgNhE$U#|6x zZ95-Fh}qtFjIul5a{+b}u!T>Hf4x_~ru35_pD$~c0FV_x(Lb^`Mc%ie!;0cwm AB4eH-E83Ag?CZ>)3g~UJl!3tJ53cSVIEM~|ixkXN7#=p8>DM qukE-3*UVjX? z)bo-zIEL$(CO8IXIr@>j71^L2k&t`Rv%Wbath?l;!8;{UA;USKR?7y*vDx+Ok`2|G z2870eo$uReY~X7a=Sk3sY_QW{MR}nrA4zDi0sRp!Y6HI9Esx{smFFu)L>TaQWN1)B zEzpak!$#c{0kI+lwA4VXgZ1$Yg*!qu+p#}|oBmwlp9K07ycuV(6bHgHm12`R%W#uA zA*vSnasuR7Y&K|@XrzwVJH0oeLRfrJ*8oCA;vLPO^i|?WkYR?!4PP9#d~q!DgLSDH zp!t9!?D_4r@6*8~ZYV}GxKkA)dZ-JU-o*tM2(_=Zjy6bX&YO~v_1KQ7CgI0#ezm0| z+ WWCHk>+3@Okq<@@67a9o7tZ zOgr~KFJenUH{HEnyW!e(jus1rKV9*m)*0o^dP1_?D1Ia~6Pb^UtMV06&~2?YW)gRB z1YbRsu$sOx>;y}j@ +id@vN zr|;NOjMAlN+;`iPuiItqw1^Y@vAQJuv1XY5aW~KT_bhRU){;KDLS6(#b|ReVg*B*F zi7D JK1oEZ zI1(5c*fa$M=j^)6!A~GAq(s$Kv=YszGUTMG=^vY|hmXfqM|?<6LG-UZxMWi-S>z#q zop6`^;@(-9jgw4d+7LZX0G~PQfm;p?^R>!Z2M?u!=cZE~NN}2cLxpAo7Lcj6Wi{{w z(iU^?@M7!Zf0 P4H4_cy6@9F6=4$hJc`cG8o1d~=r3{^MFEY4!dIlx=N9*- zX(4~CCo3Vm$5^Yh^7)mnHDiL@ HHKYl% z!<(7?y~qOPP(=rdb@C#xQI&P7xh?*hoCfbo!H5jU*yksc!PQFb7WfWnyv! r=}EV@mL=M4IQ_!dTf!u}lbTrJn*T)ANnHBH0l;ptG*qHruy13`I-3L| zfWVi4^Go1BVMjuE()lu3s?e^OY!UA&o6Jnr^?@)~QsN}oZTtdgkRFJsk)ChBtnz-> z7a1A|V1`8gtqs<2wIV@l7FAaeMfz7L;8EtX{0%0pgo+65i(`@pF}E0U%x_sli7I#H zX{mnc&lK{B5+QSe{i2QF@g2fz*ayW_WQE5TNd5NY%%sd)o^~ku;jwMPW8SxEi_*n1 z?VvWb!Z}>|_d0>@*F=2xr^8*LDop `n92xzAE-IYZsc|fj$$>c`+ZF8eba6^j2z~cw19;Q!Z+Al8r(YJMzy} z Zjq9^c)GX=+Az67;yJS;*>t!bQ^#<^D_a>YgbjL-5m}m (SWAyLeHRE9)M}Za6`iEF R$iozLADYs6o jzvCZ5uTBn>$Ojj=$!dUGlP2vq8~v5`mIL)Lu7);zWqQ2cst!IPuQE8RctI2hU` zP&3FBV%W_vASPEI;wtE@r(d_6mWGMvYZ~8WnT*i=BQ#xf*+;dKO2bm+opZE1e-J5T zK!U8NXU3w2gZnqi=VW$Nb(SUZ!;A|tw_L~D8$E;BlPRu{ m-@UtqOLv~%7z7p6)PFUuKxKZi4uW#rHij-l3oIm-{XsyEe%oC%F z3|q_g>KlN&qhxi|G2giSnD0T;EIcq_T4)o7*|@TwhXaSh`{(Oxb}G3Sd88Tq9Nltk zx3}=76s8hA!?*op4*Q9KO;ft`-GZ%(xo}@Lcm{Kd_~lE!QFgP_sOz~c;i#M@q*3K~ ztv%mgc-H1A5FU8plTiOLlXPsF&H#yO(z@lvSYZf*!Xb(S^CbB%;)WAV_eWJm{OTl! zS*}Qc%Y=>*nVixi<#Vr6>T}vjA#(kyFeys!U<_fL$}u-dmdP*>ZDQ2QhT6=q-^B2N zo2DB`tsRKGMr5cr`;%e`F=oLQB&LtjW`AIpZ5S {;P%(P^|O76dO!`TTNA@-B-`w%l|bB^MYe3;#@P6_$qLyN7*>p(H&+PXk4+a z^@+yeb+=x@PylZw*gq|n=sblG(847|NXs#oqNBiJhKHa9wg@6!n*DA#HmTcZg;Yo) zH)6Oy&EY1^=t {YoB`S-p!c%>h-iSw<4%U=T0lSPPT ~rm1q-9aAwyS@DzciwV8%R~t9Q^BH#6*dB z(>vAG7UMGEjze(hP{hvMGs$u%0o?hE!XHz_(*efJ< B9;;FCkEkGIOePr>>1j;rT^U!{#V8K zHs&DG;Z+O8 b(b5to27@YZ;?TvOwq(q^+!Np< z2WI7&dh9dVRCB{`l*(kM|EUgWS?|>*eyQGLHIVQrdO9B)s7iKLKJZaEl+ayzsKgg` zGhz{>>y>d2fjE2)Kqpb{{*KPHBa1uu?Z_`VDM2O^L}|6*@IF)4hCz)_CKv)n|14w? z8G?Q+HX<}vZbBp+X_GJ~>=dn@=m;112lZ8RGf^EnI%x#27*)v=6HO1oqJ4Z1fpup( zJ|OGv_)e$vX(seQL{2(2!THD_dIc{Hr(LWUCUd``1!_71KyIQOGMCG6yVTnhGd_%) ze{rbpz$x*p7qD$r*feUDMHG0p-CJ;%X^4i@vbk@8SPZ>NOgqwY`6dfT 9k%F55OQpIu~;AoqkR%QZDda4KyO*L6?F9ddLs#TZsuMeBWNj7#2S zPgz2%C8qK|ge>>>Nz8d}J=P+Z8t`H$eNGkWAhIm ni<9*;4h&+G6G_XG zrCw63NLN#-6J4W @I~H@ z_Wo@Qz?&I}%(BBj>G8tJpY3Xlb!n+%nmk8gInXVCeT`hlp%YyZU0tw&s>$wHr6}P1 zd*qyLhI|~?ZdgpT0|CnpMLyBdI}f^rmh zEtkqa;O3@5kU1J2l4XBk`(&ML%-nN>8O9e6NFu(owH9^7AN(d8sHA=s*w}1NY 8 z2xc-!1{b^Hhhy_h;u$q9A&zH&%Iso@E63p#0O42Z+z=CWPLsiPPnAh1)*)*q+dL?b z;Fccvqk^|7!zPdI^v4x*`u>ijfcP@?hJY0D04_(gowyx*E+hw3qX;dE%3}^blm7?; z2%b=Dg<3R|mWSpZi)6sbUPVpw!a>o>73(-Z=YlJ~G2Fcd?GyJOI8Q;ISfR#%$N_ZR z4NQC#D6>i4AwO>Yw^9erer`9@ZW)BLA$3Ri_280!dA%E6o!gQ6nO+Pex9*cXcTrn! z4!W~X=6pE=V~}yOlXD20&>MQO#(xgLOl%wU3$nck!kjp
^J1%W=kd$n zw!uZ7X|2U*ij-WN?`N<8!yn&g?2a{FD{cP#(>*G?%ba8l{