Please wait...
PlainTools’ Docs — PlainTools Documentation Skip to main content Back to top PlainTools’ Docs§ Welcome to PlainTools’ documentation! Current Version: 1.3.241226.0 PlainTools is a Python 3 library designed to streamline simple operations, loops and contexts with easy to handle classes and functions. Library’s Github Repo Library’s PyPi Repo Author’s Github Profile This documentation site itself can be accessed from the Python interpreter | environment with: import PlainTools as pt pt.site(pt) Copy to clipboard You can easily install & upgrade this package with: pip install -U plaintools Copy to clipboard ؜ [Table of Contents] Numeric Constructor The base solution for numberic-related problems. pt.Numeric pt.pnumber() Constructor Classes & Custom Objects Custom object constructors. pt.Container pt.Constant Formatter Functions Formatted data in an easy way. pt.plist() pt.punit() pt.pnumber() pt.pdecimals() pt.pstring() pt.pistype() pt.prange() pt.pinterval() pt.psequence() pt.pindex() pt.pminmax() pt.plen() pt.pabs() pt.psum() pt.pimport() pt.pframe() Statement & Extension Functions Powerful, close to native syntax and easy to use. pt.let() pt.const() pt.attempt() pt.printnl() pt.printc() pt.doc() pt.site() pt.skip() pt.evinput() pt.timeout() pt.loop() pt.showcall() pt.namespace() Debugger & Utility Functions Easy debugging management with console operations. pt.debug() pt.clear() pt.eof() pt.deepframe() Operator & Instantiated Classes Ready-to-use instances of functional objects. pt.TIME pt.STUB pt.NULL pt.ERROR pt.MAIN pt.SILENCE pt.LOGGING pt.TRY pt.LINES pt.SEVAL pt.TEST Documentation Utilities Functions designed to retrieve and explore available documentation. pt.doc() pt.site() pt.moduleview() [Introduction] The following needs to be considered when reading these docs: It is encouraged that you use the suggested convention: import PlainTools as pt It is assumed that you know the basics of Python’s data types. Type annotations were made in a more verbose way, with: X: Integer Instead of: X: int Unfamiliar types like ‘Real’ can be associated with what meaning they first convey: Having a variable declared as: Y: Real Is the same as: Y: int | float | decimal.Decimal | fractions.Fraction And is itself similar or very closely related to ‘numbers.Real’. Any documentation found here can be similarly provided in the Python context or environment running this module by the use of the pt.doc() function as: pt.doc(*objs) Where objs is the desired function(s) or class(es) to obtain documentation from. This will print the target’s documentation, if any, to the current console or stdout in general. Note that pt.doc() also works with any builtin object as well as third-party ones, given they have any type of docstring themselves. [Resources & Credits] This project would be impossible to make without the support of my friends and family around me. Thank you everyone. Credits & Thanks: A big thanks to my professor Vitor Tocci, who lectured Introduction to Data Proccessing and introduced me into Python programming when I had little background experience in the matter. Thanks to my beloved girlfriend Ana Caroline, who tirelessly heard me babble about Python through hours in these past few months where I was still learning and improving much of my understanding of the language. I love you! Thanks to all of my friends and family, including @CherryGM who helped me revise this documentation and greatly encouraged me. And to everyone who helped me debug this documentation itself when I had zero Sphinx knowledge. I hope I did well enough and hope to do much more in the future! Disclaimer: LLM (AI) Use: ChatGPT, Codeium and Gemini (The later not credited as it did not “contribute” directly to the codebase) were used in this project development. If you, your university or your company (in general, if the target for this library’s use) does have any restrictions, implicit or explicit, against the use of LLMs in production | academic coding, please avert from using this library. Any code “contributed” by or taken from any LLM (AI) use, prompted directly or indirectly, was heavily debugged and tested (to the best of my personal capacity). If any code comes across as sluggish, unnoptimized or just bad, please let me know by raising an issue or DMing me at GitHub (@gabrielmsilva00), or email me at @gabrielmaia.silva00@gmail.com. For a more clear understanding of the above, you will probably find 40~80% LLM-made code wherever attributes from the following libraries were used: re ast itertools functools multiprocessing References & Auxiliary Material: AutoPEP8, code formatting; Sphinx, documentation; Sphinx-Design, styling; StackOverflow, definitions, concepts; W3Schools, theories, fundamentals, methods; OpenAI’s ChatGPT, definitions, debugging; Claude AI, additional debugging; Codeium AI, autocompletion, code refactoring & cleaning; SingleFile, HTML factoring of this Sphinx-generated documentation; JetBrains Mono, this awesome font! Google Search Console: This page is currently verified at Google Search. No Google Analytics is currently being used anywhere in this project. ؜ Numeric Constructor§ (Goto Table of Contents) Before anything else, it is important to lay down the documentation for the base of any numeric-related definition or class. And such is the pt.Numeric class and pt.pnumber() function. class pt.Numeric(obj) → Numeric[Number]:§ Numeric Class This is the base class for the numeric constructor. It dynamically inherits from its obj object’s class, meaning that a float object gives a direct inheritance of float to the pt.Numeric instance, gaining all its properties. Possible inheritances are defined inside the numbers.Number standard definition of Python 3.11+ numbers library. Failure to inherit from a recognizable Number type will default the instance to pt.Numeric(float(‘nan’)) pt.pnumber(*objs) → Number | List[Number]:§ Plain Numeric Constructor. For each input, this function constructs a pt.Numeric class instance which dynamically inherits from the input’s parent class. This means that all numeric types such as int, float, complex, decimal.Decimal and fractions.Fraction given to this function will generate a subclass instance with inheritance from the object’s own numeric class. Failure to convert the object to a numeric type (contained into the numbers.Number definition) will result in an instance of float(‘nan’) class being returned. Examples: Considering x = pt.pnumber(1/3); ؜ print(x) 0.333... The pt.pnumber() constructor detects repeating decimals. x.value 0.3333333333333333 This is used for proper arithmetic operations. x.period 3 This is the detected repeating decimal. x.fraction (1, 3) The fraction part can be used for reconstruction of the numeric object. x.type <class 'float'> The x object dynamically inherited from the float class. Args: obj: Any | Iterable[Any] Object(s) to pt.SEVAL(obj) into a numeric type. Failure to safely convert to a numeric type will return float('nan'). Returns: R: Number | List[Number] Numeric-type instance(s) (of isinstance(obj, numbers.Number)). The numeric class created dynamically inherits from the obj own class. Note: It is computationally expensive: non-ideal for long sequences. The trade-off [precision <> speed] is comparable to decimal.Decimal’s implementation, where pt.Numeric(n) takes about 100x more time to instantiate than i.e. float(n). However, its default precision of {n:.15g} for any given n and its capability of detecting repeating decimals etc. make it much more presentable and workable, eliminating MANY cases of float-imprecison errors. Constructor Classes & Custom Objects§ (Goto Table of Contents) Constructor Classes have the purpose of creating Custom Objects that can be manipulated in specific, useful ways. A more in-depth explanation is provided in each’s documentation below. class pt.Container§ Container Class; dict Subclass. A flexible dict-class that supports various operations and transformations. Unlike a standard dictionary, a Container is unpacked by its items rather than by its keys. Note: Containers can’t have numeric keys due to how their keys are directly associated to its instance attributes. However, any String type is a valid key type. Attempting to update a Container instance with enumerated dictionaries will raise a TypeError. The Container supports basic arithmetic operations on a per-key basis, meaning that you can operate an iterable to a Container, where each ordered element operates each key’s value until exhaustion; Where as single, non-iterable operations are performed on the entire Container. Containers can have its values accessed as attributes when calling for their keys. This means that assigned attributes into this class are also added to the Container’s keys with the designated value. Examples: C1 = Container(a=1, b=2) Creates a Container as {‘a’: 1, ‘b’: 2} C2 = Container(‘c’) Creates a Container as {‘c’: None} C1(C2) # Same as C1 += C2 Aggregates C1 and C2 for {‘a’: 1, ‘b’: 2, ‘c’: None} C1.fill(4) Alocates ‘4’ to the first encounter of None value in C1. Methods: .sort(*args, **kwargs): Self Sorts the keys (or values) of the Container; Optional lambda. .shove(*vals): Self Adds the values to the keys following the current order of keys. .fill(*vals, target=None, exhaust=True): Self Fills in any target vals in the Container with provided vals. target argument can be a lambda | function | builtin | singleton. exhaust argument defines if fill is finite or cyclic infinite. .order(*keys): Self Orders the keys of the Container as provided. .filter(*keys): Self Filters the keys of the Container as provided. .remove(*keys): Self Removes the keys of the Container as provided. .only(*keys): Container Returns a Container copy containing only the specified keys. .without(*keys): Container Returns a Container copy without the specified keys. .keyval(): dict Returns a copy of the dictionary object as {keys: values}. .key(*keys): list Returns a list of keys in Container; Optional filter for values. .val(*vals): list Returns a list of values in Container; Optional filter for keys. .sub(): Tuple[Container] Returns a tuple of each k: v pair in Container, as Containers. .copy(): Container Returns a deepcopy of the current Container. Operators: Any basic arithmetic operator is supported as in: Container <> Container; Container <> other Operations with non-iterables are valid as long as the operation to every Container[k:v] <> other is valid for all given (v). Container(f=1, g=2, h=3) * 2 == Container(f=2, g=4, h=6) Container(Bob=’Foo’) - 5 == Container(Bob=’Foo’, Bob_1=5) Operations with iterables are valid as long as the operation to every pair Container[k:v] <> other[i] is valid for the max possible [i]. Container(R=5, S=10) * (2,3,4) == Container(R=10, S=30) Container(T=2,U=4,V=6) - {2,3} == Container(T=0, U=1, V=6) Remainder of Container <> other[i] operations are ignored, as the result is a Container type with the same keys as the involved Container. Container(i=2, j=3) * [2, 3, 4] == Container(i=4, j=9) Remainer of Container <> Container operations aggregate non-similar keys into the final result, unmodified, as no C1[k] <> C2[k] is valid. Container(f=5) - Container(g=10) == Container(f=5, g=10) add (+) Adds the values of another Container, or from a sequence. i.e. Container(a=5) + (b=4) == Container(a=5, b=4) i.e. Container(a=5, b=4) + [3, 4] == Container(a=8, b=8) sub (-) Subtracts the values of another Container or from a sequence. i.e. Container(x=5, y=10) - 3 == Container(x=2, y=7) i.e. Container(a=5, b=4) - Container(c=3, d=2) mul (*) Multiplies the values of another Container or from a sequence. i.e. Container(x=5) * 2 == Container(x=10) i.e. Container(x=5, y=4) * (3, 4) == Container(x=15, y=16) truediv (/) Divides the values of another Container or from a sequence. i.e. Container(T=2, U=4, V=6) / [1, 2, 3] == Container(T=2.0, U=2.0, V=2.0) floordiv (//) Floor divides the values of another Cont. or from a sequence. i.e. Container(A=12.5) // Container(A=3.5) == Container(A=3.0) mod (%) Modulo operates on the values of another Cont. or from a seq. i.e. Container(B=7.5) % Container(B=2) == Container(B=1.5) pow (**) Raises the values of the Container to the power of. i.e. Container(C=5) ** Container(C=3) == Container(C=125) Return: Container A dict subclass object that is callable. class pt.Constant§ Immutable Constants. Wraps a value and provides a constant, immutable interface to it. Overrides most of the standard dunder methods to ensure immutability. Non-dunder methods can be called, but will only return the Constant’s value and won’t modify the Constant itself or it’s value in any way. Examples: x = Constant(5) Create an immutable constant with a value of 5 i.e. x + 5 == 10 i.e. x += 5 ; x == 5 pi = Constant(math.pi) Assign ‘math.pi’ to ‘pi’ as an immutable constant i.e. const(rpi=pi*2) # ‘rpi’ is also a Constant now. Args: value: Any The value to be wrapped as a Constant. Return: Constant An immutable Constant instance wrapping the provided value. ؜ Formatter Functions§ (Goto Table of Contents) Formatter functions are intended to take a variety of types as input and output data in a formatted, previsible way. pt.plist(*vals) → List[Any]:§ Plain List. Transforms iterable sets into a flat list; Recursive unpacking. Pseudocode: If one (List) contains other (Lists) inside: (Unpack) the (Lists) inside, keeping only the (Values). This repeats until all (Lists) only contains plain (Values). Return a final (List) containing only the (Values) of everything given. Examples: plist((1, 2), [3, 4], {5, 6}) [1, 2, 3, 4, 5, 6] plist({0: 10, 1: 20, 2: 40}) [10, 20, 40] plist({‘A’:10, ‘B’:15, ‘C’:20, ‘D’:{“X”: 100, “Y”: 200, “Z”: 300}}) [10, 15, 20, 100, 200, 300] Args: *vals: Any | Iterable[Any] Data entries to be flattened. Return: R: List[Any] Flat list containing the data entries. pt.punit(*its) → Any | Tuple[Any]:§ Plain Units. Unpacks single units inside iterable sets; Returns a single value if there is only one value in the iterable. Pseudocode: If any given (List) contains a (Single) (Value): (Unpack) the (List), so it becomes it’s plain (Value). If (Final List) contains (Multiple) (Values): Return (Final List). Else, if (Final List) contains a (Single) (Value): Return (Value). Examples: punit([5], [3, 2], [[9]]) (5, [3, 2], 9) punit([1, 2], 3, (4,)) ([1, 2], 3, 4) punit([[7, 8]], {9}) (7, 8, 9) Args: *its: Iterable[Any] Iterable sets. Return: R: Any | Tuple[Any] A single item or a tuple of items. pt.pdecimals(*nums) → Integer:§ Plain Decimals. Identifies the highest number of decimal places in a set. If the number has a repeating period (detected by pt.pnumber()), the return value will be float(‘inf’), even if the Python representation of the float(num) is limited to 16 decimal places. Pseudocode: Start (Decimals) as 0. (For Each) (Value): If (String) of (Number) in (Value) have (‘.’) character: (Count) how many (Digits) there is after (‘.’) character. If (Digits) is greater than (Decimals):(Decimals) become number of (Digits). Return final (Decimals) value. Examples: pdecimals(1.23, 4.5678, 3.1, 5.67890) 4 pdecimals(1/3) inf pdecimals(math.pi) 15 Args: [*]nums: Number | Iterable[Number | String] Numbers to be formatted. Return: R: Integer Highest quantity of decimal places found. pt.pstring(*objs, sep=', ') → String:§ Plain String. More comprehensible ‘str()’ operator; Concatenates elements of iterables. Pseudocode: Check (Type) of (Value): If (Type) is (Dictionary):(Include) the (Keys) and (Values) of (Dictionary) in the (String). Else, if (Type) is a (List), (Tuple) or (Set):(Include) all (Values) in the (String). Else, if (Type) is (Something Else):(Include) the String of (Type) in the (String). Return final version of (String). Examples: pstring({0: ‘a’, 1: ‘b’, 2: ‘c’}) ‘0: a, 1: b, 2: c’ pstring([1, 2, 3], (4, 5), {6, 7}) ‘1, 2, 3, 4, 5, 6, 7’ pstring(‘Hello’, [‘world’, ‘!’], sep = ‘ ‘) ‘Hello world !’ Args: *objs: Any | Iterable[Any] Objects to be converted to string. Kwargs: sep: String = ‘, ‘ Separator between elements in the final string. Return: R: String Single string containing the concatenated elements. pt.pistype(obj, *types) → Bool | Tuple[Bool]:§ Plain Type Check. Checks if the object is an instance of the provided types. Pseudocode: Check (Type) of (Value) and (Type) of (Asked Types): (For Each) (Asked Type): If (Type) of (Value) is the same as this (Asked Type):(Include) (True) in the final (Result) Else, if (Type) of (Value) is not the same as this (Asked Type):(Include) (False) in the final (Result) Return the final (Result). Examples: pistype(‘Hello’, String, Iterable, Set) (True, True, False) pistype([1, 2, 3], List, Tuple, Iterable) (True, False, True) pistype(42.0, Number, Integer, Float) (True, False, True) Args: obj: Any Object to be checked against. *types: Type Types to compare using isinstance(obj, type). Return: R: Bool | Tuple[Bool] Sequence of Booleans according to the checks. pt.prange(*args, type='list') → Iterable[Number]:§ Plain Range. Simulates the ‘range()’ function from Python 2.x. Instead of a range object, returns a plain Iterable of specified type. Default Iterable type is ‘list’. The ‘chain’ type is also available. Stop argument is the de-facto stop, being the last value of list. Args functionality is the same as standard ‘range()’ built-in function. Pseudocode: Check for the given (Parameters): If there is (One) (Parameter):Return a (List) (Starting) at (0) and (Stopping) at (Parameter) with an (Step) of (1). Else, if there are (Two) (Parameters):Return a (List) (Starting) at (1st Parameter) and (Stopping) at (2nd Parameter) with a (Step) of (1). Else, if there are (Three) (Parameters):Return a (List) (Starting) at (1st Parameter), (Stopping) at (2nd Parameter) with a (Step) of (3rd Parameter). Else, if there are (Four) (Parameters):Return an (Iterable) of (Type) (4th Parameter), (Starting) at (1st Parameter), (Stopping) at (2nd Parameter) and with a (Step) of (3rd Parameter). Return the final (Iterable). Examples: prange(5) [0, 1, 2, 3, 4] prange(5, 2.5, 0.5, ‘tuple’) (5, 4.5, 4, 3.5, 3, 2.5) prange(0, 15, 4, ‘dict’) {0: 0, 1: 4, 2: 8, 3: 12} Args: *args: Number Functionality varies according to arguments: A single parameter determines the stop; with start of 1. Two parameters determines start and stop; with step of 1. Three parameters determines start, stop and step; returning a list. Four parameters determines start, stop, step and type Kwargs: start: Number = None Start value of the iterable. stop: Number = None Stop value of the iterable. step: Number = None Step value of the iterable. type: String = None Return type (‘tuple’, ‘list’, ‘set’, ‘dict’, ‘chain’). Return: R: Iterable[Number] = Iterable (defined in ‘get’) containing the range. pt.pinterval(*args, type='list') → Iterable[Number]:§ Plain Interval. Generates a list of numeric elements equidistant between them, from start to stop. Pseudocode: Check for the given (Parameters): If there is (One) (Parameter):Return a (List) (Starting) at (0) and (Stopping) at (100) with (Parameter) (Values). Else, if there are (Two) (Parameters):Return a (List) (Starting) at (0) and (Stopping) at (2nd Parameter) with (1st Parameter) number of (Values). Else, if there are (Three) (Parameters):Return a (List) (Starting) at (2nd Parameter), (Stopping) at (3rd Parameter) with (1st Parameter) number of (Values). Else, if there are (Four) (Parameters):Return an (Iterable) of (Type) (4th Parameter), (Starting) at (2nd Parameter), (Stopping) at (3rd Parameter) and with (1st Parameter) number of (Values). Return the final (Iterable). Examples: pinterval(5) [0, 25, 50, 75, 100] pinterval(3, 5) [0, 2.5, 5] pinterval(5, 10, 0, ‘dict’) {0: 10, 1: 7.5, 2: 5, 3: 2.5, 4: 0} Args: *args: Number Can contain up to four positional arguments: One argument: divs;List of [0, 0±n1, 0±n2, (…), 100] with ‘divs’ elements. Two arguments: divs and stop;List of [0, 0±n1, 0±n2, (…), stop] with ‘divs’ elements. Three arguments: divs, start and stop;List of [start, start±n1, (…), stop] with ‘divs’ elems. Four arguments: divs, start, stop and type.Iterable of type(start, (…), stop) with ‘divs’ elements. Kwargs: divs: Number = None Number of elements in the returned Iterable. start: Number = None Start value of the interval (default is 0). stop: Number = None Stop value of the interval. type: String = None Type of the returned collection (‘list’, ‘tuple’, ‘set’, ‘dict’). Return: R: Iterable[Number] List of numeric values with equidistant intervals. pt.psequence(*nums, abs_lim=None, rel_lim=10e3) → Chain[Real]:§ Plain Sequence. Generates a numerical sequence based on the provided numbers or patterns. It supports the use of ellipsis (…) to denote the continuation of the sequence with a defined step or to an optional limit. Args: *nums: Real | Iterable[Real] The numbers or patterns used to generate the sequence. Ellipsis (…) can be used to sign continuation of sequence. Kwargs: abs_lim: Real = None The absolute limit for the sequence, if provided. rel_lim: Real = 10e3 The relative limit, as a multiplier to the last expressed num. Return: R: Chain[Real] A chain of numbers representing the generated sequence. Examples: psequence(1, 2, 3, …, 10) Generates the sequence equivalent to (1, 2, …, 9, 10). psequence(1, 3, 5, …, abs_lim=150) Generates the sequence equivalent to (1, 3, …, 147, 149). psequence(0.1) Generates the sequence equiv. to (0.1, 0.2, …, 999.9, 1000). Notes: If an ellipsis (…) is used, the function will infer the step from the preceding numbers in the sequence. If abs_lim is provided, the sequence will stop when it reaches or exceeds this limit. If rel_lim is provided, it will be used to calculate the maximum limit based on the last number in the sequence before the ellipsis. The sequence continues either until the absolute or relative limit is met. pt.pindex(target, *its) → Integer | None | Tuple[Integer | None]:§ Plain Index. Returns the index of the first occurrence of ‘target’ in ‘its’. Pseudocode: Look for (Target) in all (Iterables) provided: (For Each) (Iterable): If (Target) is found in this (Iterable):(Include) (Target)’s (Index) in the final (Result). Else, if (Target) is not found in this (Iterable):(Include) (None) in the final (Result). Return the final (Result). Examples: pindex(True, (False, False, True)) 2 pindex(5, range(10)) 5 pindex(1, (False, False, True), [‘a’, ‘b’, ‘c’], range(10)) (2, None, 1) Args: target: Any Value to search for in the provided iterables. *its: Iterable[Any] One or more iterables to be checked for ‘target’. Return: R: Integer | None | Tuple[Integer | None] Index of the first ‘target’ occurrence into provided iterables. pt.pminmax(*vals) → Container[String: Number]:§ Plain Min & Max. Returns the minimum and maximum values from a set of numbers. Pseudocode: Given any (Values) or (Iterables[Values]):Return both (Minimum) and (Maximum) from all given (Values). Examples: pminmax([5, 2, -8, ‘15*2’]) {‘min’: -8, ‘max’: 30} pminmax([5, 2, -8, ‘15*2’]).min -8 pminmax(1, -2, [‘1.5 * 2’], math.pi)[1][1] 3.141592653589793 Args: *vals: Number | Iterable[Number] Objects to be compared for their value. Return: R: Container[String: Number] A Container, derived from dict, containing min & max values. pt.plen(*iters) → Container[String: Integer]:§ Plain Length. Returns the minimum and maximum sizes of given iterables. Pseudocode: Given any (Iterables):Return both (Minimum) and (Maximum) (Size) from all given (Iterables). Examples: pcount([1, 2, 3], (4, 5), {6}) {‘min’: 1, ‘max’: 3} pcount([1, 2, 3, [4, 5], 6], (“ABCDEFGHIJ”, “XYZ”), {}).min 0 pcount({0: 1, 1: -2, 2: 4, 3: -8, 4: 16, 5: 32}).max 5 Args: *iters: Any | Iterable[Any] Objects to be counted for their sizes. Return: R: Container[String: Integer] A Container , derived from dict, containing min & max lengths. pt.pabs(*nums) → Container[String: Number]§ Plain Absolutes. Identifies the lowest or highest absolute number of a set. Returns a Container with the min, max, original min, original max values. Pseudocode: (Flatten) the input (Values). - Calculate the (Absolute) (Maximum) (Value). - Calculate the (Absolute) (Minimum) (Value). - Identify the (Original) (Maximum) and (Minimum) (Values). Return a (Container) with (Absolute) and (Original) (Minimum) and (Maximum) (Values). Examples: x = pabs([5, 8, -2, ‘15*2’]) x == {‘min’:2, ‘max’:30, ‘ogmin’:-2, ‘ogmax’: 30} x.min == 2 x.ogmin == -2 x.max == x.ogmax == 30 y = pabs(-1, -2, [‘1.5 * 2’], math.pi) y[‘min’] == 1 y[‘ogmin’] == -2 y[‘max’] == 3.141592653589793 zmin, zmax, ztruemin, ztruemax = pabs(prange(-10, 0, 1)) zmin == 0 zmax == 10 ztruemin == -10 ztruemax == 0 Args: *nums: Number | Iterable[Number | String] Objects to be counted. Return: R: Container[String: Number] A Container, with min, max, original min and original max. pt.psum(*nums) → Real:§ Plain Sum. Returns the sum of possible numbers from given sets. Examples: psum([5, 2, -8, ‘15*2’]) 29 psum(prange(-10, 0)) -55 psum(Container(John=2.55, Maria=3.14, Paul=1.75)) 7.44 Args: *nums: Real | Iterable[Real | String] Objects to be counted. Return: R: Real Sum of numbers. pt.pimport(libs, funs=None) → Module | Object | Tuple[Module | Object]:§ Plain Import. Helper function for local scope importation. Pseudocode: (Split) (Libs) into individual (Module Names). (For Each) (Module Name): Attempt to (Import) the (Module). If (Funs) are given, attempt to (Import) only the specified (Objects) from the (Module). Return the (Imported) (Modules) or (Objects) as (Objects). Examples: calc = pimport(‘math’) Allocates ‘calc’ as an alias to the ‘math’ module. ie: calc.e == math.e pi, log = pimport(‘math’,’pi, log’) Allocates to variables the imported objects (math.pi & math.log). ie: pi == math.pi Args: libs: String Modules to import; separated by comma in the 1st string. (‘a, b, c’). funs: String = None Objects to import; separated by comma in the 2nd string. (‘a, b, c’). Return: R: Module | Object | Tuple[Module | Object] Imported modules or objects. pt.pframe(depth, outer=False) → Frame:§ Plain Frame. Helper function for getting the frame information in the specified depth. Pseudocode: (Inspect) all the current (Frames). Return the (Depth)º (Frame), counting from the current (Frame) outwards. Examples: (@file PlainTools.py) x = pframe() x.f_code.co_filename == ‘..\path\PlainTools.py’ x.f_lineno == (Line number of pframe() call) x.f_code.co_names == (Tuple of strings of names used in the program) x.f_locals == Current frame’s locals() dictionary. x.f_globals == Current frame’s globals() dictionary. Args: depth: Integer = 1 (Default: 1) How many frames to go in; Note that this is in reverse order, so a depth=2 inspects the currentframe up until currentframe()[-2] Kwargs: outer: Bool = False Determines if the Frame is get from inspect.getouterframes() Return: R: Frame Frame object. ؜ Statement & Extension Functions§ (Goto Table of Contents) Statement Functions bring new, easy-to-use functions that improve the native, standard syntax and built-in functions. pt.let(**kwargs) → Container[Any: Any]:§ Let ‘Statement’. Note: The ‘let()’ function is unusable inside function definition scopes; It is neither a bug nor fixable, but a limitation of the Python language. Assigns and evaluates multiple variables in a single function call. Keep in mind that real assignment happens after the function call ends; Doing ‘let(x=5, y=10, z=x+y)’ raises ‘NameError: name ‘x’ is not defined’; But doing ‘let(x=5, y=10), let(z=x+y)’ works just fine. Examples: let(x=5, y=10, z=math.pi) (5, 10, 3.141592653589793) x = 5 y = 10 z = 3.141592653589793 let(w=Seval(‘15 ** 5 / 2’)) w = 379687.5 Kwrgs: **kwargs: Any Direct assignments to given kwarg variables. Return: R: Container[Any: Any] A Container with the relationed objects assigned. pt.const(**kwargs) → Container[Constant: Any]:§ Constant ‘Statement’. Note: The ‘const()’ function is unusable in function definition scopes; It is neither a bug nor fixable, but a limitation of the Python language. Assigns and evaluates multiple constant variables in a function call. Returns Constant objects, being immutable by nature. Keep in mind that real assignmenet happens after the function call ends; Doing ‘const(x=5, z=x+5)’ raises ‘NameError: name ‘x’ is not defined’; But doing ‘const(x=5), const(z=x+5)’ works just fine. Examples: const(x=2.5, y=3.5) (2.5, 3.5) x == Constant(2.5) y == Constant(3.5) const(z=[0, 1, 1, 2, 3, 5, 8, 13]) z == Constant([0, 1, 1, 2, 3, 5, 8, 13]) Kwargs: **kwargs: dict Additional constants to assign in the current context. Return: R: Container[Constant: Any] A Container with the relationed objects assigned as Constants. pt.attempt(fallback, operator, *args, **kwargs) → Any:§ Attempt Operator Attempts to execute operator(*args, **kwargs), returns ‘fallback’ if any exceptions occur. pt.printnl(*args, **kwargs) → None:§ New Line Print. Rationale: Prints the input with a new line after each prompt. pt.printc(*args, fill=' ', **kwargs) → None:§ Centered Print. Rationale: Prints the input centered on the window; Fills with (fill) character. pt.showcall(func) → Function:§ Show Call Information. This decorator outputs detailed information about the function call, including the line number, function name, arguments, return value or error, and execution time. It is useful for debugging and monitoring function execution. Examples: @showcall def my_function(x, y): ؜؜؜؜return x + y my_function(3, 4) [!-CALL-!] Ln 10 # Example! Fn my_function A* (3, 4) K* {} R* 7 Tm 0.0001s ؜ @showcall def vec_func(i, j, k, op=’div’): ؜؜؜؜(…) ؜؜؜؜if op == ‘div’: ؜؜؜؜؜؜؜؜return (i * j) / k vec_func(2, 3, 0) # Division by zero! [!-CALL-!] Ln 14 # Example too! Fn vec_func A* (2, 3, 0) K* {‘op’: ‘div’} R* [!-ERROR-!] Er ZeroDivisionError As division by zero Tm 0.017s pt.namespace(name) → Container:§ Namespace Viewer. Returns a Container of a module’s or frame’s attributes and values. Note that, as the return type is a Container, you can do such as: calc = namespace(‘math’) calc.pi # the exact same as math.pi Examples: namespace(‘math’) Returns a Container(k:v) for every ‘k:v’ pair inside ‘math’ module. i.e. {‘pi’: 3.141592653589793} i.e. {‘sqrt’: <built-in function sqrt>} Args: module: Module | String Module to be viewed. If String, its imported as a module object. Return: R: Container View of the module as k:v pairs. pt.skip(n=1, *args, **kwargs) → None:§ Line Skip. Rationale: Prints into de console ‘n’ times; Defaults to a 1 line skip. pt.evinput(*args, **kwargs) → None:§ Evaluated Input. Rationale: Performs a Safe Eval (see: Seval@:ref:Instantiable Classes) into the input, converting to adequate types. pt.timeout(secs, func, *args, **kwargs) → Any | Error:§ Timeout. Runs a function in a separate proccess with a time limit; Raises an exception if it exceeds given limit in seconds. Examples: timeout(5, long_running_function, arg1, arg2) Executes long_running_function(arg1, arg2) with a 5-second limit. Args: secs: Number Time limit in seconds. func: Callable Function to execute. *args: Any Positional arguments to pass to the function. **kwargs: Any Keyword arguments to pass to the function. Return: R: Any | Err The result of the function, or an exception if timed out. pt.loop(times=0, escape=KeyboardInterrupt, loopif=True, show=False, nl=False) → Decorator:§ Loop Decorator. A decorator that repeatedly executes the function based on specified conditions. It allows for control over the number of iterations, conditional execution, and exception handling within the loop. Exceptions raised by the function do not inherently stop the loop unless their type is specified in the escape parameter. However, the KeyboardInterrupt exception is guaranteed to always be caught and interrupt the loop execution. Examples: @loop(times=3) def my_function(x): ⠀⠀⠀⠀print(f”Value: {x}”) This will print the value of x three times at ‘my_function()’. ؜ @loop(loopif=lambda: some_condition()) def my_function(x): ⠀⠀⠀⠀print(f”Value: {x}”) This will execute my_function as long as some_condition() returns True. ؜ @loop(escape=KeyboardInterrupt) def my_function(x): ⠀⠀⠀⠀print(f”Processing {x}”) This will execute my_function in a loop until a KeyboardInterrupt exception is raised. ؜ @loop(times=5, show=True) def example_function(x): ⠀⠀⠀⠀print(x) This will run ‘example_function()’ 5 times, printing the iteration details each time. Args: times: Integer = 0 The number of times to execute the decorated function. If set to 0, the loop will run indefinitely unless broken out. Default is 0. escape: Exception | Tuple[Exception, …] = KeyboardInterrupt Exception(s) that, if raised, will stop the loop. Default is KeyboardInterrupt (guaranteed even if changed). loopif: Function | Bool = True A condition that, if evaluated to False, will break the loop. It can be a Lambda type with out-scope parameters or conditions. Default is True. show: Bool = False If True, prints the function name, arguments, and iteration. Default is False. nl: Bool = False If True, inserts a newline after each iteration. Default is False. Return: Decorator A decorator that wraps the provided function. Debugger & Utility Functions§ (Goto Table of Contents) Debug functions interact with the environment the script runs in, and output relevant information to the console. These functions do accept arguments only as buffers, this being, arguments given have no impact in the output, but serve the purpose of executing code in the same line, such as starting a timer for example. pt.debug(*buffer) → List[String] | None:§ Debug Traceback. Examples: Try: (…) Except: printnl(*debug()) Rationale: Returns the traceback, if any. pt.clear(*buffer) → None:§ Clear Screen. Rationale: Simple command to clear the console feed. pt.eof(*buffer) → SystemExit:§ End of File. Rationale: Logs into a .log file, waits for user input, and then exits the system. pt.deepframe(*buffer) → None:§ Deep Frame. Rationale: Prints the full depth of the current path and the frame stack. ؜ Operator & Instantiated Classes§ (Goto Table of Contents) Operator Classes are classes able to be used as functions, objects, contexts and as the name sugests, come with pre-loaded instances that are ready-to-use. The class definition for these objects is given in UPPERCASE, as in: class TIME:(…) Where the instances are given in PascalCase, as is with other non-operator classes, so: Time = TIME(std=’now’) Runtime = TIME(std=’lap’) Crono = TIME(std=’epoch’) Are all instance examples of the operator class ‘TIME()’ class pt.TIME§ Execution Timer. A running timer that starts immediately when instantiated. Examples: X = TIME() Starts ‘X’ as a timer. with X: Starts a timed context with ‘X’; prints time on exit. X.show Prints the current time in string format. Args: add: Float = 0.0 Time to add to the timer. std: String = ‘now’ Initial standard mode (‘now’, ‘lap’, or ‘epoch’). Methods: .mode(std: String = ‘’) -> Class Changes the standard mode of the timer. .now -> Float Returns the time since the last call. .lap -> Float Returns the current time. .reset -> Class Resets the timer. .string -> String Returns the time as a string. .show -> String Prints the current time in string format. .epoch -> List[Float] Returns recorded times. Instances: Time = TIME(std=’now’) Timer that returns the time since the last call. Runtime = TIME(std=’lap’) Timer that returns the total elapsed time. Crono = TIME(std=’epoch’) Timer that returns the entire history of recorded times. Return: R: Float | List[Float] Time in seconds.milliseconds (e.g. 1.234). class pt.STUB§ Decorator @Stub | Object Stub. Decorates an incomplete function, indicating it has not been implemented yet. Examples: @Stub Prints the stub location when the function is called. Stub() Prints the stub status, current line and module of call. Stub Null object with empty representation. Instances: Stub = STUB() Return: R: Class | Callable Decorated function or Stub object. class pt.NULL§ Null Object Pattern. A class that implements the Null Object Pattern by defining methods and operations that return neutral values or perform no actions. Examples: Nil = NULL() Assigns an instance of the NULL class. Default instance is ‘Null’. Null + 5 Performs a no-op and returns Null itself. Null str(Null) Returns an empty string. ‘’ Null.attribute Accesses a non-existent attribute, returns Null. Null Null == None Null has equality to None. True print(Null) Prints nothing. Same as print(). Instances: Null = NULL() class pt.ERROR(NULL, Exception)§ Error Object. A specialized version of the NULL class that represents an error state, overriding string and representation methods to return ‘Error’. Examples: print(Error) Error raise Error: PlainTools.ERROR: Error Instances: Error = ERROR() class pt.MAIN§ Main script guard. Evaluates if the script is being executed directly; Similar to __name__ == ‘__main__’. Examples: if Main: Evaluates if __name__ == ‘__main__’. with Main: Enters the ‘Main’ context, only executes if Main. Main(*args, **kwargs) Invokes the ‘Main’ context; runs local ‘main(*args, **kwargs)’. main(*args, **kwargs) # Inside ‘with Main:’ context. Methods: .time -> Float Returns the script execution time. .showtime -> String Displays the script execution time. .clear -> Self Clears the console; Executed by .start. .start -> Self Invokes .time & .clear. .end -> Self Ends the program after debugging and logging. Instances: Main = MAIN() Return: R: Bool = True if the script is being executed directly. class pt.SILENCE§ Context manager that suppresses console output. Redirects stdout and stderr to /dev/null, effectively silencing all output within the context. Examples: with Silence: Silences all console output within the context. Instances: Silence = SILENCE() Return: R: Class = Context manager that suppresses console output. class pt.LOGGING§ Functional Logging. Stores provided strings or objects in an internal list; Writes them to a (filename).log file. Examples: Logging(“message”) Logs “message” in the internal list. Logging([1, 2, 3]) Logs each element of the list on separate lines. Args: obj: Any Object(s) to be logged. Methods: .get -> List Returns the internal list of logged entries. .flush -> Self Writes the current log to a file and clears the internal list. This is automatically done at exiting the ‘with Main’ context. .show -> Self Displays the stored messages from the log list. .reset -> list or None Resets the internal list of logs to empty. Instances: Logging = LOGGING() class pt.TRY§ Try Context. A simpler ‘try’ context, with no direct error handling; Exits the context instead. Can be done in a verbose way by the use of ‘with Try.show:’ method. Examples: with Try: Begins execution and tracks its success or failure. Methods: .show -> Self Enables verbose mode to print the context’s progress and results. Properties: verbose: Bool = False Controls whether to print the result to the console. result: String Stores the result of the try block, indicating success or failure. class pt.LINES§ Line Number Context Manager. A context manager that prefixes each line of output with the line number. Examples: with Lines: print(“Hello, World!”) # Output will be prefixed with line no. Instances: Lines = LINES() class pt.SEVAL§ Safe Expression Evaluator. A secure alternative to Python’s eval() function, designed to evaluate mathematical and basic expressions while preventing access to unsafe operations and functions. Examples: Seval(“2 + 2”) 4 Seval(“round(math.pi * 2, 2)”) 6.28 # Only if ‘math’ is imported in the current namespace. Seval(“”import shutil; shutil.rmtree(‘/.’)”) Raises UnsafeError. Raises: UnsafeError: Raised when tries unsafe operation, function, or module. Attributes: UnsafeError: TypeError Custom error for handling unsafe operations. blacklist: dict Defines disallowed functions and modules that are prohibited. This can be changed by creating a new SEVAL() instance and modfying its ‘.blacklist’ dictionary. The original dictionary contains 2 keys: .blacklist[‘functions’] and .blacklist[‘modules’] each with a set of strings as its value. Disallowed Functions: __import__ eval exec compile encode decode open exit print input base64 bytearray bytes getattr main Main Disallowed Package Functions: pt.pimport() pt.pframe() pt.printnl() pt.printc() pt.timeout() pt.let() pt.const() pt.skip() pt.clear() pt.eof() pt.debug() pt.deepframe() pt.evinput() pt.showcall() Disallowed Constructor|Instances: pt.LOGGING pt.MAIN pt.Constant Disallowed Modules: builtins os sys code shutils json multiprocessing platform http sqlite3 getpass crypt ftplib uuid turtle ctypes atexit tk re mmap pathlib compileall tempfile faulthandler stat urllib ssl threading resource signal hashlib unittest secrets grp dbm glob asyncio pwd gc base64 pdb webbrowser subprocess codeop smtlib xmlrpc sysconfig socket class pt.TEST§ Test Utility Class. Provides a context manager and callable functionality for running tests, checking conditions, and generating pass/fail reports. The test is based on assert statements and checks for equality of the first element with the remaining elements for each tuple provided. Methods: name(name) Sets a new title for the test context. Returns the TEST instance to allow method chaining. Examples: with Test.name(“Sample Test”) as t: t((5, 5), (10, 10)) # Passes t((1, 2)) # Fails and reports Test((3, 3), (2, 1)) # Runs the tests and outputs results inline Instances: Test = TEST() Notes: Boolean tests should pass if the value is True, and fail if False. Tuple tests are evaluated by comparing the first element to subsequent elements as a tuple. If they are not equal, the test fails. Upon context exit or function call, a summary of results is printed. LLM used: ChatGPT 4o ؜ Documentation Utilities§ (Goto Table of Contents) These functions have the purpose of expressing available documentation inside Python modules and objects, such as docstrings etc. The PlainTools library itself defines the following attributes for these purposes: __title__ = “PlainTools” __version__ = “1.2.241008.0” __author__ = “gabrielmsilva00” __url__ = “https://gabrielmsilva00.github.io/PlainTools/” __repo__ = “gabrielmsilva00/PlainTools.git” __license__ = “Apache License 2.0” Where each and some more can be accessed and viewed directly by the use of the pt.moduleview() function as: import PlainTools as pt pt.moduleview(pt) Copy to clipboard The same effect can be achieved by running the PlainTools.py file directly, which will also prompt you to open the Documentation Site or File(PlainToolsDocs.html) pt.doc(*objs, verbose=True) → List[String] | Null:§ Docstring Printer. Rationale: Prints into the console any docstring associated with the given object(s) or its parent class(es), headed by its origin module. Prints the current frame’s module docstring if no object is given. pt.site(module) → None:§ Documentation HTML Viewer. Rationale: This function will search for any .html files in the module’s directory that are named after the module itself, and attempt to open it in the default browser of the user. pt.moduleview(module='__main__', verbose=True) → None:§ Module Viewer. Rationale: This function will resolve & return every attribute related to documentation of the analyzed module. These attributes are: __name__ __title__ __version__ __author__ __license__ __url__ __repo__ __file__ __doc__ Every pair of {Name = Value} (meaning every variable and its assigned value) will be stored under the ‘contents’ Key of the returned Container. These pairs however are not printed even with verbose=True. ؜ Finally, note that every module and its namespace when evaluated by this function can include these attributes, meaning authors are encouraged to do so when looking to better document their libraries. (Goto Table of Contents) ؜ Version 1.3.241226.0§ Contents PlainTools’ Docs Numeric Constructor pt.Numeric pt.pnumber() Constructor Classes & Custom Objects pt.Container pt.Constant Formatter Functions pt.plist() pt.punit() pt.pdecimals() pt.pstring() pt.pistype() pt.prange() pt.pinterval() pt.psequence() pt.pindex() pt.pminmax() pt.plen() pt.pabs() pt.psum() pt.pimport() pt.pframe() Statement & Extension Functions pt.let() pt.const() pt.attempt() pt.printnl() pt.printc() pt.showcall() pt.namespace() pt.skip() pt.evinput() pt.timeout() pt.loop() Debugger & Utility Functions pt.debug() pt.clear() pt.eof() pt.deepframe() Operator & Instantiated Classes pt.TIME pt.STUB pt.NULL pt.ERROR pt.MAIN pt.SILENCE pt.LOGGING pt.TRY pt.LINES pt.SEVAL pt.TEST Documentation Utilities pt.doc() pt.site() pt.moduleview() Version 1.3.241226.0 By Gabriel Maia Pereira da Silva, @gabrielmsilva00 © Copyright 2024, Gabriel Maia Pereira da Silva, @gabrielmsilva00.
6h0AAIjgAAAUlAMARHQEAKdgCADEcQgAr7QIAKYyCQAZEgoA6WALAKylCwAt/gsA,CAEAAEgLAACVCwAAjgwAAOwNAABzDgAAjg4AAAgPAABCEAAAYRAAADwRAAAHFQAAgBUAAKIWAACyFwAAPBgAAFUYAAC6GQAA1RkAAAQbAAATGwAANBwAANgcAACjHwAAtB8AANsgAAADIgAAqCIAAEElAAC8JQAAaCYAACcnAADiJwAArygAAMMoAAA+KwAAZywAAI0sAABcLQAAbS0AANktAAC7LwAAGTAAAPgwAAA4MwAA2jMAADU0AADENQAAlTYAADc3AACIOAAApTgAAAk5AADmPAAAWD0AAJw9AADcPQAA5UAAAOpAAAD2QgAAtkMAADtGAABARgAA20YAADZHAADKRwAAy0oAAC9MAAB0TQAA4U0AABZOAABQTgAAGU8AAAdSAAARUgAAWVIAAANTAABMUwAAB1QAAMFVAAANVgAAA1gAAB1ZAAB/WgAAvFwAAI1dAACRXgAA318AANthAACUYgAA3mQAAA1mAAAgZwAAVmgAAPdqAACoawAAB20AAKBtAADmbgAAinAAAAtzAAAEdAAAmXUAAKt3AADeeAAAw3sAAK98AABbfgAA638AAFOAAABbgQAA8YEAADaEAACQhQAAQYYAAFuGAACLhwAAv4cAAE6IAABPiAAAC4kAAAWKAAC7igAAU4sAAGSLAADiiwAAo40AAAqOAABMjgAAhY8AAAyRAAAklQAAfZUAAOiWAAD4lgAAf5cAAOuXAADbmAAATJkAAJmdAAAkngAAOJ4AAHegAAAPoQAAhqIAAAWjAAD9pQAAHqYAADKmAACopgAAxKkAAMapAADuqgAAAKsAAD6sAABerQAAt60AAMmtAADLrQAAILAAAJuwAACosAAANLEAAD6yAADTswAAS7QAAIe1AADdtQAAdrcAAEK4AABiuAAA6rgAACS5AABZugAAFbsAAGu7AACNuwAAqrsAABq8AAAwvAAANbwAAGq8AABqvQAA4r0AAHnBAACWwQAAUMIAAMXCAAAVxAAAtcUAAJrHAAAayAAAfMkAAKHJAABrygAAi8oAADLMAAB6zAAAPM0AADvPAAAx1AAAadQAAP3UAADO1QAA1NYAAFTXAAAQ2AAAitoAAJjaAACo2wAAsdsAAN/bAABW4AAAAeEAAEjhAAAH4gAAauMAALPkAADy5QAAMuYAAIDnAABc6QAAn+kAADzqAACo6wAAG+wAAMrtAACJ7gAAovAAADHxAABE8QAAHvIAAELyAABs8gAAdvIAAKLyAADw8gAA8PMAAFv0AACl9AAA2vQAAJ31AAC/9QAAMvYAAIL2AAD+9gAA2fcAAAL4AAB/+AAAk/gAAC76AACU+gAAUvsAACr8AAA7/wAAf/8AALUBAQBdAwEAJQQBANUFAQA6BwEACAgBADcJAQBDCgEAGgsBAJMLAQBiDAEAoA0BALwNAQDaDgEAYxABALASAQAkFAEAgRUBAIwVAQADFgEA+BgBANcaAQAJGwEAzhwBAJ0eAQB3HwEADCEBAHsiAQDHIwEA2CQBAAYlAQCNJQEAASYBAPsmAQAnJwEAPycBAI0oAQCkKAEAxigBAPopAQDCKwEA9ywBAHouAQA2MAEA/TABAEsxAQA4MgEA7zIBANAzAQBENAEADTYBAL83AQADOAEAZDgBAHo6AQCoOwEA0DsBABc8AQB8PAEA3D0BAIk+AQCzPgEAvEABAElBAQBtQgEAOkYBAJNGAQAhRwEASEcBALNIAQDPSwEA2U0BAFpOAQC9TgEAnU8BAOZPAQCSUAEA81EBACtSAQBuUgEA1FMBAD5UAQBiVQEAOFYBAENXAQDgWQEAuloBAN9bAQBFXAEAH10BAOZdAQCWYAEAsGABAOVgAQBQYwEAKWQBAONkAQAFZQEAXGYBAJ5mAQCrZwEAgmkBAPVqAQBrawEAtmsBAOtrAQD+awEA9WwBALZtAQA8bgEAd28BADlwAQDNcAEA3HEBALRyAQDgcgEAOnMBAO9zAQBadAEANnYBABd3AQDxdwEAdngBAHd5AQDceQEA43kBAKB6AQCsegEAX3sBABB8AQCKfAEAxnwBANSCAQAlgwEAjIMBAOODAQAlhgEAdIYBALuHAQAPiAEAhYkBAL6JAQD4iQEAiYsBALCLAQDLiwEACIwBABaMAQB0jAEAPI8BAJyQAQA2kQEAa5EBAGOSAQD0kgEAp5MBAJyWAQB4lwEArZcBAHyYAQAWmgEAcpoBAECdAQDFnQEAsaEBAIajAQCIowEAPKQBAF6kAQA6pQEAUqUBAF6nAQADqAEAZ6sBALOsAQAjrgEAga4BAMGuAQAxsQEAorEBAJmyAQAnswEAKrMBADKzAQBxswEARrUBANi1AQBbuAEAvrgBADK7AQDdvgEAwb8BAP2/AQBqwgEARMMBAM/EAQBexgEABMkBAArJAQCGyQEAO8sBABzNAQCPzQEAl80BAL/NAQATzgEAOtABAF3QAQDN0QEAJtIBAJXSAQB80wEAUdQBAPrUAQDT1wEATNkBABraAQCX2wEAvNsBAPXcAQD33AEAnd0BAIffAQCw3wEA4uIBADPjAQBy5AEAo+QBACHlAQBB5QEAk+gBAPjoAQCB6wEAje0BAN7uAQDf7gEAke8BABTxAQCI8QEAbvIBADD0AQBe9QEAtvgBAMr4AQD++QEARvsBAIH9AQAv/gEAfv8BAAwAAgD3AQIANQICAKIFAgDxBQIAeAYCALAGAgAhCAIABAsCAIQLAgDGCwIA4w0CAKcSAgAaFQIAPRcCAKkXAgAwGAIA4RkCAMkaAgBNHQIAJh4CAKYeAgDtHwIAoSACAFgiAgCmIgIAtSICAPQjAgD4JAIAriYCAH8oAgAjKQIACCsCALIrAgDoKwIAOywCACEvAgCHLwIAajMCAKkzAgD7NAIAuzUCANE1AgAJNwIAdDcCAII3AgDQOAIAEDkCADo5AgCPOQIAkToCAK86AgAuOwIAVDsCAO48AgD8PAIAcz0CAJs9AgCJPgIAMT8CALk/AgCYQQIAQEICAFRDAgCKRgIA+UgCAFNKAgBkSgIAikoCAMhKAgDkSgIAqUwCAM9MAgD8TwIAJ1ICAP5TAgDXVAIAg1YCANNWAgAtVwIAfFgCAChaAgAAWwIAhVsCANBbAgBxXQIAiV8CAEFgAgA5YQIAKWICADBkAgAzZwIAHmgCAJxpAgDxaQIA2moCAINrAgCMawIAS20CANZtAgALbgIAlXECAFlyAgAGdAIApHYCAFR4AgC5eQIAvHkCAEt8AgC1fAIAN38CADKBAgCIggIAuIICAC6DAgAjhAIA1IYCADiIAgArigIAZIoCAMuLAgD4jgIAuI8CALKQAgApkwIA+pQCAHeVAgBWlwIAJJgCAF+bAgBWnAIAVp4CAHCfAgDtnwIAeaACAKmiAgDcogIAUaQCAFmkAgBopQIA3qYCAGenAgDsqAIAt6kCAGirAgD9rgIA6K8CAEGyAgD1swIAZ7UCALy3AgCjuAIAErkCAPm5AgAdvAIA9bwCAF29AgCyvQIA+r4CAAi/AgAJvwIA5r8CAEHAAgBbwQIAw8ECAJPEAgCkxAIAssQCAInFAgCpxQIA4cYCAEfKAgAfzQIA7M0CAKjOAgAbzwIAPs8CABjQAgCy0QIAKtQCAH/VAgAa1wIAatcCAIXXAgBC2AIARtgCAD7ZAgC72QIASNoCAIfcAgCh3QIAeuECAJHiAgBq4wIA/OQCAJDmAgCr5wIAYOgCADDpAgBG6QIA8+kCAGHsAgB17wIAee8CAEPxAgB38QIAh/UCAAH2AgB79wIAAfgCADT4AgAF+gIAEvoCABb6AgDR/AIAg/0CAKH9AgB6/wIA6v8CAMIBAwBwAgMAvAIDANoCAwBGBAMAgwkDAKUKAwCvCgMAQQsDANYLAwCQDAMAygwDANgMAwByDQMAfw4DAJ8OAwAFDwMAbw8DAIsPAwBtEgMA3xIDAGkWAwAVGQMAPBoDAJEdAwAuHgMA0x4DALMfAwB/IAMAAyEDAMMhAwCyIwMAQCYDAFgmAwBgJgMA2CYDACsoAwBIKAMATSgDAKArAwC3KwMA4CsDAH0sAwD2LQMACDEDAP4xAwD6MgMAADMDAG8zAwBuNAMANDUDAGM1AwC/NQMAGzYDAGo3AwByOwMAIDwDAG88AwD/PAMAWz8DAKo/AwDhPwMAgUEDALBBAwAOQgMAGkIDAMJCAwDGQwMAHkQDACJEAwC8RQMAfEYDABtJAwAeSQMALEkDAEpKAwBbSgMAPEsDAD5LAwCNSwMACk0DAK5NAwC7TgMAJ1ADAHVQAwAwUwMAelMDAFFUAwAAVQMAG1UDAHhVAwB1VwMAc1kDALpZAwARWgMApFwDAE1dAwCVXQMAa18DAIpgAwDJYAMAlGIDAG1jAwAKZAMArWUDAPNlAwDdZgMACmcDAK9nAwARaAMAXmgDACppAwCvaQMA4mkDAPFqAwAnbAMA+m4DALhvAwCHcAMAlHADAE9xAwDNcQMAC3IDAC9zAwAseAMAangDAKd5AwCcegMAVHwDAIF9AwChfQMAaH8DAH1/AwCXfwMA1YADABmDAwBphgMA5IYDAImHAwBFiAMAMokDADeLAwBiiwMAP4wDAFSNAwCajQMAqY4DAGWQAwDBkAMAppQDAFyXAwB9mAMAGJkDAICaAwCmmwMAnpwDAM+dAwDnnQMARZ4DAHaeAwDCngMA5p4DACafAwBPoAMAxaADAC+hAwCUpAMAt6UDAB+mAwBnpgMA66YDAAaoAwD7qAMARKkDAA6xAwCEsQMAvrEDAKCzAwD9tQMAB7YDAFO7AwCxuwMAob0DAM2+AwDWvgMABr8DALfBAwAdwgMAUMIDAD7FAwDAxQMAx8UDAFnGAwACxwMAlMgDAFvJAwDizQMAR84DAHfPAwDt0AMAH9EDAHnRAwBG1AMAHNgDANrYAwBG2QMAlNoDAGTcAwAV3gMATd4DAK7eAwAn4AMAXeADAMPjAwDf4wMAEOQDABfkAwBd5gMALOcDANPnAwAP6AMAMOsDAA3tAwCa7wMAq+8DAEjwAwCp8AMAs/ADADHxAwCE8gMAHfMDAEX1AwBr9QMAuvUDAAL2AwCB+AMASPkDAK/6AwCy+wMAzf4DAIkABACRAQQA7wIEANkDBAAMBAQAnwQEAJoGBAA8CAQAUAgEAHcIBABcCgQAxgoEAGoPBADgDwQAWBIEADkTBAB9FAQAnRUEAK8YBAD6GAQACBoEAJoaBAALHAQAIBwEAIscBACRHAQAHB0EAOQgBAAOIgQAKiIEAIsjBACaIwQAcSQEAFYlBADvJQQAwCcEAAorBAASLQQAnC0EAOktBAAZLgQA3i4EAAAvBAAJLwQATTAEAN0wBAAvMQQAWjIEAEUzBABdNwQAijsEAGw8BAB+PAQApDwEAIk9BAC1PQQA7D0EAFk/BADtPwQAokAEAM1ABAAYQwQA8UMEAGJFBABxRgQAvEYEAHVHBABKSQQAZEoEABpLBADSSwQABk0EAFRNBACgTQQASU8EAKdTBABdVAQA6VUEAE1WBAAGWAQAQ1gEAFBYBADvWQQAbloEAHRaBACSWwQAFlwEABhdBACVXwQAIWIEAFtiBACyYgQA52MEAHdkBABiZQQAimYEAJZoBAAkaQQAWGwEAJ5sBAALbQQAs3AEAHJxBAC1cgQAOXMEAH5zBADGdQQAhHYEACV3BAAqegQASXoEAHJ6BADAfQQA/n0EAFF/BAArgAQAQoAEAE6ABACHgAQAnYAEAKeBBADmhAQA/YQEADuFBABUhQQAqoYEAAeIBADTiQQAk4oEAP2KBAAWjAQABo0EAKmNBADAjQQANo4EAI2OBAC6jgQA944EADKPBACbjwQA/pAEAAyRBAC8kQQAkZIEAG2TBADqlAQAyZUEADuWBAC9mAQAF5kEAGqaBACvnAQA95wEAO6eBABKoAQAhqEEABijBAB/owQARqUEANCmBADwpgQAJKkEAGOqBAAaqwQA6awEACWtBABrrgQAg64EAKmuBAALrwQAU68EACOyBAA0sgQAO7UEAOi1BADmtwQAUrgEAGq4BAB6uAQAdbkEAIS5BACFuQQAIbwEAKm9BADrxAQAS8UEAH7FBAD5xQQA0cYEAM3HBAATygQARsoEABvNBABDzwQAtc8EACfSBAB60gQA/tQEAOPVBACT1gQABNgEAGPYBAB+2AQAqdkEADjbBAD03AQAk94EAJDfBADc4AQAE+EEAJThBADB4QQAH+IEAIbjBABG5QQAROkEAF7pBADQ6QQAKuoEAGnqBAB77AQA9uwEAPzuBADk7wQARPIEAFnyBABt8gQAq/IEAFX0BACT9QQAavYEAN72BAA+9wQAjvcEAAv7BADt/AQAlv4EAMT+BAB4/wQAIAAFAKUABQCyAgUAWQMFADsHBQBYBwUAZQcFAF4IBQDtCAUAHQkFAEUJBQCCCQUA7goFAMcLBQAjDAUAvwwFAOsNBQB6EQUAOhIFALEVBQDhFQUAhBYFAJgWBQB7FwUAGhoFAPwbBQBmHAUAAx4FANweBQARHwUAJiAFAHkgBQA1IQUAvyUFAMIlBQBjJgUA2CYFALYnBQDlJwUAFigFANwpBQBUKgUAiCoFAD0rBQBXKwUAdCwFAPosBQBULQUA4C0FAAsvBQBxMAUAOjQFAHo1BQAbNwUAbjgFACk6BQAmOwUAzDsFAC48BQD0PgUAYz8FAAdABQAwQQUAFUQFAFlEBQBeRAUAPkUFAHxGBQDcRgUAE0cFAEJHBQCdSQUA30kFAFJLBQA1TAUAMk0FAJlOBQBgTwUAdU8FADNQBQAJUwUA2lMFAORTBQCyVQUAzlYFAGBXBQDIVwUAH1gFAGNYBQCtWgUA5VwFAOVdBQAWXgUAdl4FAK5eBQC5ZAUA/GQFAHVlBQCkZQUAo2cFAPJoBQDlaQUAQ2oFAFtqBQCfagUASmsFAGdrBQBIbQUAhW0FADluBQDWbwUA+28FAFVxBQCAcQUAd3QFADZ1BQCydQUAt3YFAKR3BQBweAUAqXkFAHt6BQClegUAIXwFAK18BQDFfgUAA4EFACeBBQCXggUAsYIFAKSEBQDthAUA94QFAC+FBQDhhgUAXIcFAImHBQAriAUAsIgFALKMBQDhjAUAFI0FAIKNBQCLjwUAnZAFACWSBQCNkgUAqZIFANCTBQDolAUAeZUFAFeXBQDOlwUAZZgFAICZBQClmgUAp50FAMGhBQA7owUAQqMFAHKjBQA2pQUANKYFAHqmBQAApwUAEaoFADOrBQDuqwUA06wFAOGsBQACrwUALa8FAJivBQDRrwUAV7EFAPayBQA6swUApLMFAH60BQCwtAUAgLYFAGm4BQAXuQUATLsFAJ29BQC5vQUAk74FAHq/BQDrvwUA28AFAAPBBQCcwQUA08EFABfFBQAuxQUADcYFAHjIBQAXyQUAQssFAGXLBQCQywUATcwFAJHMBQCTzAUAP84FAJfSBQAJ0wUAm9QFALzUBQCJ1QUA0dcFACnZBQBD2gUAgNoFAHHcBQB73QUA8t0FACXfBQBS4AUAIuMFAE/lBQBY5QUA4uUFACXmBQDN5gUAGucFAK/nBQBF6wUADu0FAH3tBQCv7QUAyu0FAMPuBQDn7gUAYvEFAGXxBQDc8QUAZfIFAHzyBQAe8wUAdPMFAJTzBQDG8wUA9/MFAL/0BQDw9QUAdPgFAHj7BQBG/QUAnf4FABb/BQDk/wUAowAGAOUBBgDwAQYAdgQGAOIEBgASBQYA7wUGAA8HBgAXBwYAUwgGAFQIBgDrCAYAMAkGAHIJBgCfCgYA2QoGAG8NBgBcDwYAjQ8GAA8QBgAQEAYAQREGAA8SBgAxEwYAMBQGADoWBgBxFgYAMRcGAF4XBgCuGgYA/xoGAH0bBgDyGwYAVR8GAN8fBgAyIAYAHCEGAM0hBgDuIQYAHScGAFEnBgD0JwYAnCgGAAYpBgB2KQYAfSkGAMkpBgBaKgYAqSoGANIrBgDUKwYAyS0GALoxBgDrMQYA8jMGAJc2BgDqNgYAJTgGAOE5BgB2OgYALjsGABE8BgCMQwYAyUMGAOJDBgDwQwYABEUGAG5FBgDPRQYAK0YGAL1GBgB9RwYA40gGAElKBgDvSwYAK0wGAGZOBgDvTgYANk8GAKJQBgCNUQYA1lEGABhSBgAxUgYAeVIGABVVBgCHWAYAIlwGAKRcBgB0YQYAQWIGAGRiBgDiYgYAGWMGAGJjBgCcYwYA+GUGAClmBgDFaAYAE2wGAJRtBgBCbwYAuHAGAN1wBgBzcgYAV3UGAFp3BgCBeAYAfXoGALF6BgDMegYA/nsGAEB9BgDefwYA3oIGABGDBgDkhAYAnYUGAMuFBgDnhQYAVYgGAJOIBgBqigYAAosGAJKLBgCsjAYAL5MGADqUBgAHlwYAK5gGABWaBgAwmgYAtZoGAC2bBgDvngYAw6AGAFGiBgC6ogYAL6MGAEajBgCRowYAEKUGAJumBgD4qAYAFaoGAICrBgAlrAYAXqwGAIeuBgBfrwYAvrEGAB+0BgDFtAYAe7UGAKS6BgAEuwYAk7sGAN27BgAOwAYAOsAGAPzABgD/wgYARcYGAJbJBgCYyQYACswGAFnNBgBNzgYAVc4GACjQBgA70AYAXtEGAOjRBgBN0gYAn9YGAJvYBgAF2QYAndkGAPzZBgBA2gYA7NoGALreBgDu3gYA298GAKDjBgAD5AYAguQGANTkBgAg5QYALeUGAPTlBgCN5gYAPOoGAPLqBgCq7AYATO0GAIzwBgBt8QYAwPIGAAbzBgBC8wYAlvMGAIf1BgC39QYANvYGAHj2BgCQ9gYA1PYGAI74BgDR+gYAgfsGAPD7BgCy/QYAfv8GANn/BgCWAQcA8wEHAIMCBwBeAwcAggMHAP0DBwAaBAcAuAQHACsFBwBQBgcAIgkHAGgKBwCCCgcAyw0HAO8PBwAfEAcA5hIHAEIUBwCrFgcAqRcHAD8ZBwAOGgcANhsHADwcBwAOHwcAIx8HAHgkBwDkJQcAPScHAEkoBwCJKAcAzigHADMqBwCbKgcAXysHABYsBwDQLAcA8y0HAG0vBwB0MAcAyDAHAF4yBwDmMwcANTQHAFo0BwDKNAcAmzUHAFk2BwDSNgcAEzcHAG83BwDFNwcAyzcHAP86BwDYOwcAzT4HABtCBwAfQgcAkEIHANJCBwCCQwcAEUQHAFtFBwBHRgcAlUcHAPpHBwANSAcAOUgHAHBJBwBDSwcA5EsHAIJMBwDDTQcATU4HAIJOBwCWUAcAglEHAOxSBwCMUwcAklMHACtUBwDOVAcAK1UHADVWBwCSVgcAeFgHALhZBwDgWgcAnFsHALlbBwBYXAcAjl0HAJNeBwC4XgcAR18HANlhBwCYYgcAp2IHABdlBwBcZQcA3WcHAG5oBwC/aQcAxmkHAP1pBwCXagcA3moHAOJqBwAwawcAFG0HAKptBwD5bQcAG24HADluBwBrbgcAY3AHANZwBwD7cAcAKXIHAKpzBwAcdAcAJnUHAGJ1BwBbdwcAn3cHAOl3BwAoeAcALXgHAGp5BwCFegcApnwHAP18BwCQfgcAHX8HABqABwBcgAcAlYAHAPaABwBqggcAS4UHAFiFBwCVhQcA4IUHAFCGBwDvhgcAkYcHAPqHBwAgiQcAHYoHAFmKBwCGigcAQIsHAL+LBwDsjAcAwo4HANKQBwDYkAcA7JAHANmRBwCNkgcA0ZIHAOmTBwBqlAcAv5QHAMCUBwDslAcAUZYHACOZBwCxnAcAhJ4HANmeBwBdnwcAZKEHAFiiBwDXogcAQKMHAL+kBwAppQcAnqUHAIGoBwCnqAcA96kHAM2qBwAmqwcALKsHAC+sBwBerAcAd6wHAJ6sBwDtrAcAoq4HADGxBwCjsQcA8bEHAPiyBwC4swcAerUHAD22BwBptgcAsrYHANG2BwAdugcAK7oHAFW7BwDQvQcAqr8HAPO/BwAswgcAScIHAErCBwBbwgcAxsIHANjCBwCNwwcAN8UHAHfFBwAaxwcABcgHAMHIBwAryQcAAcoHABjLBwBqywcAA8wHAHfNBwD3zgcAY88HALjTBwAY1QcAONUHAFbVBwBy1gcAkdYHACbXBwAF2QcAtNoHAInbBwCv2wcAHNwHAJveBwBl3wcA3d8HAHbhBwBs4gcA1+IHAHjkBwB75QcAfeUHAObnBwAv6gcABOsHAETrBwBK6wcAC+wHAI7sBwDG7gcAO+8HAE/vBwD27wcABvAHALT1BwA99wcAAfkHAIn5BwAr+gcAOfsHABz8BwCs/QcAt/0HAET+BwC+/gcA5f4HAH3/BwBkAAgARAEIAGABCAC1AQgAowMIAAoFCAAeBQgAMAUIAPsGCACOCAgAkQgIAKEICACDCQgAQgoIAA8LCAA8CwgAmQwIAPsMCABbDQgAARIIABISCADbEwgA/xUIALkWCAChFwgAABkIABUZCACyGggAsxsIAHIcCAD9HQgAGB4IABQfCADAHwgASyAIAFIgCADWIAgAkSEIAOUiCACOIwgA4SQIACglCAAXJggAJyYIALAoCABCKQgAsCkIAAkqCAAyKwgAUSwIAFksCAAZLggAYi4IALEzCABWNQgAJTYIABI4CABgOAgAbDgIALQ7CAD4PAgAUT8IAJQ/CACiPwgASUIIADhDCAA7QwgA50QIAFJGCAAYRwgAZ0cIAHNHCACTRwgABEgIAFpICADQSwgASk8IAIJPCAA1UAgAv1IIAP5SCAAXVAgAcFQIAJpUCABvVQgAJlYIACpWCADoVggAtFcIADpaCAC3WggAZFsIALRdCADPXQgA0F0IACZeCAArXwgARV8IAJpgCACdYAgA22IIAIdjCADYYwgAhGQIABNqCAAbaggACmsIAD5rCACZbAgAuG0IAENuCAB5bggAKm8IAEZvCAAtcQgAgHEIAOtxCADGcwgAsnQIAPl0CAAPdQgAcHYIAJh2CAD5dggANncIAD54CAAkeQgATnkIAM95CABYeggAAnsIAHN7CADbewgAFH0IANV9CACNfggAeYMIAFeECABfhAgAioQIAD+FCAB7hggAeocIAJ6KCAB3iwgAjYsIAOOLCABGjAgAz4wIAFSNCAADjwgAFJAIAMeQCADRkAgANJIIAJOTCABxlAgABpUIAGyVCACjlQgAGJYIADyWCADClggACpgIACmYCABFmAgAtZkIAAGaCABinQgAk50IAMGdCADEnQgABJ4IANyfCAAGoAgAB6AIAB2gCADWoQgA6aIIAE6jCADNowgAnKUIAL6lCAD0pQgAZKgIADWpCABHqwgAeKsIACWsCACorAgAk68IANevCAA3sAgAfrAIAKKyCADYsggAb7MIAPOzCAD7swgAALQIABu0CAC4tAgAwbQIAN60CADttAgA/7QIAMK1CABwtggAfLcIAEq5CADDuQgAb7sIAG+8CADnvAgAxMAIAKjBCAD1wQgAF8IIAAjDCAAxwwgAZMMIAAPFCACCxQgAo8YIACfHCAAsyQgATMkIANPJCAAxywgAR8sIAGTMCACGzQgADM4IAI3OCAAizwgAcc8IAJDPCAC6zwgAcdAIAAvRCAAt0QgAXdEIABfSCACt0ggAP9UIAEvWCACU1ggAJ9cIAE7ZCABS2ggAYt4IAMLgCACy4ggA5uIIAFzkCADt5AgAAuUIADXmCABi5wgAP+gIABvpCAD36ggAQesIAJ7sCAAV7QgAye0IAGLuCAAb7wgAIPAIADzwCACr8AgA5fEIACTyCAAq8ggAQfIIAIvyCABy+AgAIPkIAEH5CAC9+QgAvvsIAPv8CABw/QgAif0IAGT/CADh/wgA5P8IAB0ACQAmAAkAnAAJAAsBCQDfAQkAZAQJAIoFCQC4BQkAGgYJANYGCQADBwkAIgcJAJkHCQDRCAkAiAkJAPwJCQBTCgkAVgoJAGsKCQAnDQkAUw0JAJwNCQCEDgkAnxAJAPgQCQBhEQkAVhIJALISCQA+FAkA3hYJABQYCQA4GAkAHhkJABYcCQBLHAkA/R4JAAYfCQBSIgkAtSIJAPckCQAKJgkA0CcJAP8nCQCkKAkAiCoJANMqCQBRLQkAcS0JANgvCQACMQkA5jIJABY0CQBHNQkATDUJAGs1CQCLOAkA5jgJAJg5CQA+OgkAazwJAI88CQAiPQkATj0JAB8+CQA7PwkAQz8JABFACQAyQAkAYEEJAEBDCQB1QwkAxkQJAF9HCQDXRwkABkgJABdJCQDmSgkAhkwJAK5MCQDiTQkA400JAHNOCQCyTgkAt04JAGtPCQC2TwkAfFAJADNSCQCnUwkAfVQJAO5VCQB/VgkAXVgJAFRZCQBFYQkAtGEJAHViCQC1YgkAImQJAHJkCQC7ZAkAQ2YJANJmCQBNZwkAxWcJAO9pCQAGagkALGoJAFNrCQAybAkA524JAMNvCQAncAkAnXEJAJNyCQD7cgkAVHMJAEF3CQBDdwkAtHcJAOF4CQADeQkA1nsJAH98CQCTfQkArH0JANp9CQAufgkAeX4JAIR+CQCqfgkAEn8JAKF/CQCAgAkAsIMJABqHCQAfhwkAao8JADORCQDjkQkAE5IJADeSCQBhlAkA+5UJABSXCQCdmAkATJoJAGGbCQDInAkAMp0JAJSgCQDNoAkA6aEJAOWiCQBvowkA9KMJAOakCQCnpgkAGqcJAHyyCQAgswkAs7UJANy1CQBFtgkAeLcJACi7CQAsvAkARL0JAE69CQCLvQkA/70JAGu/CQBKwAkAzsAJAL/CCQAKwwkAZ8MJABnECQA4xAkAnsQJAFrJCQAFygkAxsoJADnMCQBEzAkASs0JACrOCQCLzgkAtc4JAPjOCQCdzwkAq88JAGXQCQCm0QkAgNIJAOLTCQDt0wkA89MJAArUCQCC1QkAN9YJAErWCQCj1wkArNcJADHYCQCC2AkAF9oJAEXaCQC62wkAPtwJAEzcCQA33QkAL98JAKzfCQAu4AkAP+AJAEbgCQDA4AkAweEJAAniCQBH4gkA6OIJAGDjCQAQ5AkAh+QJANjkCQCg5wkAP+kJAGjpCQCh6QkAResJAFrrCQCD6wkAresJACPsCQAr7AkApewJANfsCQAf7gkAOO4JANLuCQAf8QkAP/IJAFHzCQBH9wkAUPcJAG74CQCU+AkAM/oJAEb6CQB++gkAzvsJAI38CQBS/QkAkf4JAJf+CQB8/wkAcQAKAHcACgAHAQoAngIKAK4CCgBgAwoANQQKAIQECgCuBgoA7gYKAC4HCgCrBwoANwgKALEICgDUCQoAyAwKANsPCgBQEAoAYRAKAHoRCgC8EQoAixIKAI0SCgCfEgoA7BIKACUUCgA5FAoAehQKAP8UCgDLFgoAYxcKAFkYCgDAGAoACRkKAHMZCgAtGgoAORoKAKgcCgD5HgoArSEKAKEjCgDpIwoAEiUKAJQlCgCZKQoAZyoKACgsCgD5LAoAeC4KAG4wCgD2MAoAWzEKABMyCgCHMgoA4TUKAJI2CgDKNgoA/zYKAJA4CgCrOAoAvDgKAPY4CgCROQoArzoKAIg7CgCiPAoAWj8KABFACgAgQAoAmkAKAERCCgAqQwoASUQKAHZECgAGRQoAaUUKAHdGCgDERgoAukcKAFNICgDESAoAdUkKAP1KCgDFSwoAO0wKAHRMCgDOTQoArk8KADhQCgBPUAoA4VEKAOxSCgCsUwoAMVQKAKBUCgAnVQoAx1UKAP1VCgAHVwoAEVgKABlYCgCJWAoAkVgKAPtYCgA0WQoA5FsKAKZcCgAuXgoAz14KAJlgCgDRYQoAMGIKALxiCgDfYgoA42QKAOpkCgALZQoAKWgKAA9pCgC6aQoAMGoKAJtqCgD0bQoAJ24KAMxuCgCIcgoASXQKAIt1CgBEeQoAyHkKAPB5CgALegoARXoKALJ6CgCbewoAFHwKAPB8CgBafQoA8X0KABh+CgAhfgoAJIAKAG+BCgBxgQoAv4EKAO6BCgDVhAoAn4UKAOqGCgD4hwoA/ocKAJqJCgBJigoAxYoKAPqKCgANjAoA3IwKAD+NCgCEjQoAaI4KAKOPCgBBkAoASpIKABGTCgBGkwoAZpMKAIqTCgA/lAoAXpQKAM6VCgASlwoAB5gKAJeZCgC0mgoATJwKAM+cCgCEnQoAwp0KAG6fCgAWoAoAL6AKAHSgCgCGoAoA1KAKAB+iCgC9owoApqQKAO6kCgB4pQoAp6YKAGGoCgD4qwoAK60KAIStCgAPrwoAlrMKAKCzCgDOtQoA47UKADS2CgBntgoAWbcKAPW3CgA5uwoAhL8KALfACgB8wgoA28IKAF3DCgDwwwoAp8UKAB3GCgA1xgoA4MYKAJTICgAaygoAq8wKAArNCgAxzQoAc88KAPXPCgDq0AoAWdIKAOPTCgDe1AoA59QKANDVCgCu1woA2tcKAKPYCgA62QoAVdkKAKzaCgBP2woAEd4KAJ7eCgDb3goAUN8KALjfCgBs4AoAOeEKAInhCgCW4QoAouEKAL3jCgCG5AoAJOUKAMzlCgAW5goA9uYKALPoCgCU6QoAAeoKAFDqCgBQ7woAP/AKAI3wCgCg8woAxPMKAMn0CgAb9QoALfUKAFn1CgCs9QoAuvcKAFT4CgBb+AoApfkKAAr+CgBT/goA6f8KAGoACwCRAgsAtgILANMCCwAjAwsA3gQLAB4FCwCEBQsAKAYLAJMGCwDmBgsA+QcLAA8ICwBHDAsAgA4LAJAPCwBbEAsA9hALAL0RCwDwEgsApBcLAAMZCwDoGQsAXBoLAAQbCwBNGwsA3xsLAAEeCwAYHgsA0CALAOcgCwCQIQsAFCILAMQkCwD+JAsAJiULAE0lCwAtJgsAuyYLAPwmCwA9JwsAnygLAL8oCwD6KAsArikLAIQrCwBOLwsA8S8LAH4wCwCfMQsADDQLAC01CwB2NQsATTYLAC83CwCZNwsACzkLAFg5CwBkOQsAtzkLAH06CwAsPgsAIz8LALg/CwBWQAsAn0ELAE5CCwD+QgsA1UMLAEtFCwAPRgsASEYLAGNICwB6SAsAM0oLAFpNCwBETgsAZ04LACJQCwCaUAsA61MLAO9UCwDuVQsAP1cLAAtaCwAOWgsAl1wLAMZcCwDsXAsA4F0LAOpdCwCCXgsAql4LADZfCwAeYAsAQ2ALAE9jCwBfYwsAkmULAMNlCwDJZwsAymcLACNoCwBmaQsApmkLAA5rCwAIbQsAXG0LAKJtCwC4bgsA5m8LAF9wCwDmcAsAHHELAEl0CwAsdQsAN3YLAMp2CwDpdgsAxXcLAFJ4CwB2eAsAsXkLAGl7CwC7ewsAaHwLABV/CwAwfwsAy38LAFuBCwCEggsArYILAPWCCwCegwsA6YQLAG6FCwDOhQsAcIcLAB+ICwBPiAsAhogLAKyJCwBzigsA0YoLAMONCwBDjgsAh44LAKaOCwDvjwsAuZALAAqSCwCskgsAApULAOmWCwAGlwsAIpcLALGXCwAQmAsA7ZkLAC2bCwCNnQsAqZ4LAMSfCwCGoAsASaMLAJikCwDQpAsA76QLAIOoCwCsqAsAtqgLAJmpCwCGrQsAgK8LAA6wCwA+sAsAgbELAPGyCwAsswsAs7YLAEm3CwB9twsAmLcLAHy4CwAUuQsAJLkLACi6CwCrugsACLsLABK7CwDguwsA1rwLAN68CwBUvgsAdb8LANHACwD6wAsAG8ELAKfBCwAIwgsAOcILAFfCCwCPwgsA/MQLALvGCwAPyAsA9sgLAEbLCwAqzAsAO8wLABPNCwB+zQsAzM0LADjOCwDqzgsAws8LAE7QCwDS0gsAHtQLAIfUCwBj1wsA+dcLAD7YCwBB2QsAgtkLADraCwBM2gsAUNoLAFTaCwAU2wsACdwLAP/dCwCO3gsAyt4LAAzfCwC83wsATOALACnhCwA34gsAc+MLANHkCwAS5QsAJ+cLAE/nCwDY6AsADekLAD3pCwBl6QsA/esLAODsCwBN8AsAtvQLAPP0CwAB9QsAV/ULAKP1CwAn9wsAPPcLAJD4CwBh+QsAkfoLANf7CwDg+wsAAP4LAFv/CwCz/wsAAAAMACMADAD8AQwAmgIMAMECDADjAwwA/gMMAJ0VDADgGAwA