From 1454bdcdf72b38f05d94ce7f41150264f20ffee6 Mon Sep 17 00:00:00 2001 From: 332fg-raven <152709000+332fg-raven@users.noreply.github.com> Date: Sat, 13 Jan 2024 11:37:12 -0800 Subject: [PATCH] Added support for a_out_picture action (#351) supports sending picture to all, coalition, country, group and unit. DCS UI issue allows picture to be sent to unit without picture resource, so a dedicated test covers that. --- dcs/action.py | 211 ++++++++++++++++++++++++++- dcs/coalition.py | 11 +- dcs/country.py | 14 ++ dcs/mission.py | 28 +++- dcs/translation.py | 5 + tests/missions/a_out_picture.miz | Bin 0 -> 41139 bytes tests/test_mission.py | 236 +++++++++++++++++++++++++++++++ 7 files changed, 496 insertions(+), 9 deletions(-) create mode 100644 tests/missions/a_out_picture.miz diff --git a/dcs/action.py b/dcs/action.py index 337096ad..fadeb2c4 100644 --- a/dcs/action.py +++ b/dcs/action.py @@ -1,7 +1,15 @@ -from typing import Any, Dict, List, Type, Optional +from __future__ import annotations + +from typing import Any, Dict, List, Type, Optional, TYPE_CHECKING from dcs.lua.serialize import dumps from dcs.translation import String, ResourceKey from enum import Enum, IntEnum +import dcs.countries as countries + +if TYPE_CHECKING: + from .mission import Mission + from .country import Country + from .unitgroup import Group class Action: @@ -1787,6 +1795,200 @@ def dict(self): return d +class PictureAction(Action): + + class HorzAlignment(Enum): + Left = "0" + Center = "1" + Right = "2" + + def __eq__(self, other: Any) -> bool: + if isinstance(other, str): + return self.value == other + return self == other + + class VertAlignment(Enum): + Top = "0" + Center = "1" + Bottom = "2" + + def __eq__(self, other: Any) -> bool: + if isinstance(other, str): + return self.value == other + return self == other + + class SizeUnits(Enum): + OriginalSize = "0" + WindowSize = "1" + + def __eq__(self, other: Any) -> bool: + if isinstance(other, str): + return self.value == other + return self == other + + def __init__(self, predicate: str, file_res_key: ResourceKey, seconds: int, + clearview: bool, start_delay: int, + horz_alignment: HorzAlignment, vert_alignment: VertAlignment, + size: int, size_units: SizeUnits) -> None: + super().__init__(predicate) + self.file_res_key = file_res_key + self.seconds = seconds + self.clearview = clearview + self.start_delay = start_delay + self.horz_alignment = horz_alignment + self.vert_alignment = vert_alignment + self.size_units = size_units + self.size = size + if size not in range(1, 101): + raise ValueError + + def dict(self) -> Dict[str, Any]: + d = super().dict() + d["file"] = self.file_res_key.key + d["seconds"] = self.seconds + d["clearview"] = self.clearview + d["start_delay"] = self.start_delay + d["horzAlignment"] = self.horz_alignment + d["vertAlignment"] = self.vert_alignment + d["size_units"] = self.size_units + d["size"] = self.size + return d + + def __eq__(self, other: Any) -> bool: + if isinstance(other, self.__class__): + return self.__dict__ == other.__dict__ + return False + + +class PictureToAll(PictureAction): + predicate = "a_out_picture" + + def __init__(self, file_res_key: ResourceKey, seconds: int, + clearview: bool, start_delay: int, + horz_alignment: PictureAction.HorzAlignment, vert_alignment: PictureAction.VertAlignment, + size: int, size_units: PictureAction.SizeUnits) -> None: + super().__init__(predicate=self.predicate, file_res_key=file_res_key, + seconds=seconds, clearview=clearview, + start_delay=start_delay, horz_alignment=horz_alignment, + vert_alignment=vert_alignment, size=size, size_units=size_units) + self.params = [self.file_res_key, seconds, clearview, start_delay, + horz_alignment, vert_alignment, size, size_units] + + @classmethod + def create_from_dict(cls, d: Dict[str, Any], mission: Mission) -> PictureToAll: + return cls(ResourceKey(d["file"]), d["seconds"], d["clearview"], d["start_delay"], + d["horzAlignment"], d["vertAlignment"], d["size"], d["size_units"]) + + +class PictureToCoalition(PictureAction): + predicate = "a_out_picture_s" + + def __init__(self, coalition: Coalition, file_res_key: ResourceKey, seconds: int, + clearview: bool, start_delay: int, + horz_alignment: PictureAction.HorzAlignment, vert_alignment: PictureAction.VertAlignment, + size: int, size_units: PictureAction.SizeUnits) -> None: + super().__init__(predicate=self.predicate, file_res_key=file_res_key, + seconds=seconds, clearview=clearview, + start_delay=start_delay, horz_alignment=horz_alignment, + vert_alignment=vert_alignment, size=size, size_units=size_units) + self.coalition = coalition + self.params = [self.coalition, self.file_res_key, seconds, clearview, + start_delay, horz_alignment, vert_alignment, size, size_units] + + @classmethod + def create_from_dict(cls, d: Dict[str, Any], mission: Mission) -> PictureToCoalition: + return cls(d["coalitionlist"], ResourceKey(d["file"]), d["seconds"], d["clearview"], d["start_delay"], + d["horzAlignment"], d["vertAlignment"], d["size"], d["size_units"]) + + def dict(self) -> Dict[str, Any]: + d = super().dict() + d["coalitionlist"] = self.coalition + return d + + +class PictureToCountry(PictureAction): + predicate = "a_out_picture_c" + + def __init__(self, country: Country, file_res_key: ResourceKey, seconds: int, + clearview: bool, start_delay: int, + horz_alignment: PictureAction.HorzAlignment, vert_alignment: PictureAction.VertAlignment, + size: int, size_units: PictureAction.SizeUnits) -> None: + super().__init__(predicate=self.predicate, file_res_key=file_res_key, + seconds=seconds, clearview=clearview, + start_delay=start_delay, horz_alignment=horz_alignment, + vert_alignment=vert_alignment, size=size, size_units=size_units) + self.country = country + self.params = [self.country.id, self.file_res_key, seconds, clearview, + start_delay, horz_alignment, vert_alignment, size, size_units] + + @classmethod + def create_from_dict(cls, d: Dict[str, Any], mission: Mission) -> PictureToCountry: + return cls(countries.get_by_id(d["countrylist"]), ResourceKey(d["file"]), + d["seconds"], d["clearview"], d["start_delay"], + d["horzAlignment"], d["vertAlignment"], d["size"], d["size_units"]) + + def dict(self) -> Dict[str, Any]: + d = super().dict() + d["countrylist"] = self.country.id + return d + + +class PictureToGroup(PictureAction): + predicate = "a_out_picture_g" + + def __init__(self, group: Group, file_res_key: ResourceKey, seconds: int, + clearview: bool, start_delay: int, + horz_alignment: PictureAction.HorzAlignment, vert_alignment: PictureAction.VertAlignment, + size: int, size_units: PictureAction.SizeUnits) -> None: + super().__init__(predicate=self.predicate, file_res_key=file_res_key, + seconds=seconds, clearview=clearview, + start_delay=start_delay, horz_alignment=horz_alignment, + vert_alignment=vert_alignment, size=size, size_units=size_units) + self.group = group + self.params = [self.group.id, self.file_res_key, seconds, clearview, + start_delay, horz_alignment, vert_alignment, size, size_units] + + @classmethod + def create_from_dict(cls, d: Dict[str, Any], mission: Mission) -> PictureToGroup: + group = mission.find_group_by_id(d["group"]) + if group is None: + raise RuntimeError("Group id {} found in PictureToGroup action, " + "but it does not exist in the mission.".format(d["group"])) + return cls(group, ResourceKey(d["file"]), d["seconds"], d["clearview"], d["start_delay"], + d["horzAlignment"], d["vertAlignment"], d["size"], d["size_units"]) + + def dict(self) -> Dict[str, Any]: + d = super().dict() + d["group"] = self.group.id + return d + + +class PictureToUnit(PictureAction): + predicate = "a_out_picture_u" + + def __init__(self, unit_id: int, file_res_key: ResourceKey, seconds: int, + clearview: bool, start_delay: int, + horz_alignment: PictureAction.HorzAlignment, vert_alignment: PictureAction.VertAlignment, + size: int, size_units: PictureAction.SizeUnits) -> None: + super().__init__(predicate=self.predicate, file_res_key=file_res_key, + seconds=seconds, clearview=clearview, + start_delay=start_delay, horz_alignment=horz_alignment, + vert_alignment=vert_alignment, size=size, size_units=size_units) + self.unit_id = unit_id + self.params = [self.unit_id, self.file_res_key, seconds, clearview, + start_delay, horz_alignment, vert_alignment, size, size_units] + + @classmethod + def create_from_dict(cls, d: Dict[str, Any], mission: Mission) -> PictureToUnit: + return cls(d["unit"], ResourceKey(d["file"]), d["seconds"], d["clearview"], d["start_delay"], + d["horzAlignment"], d["vertAlignment"], d["size"], d["size_units"]) + + def dict(self) -> Dict[str, Any]: + d = super().dict() + d["unit"] = self.unit_id + return d + + actions_map: Dict[str, Type[Action]] = { "a_activate_group": ActivateGroup, "a_add_radio_item": AddRadioItem, @@ -1865,5 +2067,10 @@ def dict(self): "a_set_ai_task": AITaskSet, "a_remove_scene_objects": RemoveSceneObjects, "a_scenery_destruction_zone": SceneryDestructionZone, - "a_zone_increment_resize": ZoneIncrementResize + "a_zone_increment_resize": ZoneIncrementResize, + "a_out_picture": PictureToAll, + "a_out_picture_s": PictureToCoalition, + "a_out_picture_c": PictureToCountry, + "a_out_picture_g": PictureToGroup, + "a_out_picture_u": PictureToUnit, } diff --git a/dcs/coalition.py b/dcs/coalition.py index a48dd6d3..e95dc2bc 100644 --- a/dcs/coalition.py +++ b/dcs/coalition.py @@ -1,5 +1,5 @@ import sys -from typing import Dict, Union, List, TYPE_CHECKING +from typing import Dict, Union, List, TYPE_CHECKING, Optional import dcs.countries as countries from dcs.mapping import Point import dcs.unitgroup as unitgroup @@ -11,6 +11,7 @@ from dcs.point import MovingPoint, StaticPoint from dcs.country import Country from dcs.status_message import StatusMessage, MessageType, MessageSeverity +from dcs.unitgroup import Group if TYPE_CHECKING: from . import Mission @@ -298,6 +299,14 @@ def find_group(self, group_name, search="exact"): return None + def find_group_by_id(self, group_id: int) -> Optional[Group]: + for c in self.countries: + g = self.countries[c].find_group_by_id(group_id) + if g is not None: + return g + + return None + def dict(self): d = {"name": self.name} if self.bullseye: diff --git a/dcs/country.py b/dcs/country.py index 8b014d59..ea89e86e 100644 --- a/dcs/country.py +++ b/dcs/country.py @@ -6,6 +6,7 @@ from dcs.helicopters import HelicopterType from dcs.planes import PlaneType from dcs.unitgroup import VehicleGroup, ShipGroup, PlaneGroup, StaticGroup, HelicopterGroup, FlyingGroup, Group +from typing import List, Dict, Optional, Set, Type, Sequence def find_exact(group_name, find_name): @@ -83,6 +84,19 @@ def find_group(self, group_name, search="exact"): return group return None + def find_group_by_id(self, group_id: int) -> Optional[Group]: + groups: List[Sequence[Group]] = [self.vehicle_group, + self.ship_group, + self.plane_group, + self.helicopter_group, + self.static_group] + for search_group in groups: + for group in search_group: + if group.id == group_id: + return group + + return None + def find_vehicle_group(self, name: str, search="exact"): for group in self.vehicle_group: if find_map[search](group.name, name): diff --git a/dcs/mission.py b/dcs/mission.py index 48cb8f69..20ec78fa 100644 --- a/dcs/mission.py +++ b/dcs/mission.py @@ -43,6 +43,7 @@ from dcs.helicopters import HelicopterType from dcs.planes import PlaneType from dcs.status_message import StatusMessage, MessageType, MessageSeverity +from dcs.unitgroup import Group class StartType(Enum): @@ -348,6 +349,12 @@ def loaddict(fname: str, mizfile: zipfile.ZipFile, reserved_files: List[str]) -> self.init_script_file = imp_mission.get("initScriptFile") self.init_script = imp_mission.get("initScript") + # import coalition with countries and units + for col_name in ["blue", "red", "neutrals"]: + if col_name in imp_mission["coalition"]: + self.coalition[col_name] = Coalition(col_name, imp_mission["coalition"][col_name]["bullseye"]) + status += self.coalition[col_name].load_from_dict(self, imp_mission["coalition"][col_name]) + # triggers self.bypassed_triggers = None self.bypassed_trigrules = None @@ -378,12 +385,6 @@ def loaddict(fname: str, mizfile: zipfile.ZipFile, reserved_files: List[str]) -> self.weather = weather.Weather(self.terrain) self.weather.load_from_dict(imp_weather) - # import coalition with countries and units - for col_name in ["blue", "red", "neutrals"]: - if col_name in imp_mission["coalition"]: - self.coalition[col_name] = Coalition(col_name, imp_mission["coalition"][col_name]["bullseye"]) - status += self.coalition[col_name].load_from_dict(self, imp_mission["coalition"][col_name]) - return status def sortie_text(self) -> str: @@ -1883,6 +1884,21 @@ def find_group(self, group_name, search="exact") -> Optional[unitgroup.Group]: return g return None + def find_group_by_id(self, group_id: int) -> Optional[Group]: + """Searches a group with the given groupId + + Args: + group_id: group identifier assigned by the mission file + + Returns: + Group: the group found, otherwise None + """ + for k in self.coalition: + g = self.coalition[k].find_group_by_id(group_id) + if g is not None: + return g + return None + def is_red(self, country: Country) -> bool: """Checks if the given country object is part o the red coalition. diff --git a/dcs/translation.py b/dcs/translation.py index fb028876..85dc2d7c 100644 --- a/dcs/translation.py +++ b/dcs/translation.py @@ -34,6 +34,11 @@ def key(self) -> str: def __str__(self): return self.res_key + def __eq__(self, other): + if isinstance(other, ResourceKey): + return self.__dict__ == other.__dict__ + return False + class Translation: def __init__(self, _mission): diff --git a/tests/missions/a_out_picture.miz b/tests/missions/a_out_picture.miz new file mode 100644 index 0000000000000000000000000000000000000000..ea0f89b4ba4c925de8782aba0c6822e4c7b00072 GIT binary patch literal 41139 zcmY(qW0)je(>2<*ZBE;^rfu7{ZQHgr?Vk3uZQHhOe09Ii`E!0$UX`(T?HySe85ObC zDg|j!FffxZ6KgcRB#|jfW_9*+1b+G?y5`Mxmc=&?o+R)s9(N| zv{Lm|d~qP^`_$(>3SkJ29Z-7lTBmfpB&1KAnB>FSgP4PwwYtG`M@jiWj(JYWub?n)9ve zymaTW*72Xi;N4d34x|<-HOcx>{!(E-%pJ@b@sGKlso38dRK8eoVn%L}8~f>#4EGc* z9sz{GJz;aaOwO>+)BNZH^82TGKN`-F${08M`gvd$PdNqUk5~Bzw}dZ-PUt22xwy6J zGk3groj&mT-**BOXFu{kflZgTb8kO6pDX3@Thrz7?tMo1e($S4k9YoZ+&|6@U-@?B z%AX%S-yM(87P;NHdU&s@;lAtU?+XpB*T?zGWc)P~e(RrvTfzcm8%KU}@n3idRo;;^ zXZYjc4_q^<`N~h-xi~l4!#fu$zH;{Yx$ltv)0ru`{QSq}&-Sl{ukZryXCOZU6Bc(n z6#4vkp9MdjDBp1Dk+*$?+XfFt`!^>u7bZ_0yF2!JpM_S*d;BePx|z3js51Ju@jvew zyde|!G%yWsb;@8yjSAUn@4=!DJ%q|A0^$2FliT|P-&c7P><9}>jh~R;AwMVw#{^)w zq~4N96f^Ql`jgN0e{RIDyQKX4Hm)9QJ69K?DNNDme)D+1UGc?{f86i;ULPzy+^fld z4SF>15~9fWd3{-<@2L5MQc&Gn{DnHeWYy>6hnU!4Oyg7Vyb<)3YSJm!zv0y!>*jh3 zU-Yi+t{ZqQXWiV&pF`-S{ze~cmALa=6Tqay-p?l1{iAxeKR4^1`m@LEBe(C8UAmCN6fF?P;*=7d3wo1BV`EU?e%FFl%9s_L&EhMs&!H2kKT$+(x zC7)dy7FfW98{BZqRi;lT6nh8CSdgojV+1@`zVR424C!m26LwDBqHi;IFDIgHInHh|BTKd}n4ztHDhh_(0_Ovvcy`6EC^r0{ z0uM$RhuTT{V@6M%Gr4HAPI=hg_{ZRf-1%ld*SWKGZv@rRq8`KDLMhz?pH!N)FFwe) z)Sb@89ZDRI8R3tRL;V7O)tR1c0Pavu`C`?*QS|SiNWa<}eK}nty@lHti^+c?=7f6` z?wIskzI<#k^tj6LbTMF>A3;6rRPAGYl=}N^pZ&PGz5iR`x=Qa~c+>Ws(0iWQ7X8`3 zY?W)>xbVBy^VuV4!~TPq4Qo(ez!3102wi2SKA@NW9^|drmh){Xpgq5cDF5Ip_w`8Y zt^MA7vL-)Mk*{Y$xLoe{j{Wl(^S+mUS^9|U!lN=N@M9@fBi$p~Dt=S_7SH0eMeubH zvrYAI9p`R1Vi2W0>xF5kqPlt0#7s@@*-X_-#3TyU?e2lw_>+Pl2Ah zGxYx7j5cK#zkO*={+-(RiSxD;m%vd?$~HE@^5Q9d6x5@_pYOCXo{r#Oin&B z_OLQOWPYvn=F_K3`$g~mH^==gx^zUB?u+03Uygg*MX5CDnJMi@Q?vKmio`}q`rpfi z=WA2inGAJvT850&?7y7`dbxjji|JNpH1g)!KCmZPa3lqcJ;fHzPO@`gocu$& z&g+;`B4J3sS;+UyHor;f@YHjNU!%8wxXiz2pZNv{yzxJ_&BNc`_FO-?&fQ|z?0R?% z>Tu7?_fMMMNaTmdmAxJ4K{5OV{Db1!Do2XG;(FBIdrc45Nu3+FDL}6`0MZf-u8a*r ztREuR3KpT>c6L;9jvuvCoEPyW821(M#PmjgEVMl!>GdGRpu(_cxEG4)Xt7rZ3If}K zSgb%BoPTPG&h)RMOVRuuG4o|})2}t{bqvr(Zo$Q|Qim z^=fr8ehm}jWv}SZZu0I6j{%E34|3PJB{D77j?`254GEt7zCg|Q15AH-Pak{SeJ4~) zw&=+MuzzyN#`3$#%?KexVE5d~jW19XXIreA-e~N$s_{&ZhVFwL!dvvo5iepY15Ezj z?u=B={x6$xxuGaj-hij=m)@t6=V8(6cFLg(S8m8^COtmo?;5}}%&fKTpJODPN{ohRXS+5J5s4{xZGA_gw$$f*K(W)%WSuH}%awA8q@HDk6B~N!#~qzQfCzu&Vxn^`*~*gz{&7 ze2CZT=7rQJk;?!|7Yd0C)Q3P`|E`pAuq3g zqf?@F?5p*q$8zEqo-1X?(KD_~9?t7|7KeAEi?fYDu&hMIOGRJn*04zXRHyXV@!LjdV zC+<$?0i_1{@jd(J1v>t1Bl*q~g8KEo{b{NKDx_A=#y?KJJb|e^fpWI#{KkW~2fLG* zwYyKQJb^kl&p$s<5kUgxBk-MT@SoMg5Pp7}y*sv`0s?ls0NWmX=Us{O1Cc)4(Kwfb z*Vf9v*c@8*iQ67|9KK)b{GT@r!C9EdF%Dwg|6qcyI!;o-l21fY45xzP-RmB?JazjF zLR$}qcRn9e&uPcg>yk6wmR@pM~vwk?8YOaYkMjc_wi9v3_FbKN!sz zycOTIekb9YyDUB8o?Nk0tgG06=01$5Zk&#?et*A#@@O9qaS3p6lgRqZe0N%9Ex+=d zAXc6DJvK=m*yjoSNnY`M_|$CHJDGYASB>8H#M>kzd?Jb~R$m>vH(NpF^NU-qyL)~k z<$+s~?DX=CeW3Pt5_fbV{54hg(HZ+9qCX@saLBgZ^J4YndNgyE-V(X;7PBwu_x+7E zICqa8<0@9Yq(gIy-qPL~`!1qQj?BI=GG^^7cNbz^_X7RaSQD#%gL*%*;f;>q!l1P# zEFji^6Kj&Y5@Di?N2+;)G1ks0))1Fi9e*V)>cdq=lC{;#u(&PpH~fXI&9OkD75|!B zp`B{Hpdm(c0vUSLs!R!JSs=RheisY<+11x8XND{U6kP!Soa{4Il$A~f_OTg z0&(ujwk^e4)_;1vBg;nirdv$D-DtyOO6*2J9%D|PcBPZ6#XOJweO2IQq?J&7yFC7@ zG5T=tz~a-!}v( zQGLZ6RaxWAc39pOHkkK0X9x(C>(l#nB=E;yV+i3@=1%q<99Xsfbus<%`9|8@s_?!4 za_$~-H)a1lTuhCTG`Q~#6}+(sp5*U#(r5HH?mE4$-KK+DUs(REV}oya_?{jHvvsSs zT6{JA(?Cn#%32Y8rj+KY0gb;ud}YIQ$z6TB)+-?kF|RiPCHv-AJc6^>LNX>Ii_n;u z{X0=<2@fwagU+;m6smW;Y)SWD(Djyh5Cxx0ao|5*1f5a-j%Wez9%upFFoIn|CNGpg zWFsGxK&lsAaUcrzkXA2Ec;E$K+Xsq3Qg_h;$JE(TfzEQQ|&*!;eg((8W48*}U1-h698??+mn-L>^% z=H^M>yT|w1rN>9^2k=#Ru>k+M{=aJ&;+GZ#D`>Al4p7>LxUdhzt4R9a0Kji6qcsBX z0vs3ja~MI%n}+ia8hdqc2B0OLWR!r)Q<#$Oib+#6ALU1kdZ;vBfhMQFvlk9eIY+7P z3`Kgkd>!xpt82sv6$@3L8Rhm@b({ugr{szsF7%C z-^x#MhlGAeHOe+2@`R^H8X5OM>pqCtJ%)C|awkFIkzmIHA{FKrVRJf%(RM4b7Bral z8yicSt}rS$?~t2xaZ2Vsm$+nEXNu=CXSJ34l0S8c+#6eL${Zh^Kb{Zy4B~G!WyYsJ zH{MXX0>Q9YF!<+x0I#nMelc2_^CTXr45=d#!)?INAvMS3x{}{{_bX4f?Lzq*JEXJFl)m_!Kk$i4-)6!DKXKnP;`!!*JjLdPd zSjpL_=#w~Lkq2m;6~0+q)O-s4^GXP|y&hbjyt4Dj0f}CKVf1jv?x7$@r#(9Fo#%VP zLhWtG#{g5MO(u%R0_KcAM!=1M`|Dct=i!WNVT9mYM!zd!8Tv&oL_4uxyOS3-`_~%} z_k`zYCo7^-wSFO)AO5uZ#D=Tmb_Dkpq1xTfI>}bN8^kHp#{SCO4)OYyDYc%YCXwKo zFC1T~^#K<`s6VTIh|nhsjQ>@KjxE9Ah68e^%D;lM1zb89IJ>rCSQZ9bp_AWeXTN1j zXi50zUarA|+-kk_scf^S3-!&_&n`r)MK7SH=!W|=YxXgtyWeN_!Q0l>-Dcd#uNAHP zu5Iy=n?gRzp@XUFz?;Q!r)X@l@j108+%9Od1_;3BKu)FT>h+TK1CC7E(`95a)1qN<(yN0dsz94zO zDW0B@Gllb#=a6IQe9DEt@w;_IISMGgd|q(8h|u!vrx}3)NBs}J+cQS&oNt1+H_-_! z&!YvrTVub9?z6hOwtfF}qRwhAZq>B4QOx8Ya1Q-6C-`t}LFJZ`Ll=p@>)tWUQp8yj ztK(*6-L#Fe*vvRqm7Wn0cW0GWaMTGcd2^Q^d#5C3T1*p?*k=9}-%4>&$}*dhwg^BiKAOUdH_Mt|A%jp0$@3ob5E>&K(cz*jg+Z!EK!u$YK<}Wqr$;;$|jb{mR_+q*zNXueXQYFH9iHh zGCAFp8d-cY>4-R*>x%>F6_JJdRxK5vd_&JcY8{*^S%LMMUUc%hpw2edXFI!sv5@N= zl>s!i<<#egfXd&g9Mi=F)*+-0r0!EsS2S;o@;fT+WfwIHOk&7~L^3(~kkD00W~1*q|M}@FMm6vZeoD<0dp$sSC6nE#du7{I#9*m< zpj39%Y?o6ntx5jNGU1sLIHg4>li+HqbXu>Q?O#Q3jxNc(^T)VD;IYE9q1wYmWsD#e zt+Xzr;wK-1UxxQah`%@LxSJ9xN(GbE^3vU}m$h62s zbIxkW|C={wet0*D>`UM0qFt!A*q_Y@%+1ijVEm&KuX3?LB3%|%$<3!kN;+7$%>_6E zuG46ZXrigd><890He!xi2R>wwtFZD6O|wEfquVPY$HFkQ4{=tAhCuJ=7CoKU^Ktb6 z;okhZw+VigpAqrT=iWf6^eU;wFU5Nw+@d#OB)UDlG(hOr^pQzp9qb*k>lKbXx)a$7 z_9mCfDUmi>m+@QoArAyn@T+)Wx=yLN7PGgh)A@n z1gGmkHr7wjRxyES1&9Z#{OK;XoCh}-=Be6#5^R;aORP*y{~O|ItCZ~6x+6NhSf6Ou z{tjpH<%F*H8uVWv}XpX#R5USi*pN16et z5GS+!GY-w9&P{@ny$uNJGY<>&Iv1UN7jDLhNZ0luXHcTdap1@0OqD#@QKwMr^o?fr zAk9`H5gPqoBJyco*DRjCA(NKiT0H3oZ6q0FVl|)l5QqY2{Om=WmdA#x_Uuy2J&L(! z67>n6OAe^6$iMz`z_wjo1xwF0QY^C*c4a4_f0vJt;LVnSzMW7>)U?fvKvS;El?T{d z3RdRvviohDh(yUzYIGfRCeUzPrkH;i4O#*t=f)|}h6YQsm~XGTOJ%XKAJr|!M`eGv zSj&r_*(cb`l)bVYgK-tleY|D+aN3{R!dwbn3#ccUBD$R(z7){poeGf`vdl#(HIJ!0 z7;s>!?5Qpwq9jrr@MrPN%3yk?$6eTy2wNDy8-)3USR57e8SNi_2|s*I+A-eXXuI6M zMBy`WdtK^bOtm*!ZdZPEuxAP)kVFGj4JCy>Li3nXD7iH<{5Dd+g>Mrqz3MNQwrl3z zdyy$i<6{0>nSE9=%{bZB0#pBKrY)JT{8~V92hzb-P=((@lq!wq#v1xmS+yG|pZ?B!wGLCLy|WOYCeG7~6<`n?hoRYh|*2>5W%2Cycc7y)GjJnl3;ioFZSM zh&DD_m}mzzBpFDv7jxv>6k-Vutn#K&7|=jO9KvANhJx!uZvoq+hGQY_?yprG`W91$ zioJ>S;PK(yivvt6^_GArt&+ly*EX$An#|JoQ->cZjBxB#A)JQ{6)elTkeAgBy1>fg zGA~9Hk$BX&VfEWKQD;9$Im5JxR_4t~3t{PN!@4{c*QWfAE-n9Fham_|bix!$&mcQq zW!v%ul{}fL?CABh%2E^JGEA3V;Y|lNonBWi^Lx_)pND~LG6keST^R zx8lfV=HAjvfIV>e`5|$91n4#7-xfY))Bz*zT2_#_K;QVg3Tf>eXg^zTw;WGfo;~=c znb(zuzJ@y<>Fnay6}IQpb_3_s*Fxvi-;>P?6sWTJEDM$Ym?1stAtrtDk*a+Ph|v&YaDUTYvd?3u&P0E(+^ZAHgb}&Ba`l%E zhS^#NT*PRk%nx#jj5V5Ff)Zr63sd+9T}C8o_R3g~2(RUNmTC^6N%X3>S`FTN_E~`{ z;2IsbntBVjdzyWKFG7mOs974LAu*(4u4VBIa$g#-=%a~*&KEI@u8Zb+fX;fE!bz}k zG>J6+K5ttHTqvLkd5Q}fN%0Linxn%xQ3?EKmgw>%Sgu5TD)Ex=?Euqr>cAWa^{ere0lyMX!q&l+S%Pf}|YfujRPFF`qUz@WBw_Hqu)37*Y^{&E$MN>$IEy$UdJ)GK)-T;;CYLz0%F#6`gW0I-+ zsmMLdfpumkxY3PXz1e%<$u2XZl_?UBAU$a*;}m^1R!KR~U4!HGX*jo!9f)G5hn=*; z!YszOeamu6xWFz=Rjhf+!|H8&4)&}v^Sa}0q`Ewu>(RbQ^9=R0uRllTZ`T|mt_fJ- z0*NO)3l)`fdQ>txAkW=_`wg*RQ?c{}8*53|Vkp)%&%-E|R%z_3T!GpSQpt^PEGY2a zIs6{@MO7viG0HbUr*ch*jqA$FreIc%9vpf0ha41(To(bl6s&TkWCICg#z}qcP$PVx zU36*46CTjuBrIv_SIG?OzFL}r;!8I7m66<}BvW57o9o^Dz)Nu;{0YzwhaR*5#?dTjrIkUht%X0Bzwc#jg5Krglz zI8#4;!fY%fC>`Z&k7+=1NyddM8O2hhGZq+Fb4iRnZ%F9)I>g%{+f5^eD>vB&6OPeT zjltiDcmMoCEO*j$jikLgMPbU&lMYHY8nueE3xz&qlISkeciVNhi>R-R71&RtXDFr_ zd4_u#Z?YW#-yoP8sAw?IXh@kHv`EU`k%PUzMt4XJp%7VwhTRGWP80Zo<~jg`dJDL4 zlJfKpxbD=BD#P(j+S&7L@7oPvBN52D-gqFDJrIKGJWARfyy=x5XUs{aamJn$ zf{drM!=EIkcZ^M^t@c)(*8Mcx=^MesZE14QNta!o3XXuI2$p8{({Uo5rl_uGo&8Q& zuU0b5M>|x^NBWC|Qq}HIrI4{H z#wt7Ui<7p9h~G5}Mf$kvF{$v4A9ZFzs`nft zX<-sdbB-;mT_Nw<6Ly%8C*&H$(sA8-SgyFp0w#B)?x}@i26u*AZ28 z;dkx-%|x#w+*5Sq3!9P@Vo+K`S|-aK677&TSXF*9Lea)_j%d#S7i`y!sn+o}`y1m?b8? zf@SvYS=#crg814kO-=;_FGe7&iec>S>AgysdWCRSH&#pkBScAi`(qmUKTESIbWLz) zraEY=NG!sNPqA@|&T`;&Hu5<8g2FRdx~np_uNkyUvGsgQ<=dj9vaKj`G6J76tYHzM%-@|tZaZw}zHZoyK6YyI`e5E>F$`)1f>WJc>~SIK@n-~ecaceO z{&?k!MA93^FX=P95M%iL^Vb8@cmuy|j*nMaCjseiDlpFbWtEy$jMb2pVjK!R4$j-Q zGxJaERjc_ft8n@DwxBZQ&VhrLM zbYN8q&9~W#wX@+To+y~&C2vBJ;m-?a8>CoR26DOGu4}}THoJcavrR%vf5is zT2^1GrD(qu=D0`F*<4j4N;<&tRqwm%-0{wK?DjN4u)cClm1RN)w{gfLaSmwv*msj^ zvaop^&06AJ(RhpTS&SunpUj8TP9K~whxo8>iKj#>^SUTe%hKeQr8046n;e(;R@nwf zRJCaF`VTEyubS&m^9M{97$G|y6UXB{4^YdpJzF&UcGz}}>8N)ro3Ek%pkjDMVN`*E z&t2gF*M6EPN^JxSr<@JXZ9=;_*+S}ar5zvK9`@cb0COBhAkjP@Lct4WSQW+E4!9#t zGDqWcTcRQjW~2&fi4257oE?C5X-davI=ZT01;$JR#7kbkC863`BKs)`gGwb~N?SJ$ z=I1S}rR-sIHSv5h&qn8OJ)$+GONvDUmWwFmhH*17deo<}*D)41lp*A=a+}4?w?>BY8(BjVz?zzjIh7kd&d>zmxyd zJ}|X?lv11HSLUJsOP*O;H>)#szlZQb0zCe*mwL*iRgq`-4ZP@01FWJVxiw45p(gvo zoozQ!XmDMMCiZrfOfFfOY4Ls}$2K>*SYaTQeH$=-k>hZd_5{}=D)5tKIiPm~S6K@j ztSq_{Kqeiw7qFZcqZ%bUtl}EUg>&WwyZGSAc_dDIJ9=L!LA$E@OD&cfC3*qhCz4nC zVeV$#1jGx?6T94qfl)Ng1^tKfYHxFJ@!#-*pV>kMc;ikUtjado;k;>CENA1QWk`0B zks$RnHnC+?8A1?t7=?8VG$C$m z-oC=WZXt?Qx0R(qqKDGdIxWWtcOrC<*MZXkDhfMAmQDwO*_;~XWY9bq_OX;i;k;K* zO{C~^g3m&)ooL7RKE^rgv{j@8*uzL?X)FW-dJMlOE3L(BLgpQ>JlYVg;2ur33zRuS zS_h%p*YHuy+L{8$WnF|L4c=~@aO;rdOoL6NdXvqhl}L|3!Uixx1~pRd=YeVGq9|`I zd4hV&;RgfcXW9b$2u|A!f0=cF&;G>vqS>pFY6(L;|)MPl=nL z*Ff)@sPF-fy!xShn%3=)DB^wNnz4icl83qoxGVEq*hE3mFD<&@P~2_)nZJHn&F@Dd z(Uy3%E8_>FSsJF{0p0`X?g=#|gT{&0+;r#(Qw2Ri5jJ)xeTA)_@H%^bOzT?WM53Ke z(bjX%%ZtmyHrDSB%OK&2qEv)hhLK59RP6J#FP{_WHCRRmNDP|^3&d?l&B_Q&5dXr+ zwXqpkU334!zBo|@Q1@hkrTpVlphJE>4yu_0Rwcgr>IhR6>Cl30Aplkhy#>o>HbkFU z(a|~fux&4cXF(DbN@)R+O~h757rA@kd`13EsG>St!C4eVB5hZpkGzVq4A1^1>nt3V z(v#blwn=g~7QHk5+MuOg;au0jL9oadKS&|lE)qw?2hgSMP3U`}Pv$BmENZ6AL+m1v zP2PGyDj#DXB$Z_)?!hhNYzXUUuz>L?Si>rLCM?I1Q|x;|XwP0$hZU@3dIwAba*?n3 zJW1ggh=Z_FGVc3gOWjcvs~jxv4osU=cu)j4i{~c_yv~(%wADmN1bTTaEW9AU3uy+t z0ap4aDJ%7g!M>&s)Qgu(qP2(Fx%6s#AbAUt zFnJH*P-S|^k@DXLBx6iuUVRVxb0jeP=`S>e1%aK0|G6R9qa8bc)q2~XTQh92)RM+Sp$xpA!_O$Xzr|a!*-h z-ffV|x!{7!BRV?#yl#gtAdF@c%7wtc z(hYAJ@v~)M9H11uSTfOXgm^#kGC+6<_c&ZTEVr4Vn4F2Gyp6sVY`C$x&dy?$cVH_l zT#DDUI90+6rD1Nh#jOOLC_{Dp}?Zm(GW9Lsmi6ue5 zS^N=FUVx(>!Aeb(%^48=>Juf&0$sNx)hG+7M zelouXg4NGRt}xU*V+URHt`Mtk`4YpoOX%8&3R`I_5kWmnsaVqdN9>rxI0N=` zfZ!fbK9)%hQA|rNpI41gu+DiGEHr5+j6<*E%d*e=Vh#}>O1Ou~v(4uwlbRkzBkMA{ z9&qd)hVHjENpR(hCKOowgWE$aLlR8Id_`6uuTEO>s@vn<`o(YgP3GisNWfFPzUvhO zZj+e(E%5;Nde$49P$l~Of*ZoP=hTdFQsp8)mWI}@J=7C~WrqG2sInTqsn(C)_xL*dqhhpP=7Z)N@^Q@8r!%V60Qk*!>uX#1mW4GPVfM<4@Yrnq zS&|e9LVEv{3AG8-J1Z4g3OAU9(!zb}V!~nJpP@J1sb}fkvXzhNXu66DKI{tQ)v#{{ z`>Y!hy%PA93jJO%FY)aYTTyH_VXdaR z&kHUMa>aXQgzMrXzR%duerYenVQfX@Uwf5+bCElIfHw$*rv|@kos~Hv2w3V|;b|6ie7Tc*zvN;mpO?pRDbQwb> zewDX%CSX&?8^&G8D99$eI>rw{aQRcezwZd`MXhj(-C5~Hqe~VnH|d(cK-%~>FwEd> zTkutxMcMsBGI6p6s7nTqkJ=U8XSt+r#u;6qVQucILvWQ`2p>|9v!(}cby-=skGg&CLoyDPR{~8`DXPw6@`n@zC+n235%Sw1HK;7v!%eM$sZ@am zo^E;JOH?IPS)Ly!aWbmUV&r~St|6oTVZ4aD>Oi1B|AEj8&K%T|4*VyQ)p?d_S7wzg z%Ms)`L_?g?vylqzlw`PFdhjm6q3a8wx{(;I!i6n{OwO@LJZUE!Bkf0sm-Yc64ro?A z-*g%=7JJotQ#nMz0iBu}`>gIjS4OScWc}~y#elPu=sBs4@*vLgpiao1picG1pw1Ds z1ar*cDO#mdcR^x}W^d+n_N(jzNwZ9L9Y_y%TzHi!7V}e-=U!Y{b_kpjWVh3jOw_?q zZZ>0P@Jm_L+rz3EC@Ytx7;6i=?BQaV+e+2(h|%Qs%(8sFBL?^>@w0pxxPrf`fYv!w z20^uDG|IMUx$!Rk7PjV@NS&@_-8@0qtnhVJ9hj%<9cXn*_BXMNV?le=Ra^4%S(Qlv zuByh^RDF+Yk6px-uh$FBfP>Z4N6;Uw3Z+tsKUk}UVfwkszqRW`%4Kr?{WfXFx@r?- zR6wsoq&@2TNVev--Nl|2{OcO0?dc3);<<;MZZBQ54LTi;Znw!%DxI2_O)JlW5jak0e*O z{5?a48~9>ygHq55`7H+%nQ$g9uSza_-UxWvs&RavA(R2(}bD0Z+UIGpEHpbLEV zDa3vZ_3;X3ty1AAgrA@^}4xrYo`S z^sWRfB{V3I)V9pw4g-e zij?S_-a}LoUw08@4}ZPsP@-&_7;|XiQOj@GwW^*Uy%32Ptyx*gqM9{%O%geRIZazo z44Dv5%A4IW!U3>mC!51FVvX>MjUQAOkC5LLD8z-4FjfS6ZVrDbt(UkOy0krQXO0%d z+fr7uaRlXY2;_!-lSk3kDU`~RVuN`sO{hJ`7&~Y;7;TcP#dO#Y?Rp%HI@Yndua+4h zGMO|dScgKl5sTx|t;&6X@^9D2G>hdVlF*IE^z+4XGF}}0UVAvj@q{wV)rgbPJ0YVG ziC1xRUHsbI!0B&VxQMIKwAhC;PXl&uxhL4P5>9);4)#+b&$6AYz5SY5&oAsNe-+_Kz}IhPw? zso?Q8SGqZb&#_<%r5+nEsxCaJCzHB3IJHe4nZs2bnL|Vx>D#ycms4VCe#KbOaX4sk zM1dO_2@68|UpL_Q0_PK98r-OsU@D!~(Y!0&`|EWAkucwA_d^=mDps~kCesGE7gKa5 z!^#fBewNN0&XqA5sM3cfAb{CZAfmgRW6+{mM9m`|iw%O2b#KyfuCvg1q!q%DzS=#9 zzNwrs40o!GNlH7ASh6{p7&F#!Vv3Qcw)Z(zkueo#(xTGk(=FL?rAG67w=W$8c~>=h zCu$T`EQ)x>B{J2#eXui=zT0}>N^CnQ*`8-}et%R;PalUfI8GH`FrK@rzlzp!j0`~A zpK{iQf6|PqaeY-<^9zlLgf%VE0f6Yt0yVmoc0QYIWMyE( zyJha{N$ZxsY6j%bOe~qcXfe?;xmQ=*ZS)s>+a!hPwVHj1^4lcFHir%ZAgY$QfpJ}{ z`nBc9a>#oqln-%GM>raw$Db`d6?zwyq1WnZqz#r=N1DhAx+!mxnaj-U2O$>xGz2L#^6&;&-YCI%@}5@!Dw z42DHqxJq5J0Wiz{)PJ1oz5-cz$hkg?Az22h5TM=|@wc;NisvEgvsgd-8VCKHe7K|L ze+9WmpBArE^%Jk-N-rMa({g`fF{$y}8;|GIsml+XZp183W%$5ErEmskS&_^Aa#1yX z3eSY@T3iuT&*IPSQ^{Hj*W_=kpMf%Q)ot^DL(LF%i486G}+ZEJu&247$`kSm*@GvtulA~0oO!_U(w{Z6&ksP%O zolkJF5OyDLKv?iKx6v8 zxTIx3s?l*xmdd&v;+!$uiPkR+ya+(T!@=gSsfWQX3NA$)@px3h3s&9)$qLXe&LhH- ze+j||)0Z6W!CXe~E$0U77Il|fK-z_tV%d_CaodEFG5PNS&k^879hAG27qMb7`rkID+Jx92mRI=xOG^ypUc`pU5nuyxmpm*b>Ldd znjn8>1I6cQAW!S?HkuY7sVAz0;iuDuD#4DavPviuD;J*E$AxunZ1X!6Qb&&7vh2@q zb8A4%`2?(m(-sboLML3wcNk-nRGqLP6!>bSddF?`eBO^by39Tdf-S&!Q*po2a5BBH z+>mQ=$3R62wx|H%gBB9NeB#N3vB#^;SpQ)`vr8>N!+ZXDYFO^ZCO9xRAm>{2Lst}z zuV~m?Mq3WqbN@%Z@&3<<8i8rDedDISS~iERL#+@0w8t9t&pQ>a2Q@R5wpEbNl4i%fsyX~|)%4(7YNTXXQ_}57hTW=;7^9dH#634 zSt$TIshTP%rBcXkE|lIv0i>eDRG~~V446VA6~gS0A)K7>l7=!7Uv}DL7oFSt|7$5$ zIn}^*-nz?S&QrZ8uabUSDu9<#@0J3X{#X~pGeo}G!deuCBO>)o0Hj>ErOe9QgFWy` z{ujRhcAorq{k$9U0{MbivL@^~m1fF46ME8r%LZ_jR%vx>f(uh% z{BJ%il5tTTZi;v<1~^#Y%2W{2%4Erg2Q`2n{wf?$C4S)HS(C%2bqBq+sT|Df?T7wc zIkCP6lCh_V9q)5E%qiUC#kXaH--H0oh-=&%IV=~p2CzEQV_&&kIDgYvuS24F+#Tl( zZ!65}?iQ#f9h8zGh>*8Bu|=%T0`ShUs8P+*wJM2h`?Ds2WeK8T#}k~CXL=r)lqqVX zRGd!SMCMx?8MY01BB&}=^k}inH52LpK5mO&a(cT)8wIYcc^Y^VOBYPt=e3fk9xJ-_ zzM#E+MS!+FIfiI%CG{Y&|1=tH#C|x%Ookq-;;Q!MN2CmCff>r5B4A0i4;6Aym z^g5#!%%IkSYy|*O*+P&5g`Fhrss--1f#LxbCsIT7V)checAmWQR}+4DnL5`~mdf@K zQ!kzbE*UQP{~%=hl|GuCOC6&)Upf5|%}D*SECfg~{!jh*KLlep1rD*i$*|32?6J!Y zp2a+WKS_Skm^t-Iz0p!StIlkJT&vDZ*)1BseVTPci8d!Ouv1#4S9L=Yd{Oen#GSKH z5v-{<5}4{Hg^~44HR&wvdYp2PW;F_^ss@eti_a_CHal+pR6}K(chR+8jG?dY@$g?T z*WXewg>^VnFCEdUK9V;0m0$o&2C~vflDMqUNR51)H5iGZ_lnkwj)f#xW0=Bh+Q4X| z>>NWL=2x*+2HB{X7_QvS8zY{E_BQ3(Q#L)M3F$ThLRit+#E{RZPIqgy?B6rt0B8dA z0;#@>W=*Wybu8agc@Mw@$j z@NZtS2CL99O`*`cB6*d*4^7sv*dSUAxPa?~$_X>Ma_=9vFoj>S=MA_aP8vENV%NA) zDQm$~D{JAIj$d`>ZS!t0UL=OAelZqHqK0JxTI`j~la8~<^g5Q&T0?X_OHkFM6LWbb zfq4}+*#XaFkns-_8FshbHqqh}hrpN~6akIzQET!3Rgf#pJ7gLjF%ZyM`P^nrkIYs^ zHh6VNuTIroRqtc4#Y`!mouR`1tsx8_x^94;fvr1&|D+H%TqtK-rB+D59DugO0{}ro zP+SI*DHmn;d91SVt=YxCiGMc(w6=v^V!O0Br>4lfIpfmeDmaF5whJ8ixHH1?_Fu{c zjciDq}!}*2OcvCGg^*U@()rM8Qh@jH4)}_R43<#%&d)I_4R6y=R6;n?QUy zG`p2sWnhbAi~jEt&89$AP*py_0TE5Jb=G6H<5u_VruYuoBwHpr2K*W|%VUpkchKKt zg>bFg@PS2gV}3*j+4gOk?uCWEq3zfYiPVt+4p4-PnbEs(o2#(xee}A6afg%w35}NQ z#F#W$a$1fvB|s~i@fPog>+_#3M}5^aYX-^sRJckdRn}L(Z?mp&TWb0qUAZ`qa&-wb ztu)?IR}IhPtp?`vpY5_X;_!BZ;#B|OuCY@It6X3{ZxrdT+KcqmGmN{JznEjn23bUk zozWChbWk<9GHvE{E=yEJ?*Jjfy8f5e5MJK0%nb$q!o~bN7SkStY{C--t zL@RU^(d8+o{ebNc(~-DY`ls9?{T2}J)k%YYeMFSX!bUeDt}j~+2h2T66hKXwgQ7qV znV?(TC^ts|&CxegltRcejDr40Bmm4pNuU&Z6)K%UO|o8r!KJ(zYTN!k z8KN!zE1*h6>Q|8*=FQr=Dt&~TujM<0&lxPRUUL#3vL|Up?&q5k>Qshvkbv8S_{w)3qn~Ok~ z&br?D$>}MxZ>0e_){8-!JnJr{v3_W4B7~M60+BTGRGB7r5u}!8M7#6(6E%lWOta?MKx28(Z z;gIP-3+oq5aspWjV_KuVIyYMxvuCdF-r|4Y#9%X+@qc0&c`#kVd}O= zYL?R@XHXjCE`FR!{1!5`HI52A5<$CIOupkZ;Ia3cchdq5r{gKLDfxOSyw-PJj+(Z} zx=2Yh%fbmfa%(?r|E#zIB=y~SO+HZ0$S)Eu-j8e92U5vh%TtoiT0$vUu6MmTUeDT;&i(Xb!}B(uh*v2M$Z z>1{*t1qW%4C{QSnTCE3|w_ox#srG&+@zH~iSZ75ylwEg^wkikDxxczubAEOIlH1oE z?xx>tyLcF;DI=>MsC1V?i6cuE_Ihop+5W3tkny0;KW-Jq$egZ$)nD)#60|jsVNt&#YBK~+~IZwVkM8XA#m6o*Aht%5}SoTTor(Q z_XeC$ZdUR!rxLU4yxt1Gk>xkE(#<%?m{z@MCea8M;q^SoS&Rb0;dKv+h$o%I%z;41 z#9JFB8lNl?H2`>fiUXfzGf(jv0wE}2)%@z_sPljtKILF_DZj7+I(aY*?54lx{^4#_ zF-ijo)qLP=fe1!z%FQD_EC2bafc0rgMG1`;l&K1L6A^T;gN0Gne2VY3FODBlNfp5AEFz(YD(A?vb{^j1&P=r%T>*97^#={TS zSk|vS-`v8~9!p?l4&qA(F)T+>47H+y@ZUfcNWI{Wi9Ste#rVDHErnLV3)5W4v){KC zdYkn=GS33=Kac`caXE=ug*f8Y1F)RYiY4h=E5NeFVV(Pqc{v{)@qRp&_qPk$*z^3d zfg)coYuutcIV@PLTg=JgDM5hj#M~}PVFDpKYYD#B4Y1|%LO}C!Z;$RgIsLx;*rww| zE3Co5j8$MN=QROzB78p$Y5G=05q2)5sD6d3?Iu5?RgNagxUI>{Rj1;9qS-o$u1)qj zYcKRl%zTXrH~OAFz<;t|qB=xf!ce8*0>YPd z!S{Xh#P_Y9nLj>MYFGf*34zMySrHXV+_EQYMSB>=)^u*c4%3aWPqGWJ>ep7<^R%hC!X31=svNUP3(Et@) z6J&YP-rcCtd7n|5!0Lj*+E+)IdO zc=hp)N&Pd#s!c(gSJ5I60)nY}H!*%IB<2Q5dRX*^QDp$BGS{H%C)A);TV=ra!2rx4 zY&~_up&euwS9L%W1K4_$@~@tIl3F0Oc0#XBfy@YU7V@z8}HKD&jK zd7!;`3WpVcTneX|a_movEiv_UplpiEN0U|{SAi-qFDQ=TS-{0+bzSyjrAk4hd^k^r zP*j0%_X}PK$n%G&RD1+XWj4#$eF2*pnp8BfNi!eyujF2g6Vve?yU#aGfXv!VV;+~a@`mR($Xz^<(YjH4y99b(0oweQGNg~a8si>z^ z35qs}xxzQt3GOAv>LnhGmO@k}H;H{z0oA-OC<|nt#?X5!wZbr`X#}E?SKZH2J_*@} zNB&X;mRR&Nlc;q9?0QNJRdVQp7DRHq3hE0SB6ShilT*Gf7;0aR^FjN`>D z8%YrB_x_ARGq^E=Wnz~zNP-_-Ach2<#LG!Uur&v7ldkon!V{{@ zlT|Uu+@o%?V?*dFjE9)~Et0p16|2AV_gR{{mqUp(oQG5-a49mN1I|boUPbiQ{PjLBRXdxlN#2UdU77@0-_}B zfNxa1DV&GE$uB84GUZ}Wb-IJW`!HyOGfyX_)i;SJ<^A{wP^}ZP@DgAnu_S?LsMhaz zz)1C`w`n$QR18u~2Ir$17O6~0-a|G+A-rzv7zV|1Ph5f$X}~$jn|?FtuH+fIb9XC@Sw$ygNIcgjy1RlxhMXnKF`Rm z0PD2Rd*w>J>;ktrkb)U!?*L-UIreNu!D3tDafFo2)8{A<#wMRXG#qz^fIXP6_9yb` zLRcD0kGj!pl$~juF2ku8WP~d5at;xFOJ~+*OWLa7Tv$Ov>7)AxDQsY9H6+`dKvip; zib?0&kkJb0~q){Yfy@wDV6Eg zgE0p)ui5@nmHD0F!mBtO-vwj9sM7j_2(T3_^%r?=L7_wfl4_#?^myHOsU<;`T0t~f z=YFAc6Lx?Ixt96c&qby+EC5L zE*QWpx~6_proGw#<#bU%Sc2^9$2;#XfnCi?+>?YkT$`7+y$lNg58esPpw)C7Xp0JM}j27_(U1&u2+q}L$n2b!t}80Y*zpWOdTD+ZlHTK&MtJU28;$Flz0 ze?sFsbzk`TU6D02J=hbl&t$-evs7Y~WTt{k3TJA(CFUDp(sam+bGO1HC%G%A7t13x zaoP4#R88fhm=G}%a+jD>DwKhSa?^DXH%Ch-F4O6#O z;aH&9`j+e@5QTfg3B!0>AqcT=i&yu5hfPCR^u!i#?xJiiY90j$yM_9VTwyzhoX(VzD4lsW*3r>p2#qrk-YIh-HE_0 zs0h?8u){4DL>kG#xD5S=N>%wg3B=;BfVMOxyd{e|vuK*Ta7g?03fbS?pmF_S=QGZI zrP8KzigRvF&}Dv%46Dhk`&GWF0;*XyML73KXuAQ3Yr6$iTR*!S^WcI&x8cP7 zBHw0{Nklo3&1sf$yQ>n|9Am1#Dk_DoMngez(jOlY;7}erdb9Z??nIp&90u~yt6q{= zvV&_J>A`C7uKd77rsuIA_6zWS%5ez~sqrxJi}Aw^(5e@+jb%uCCCw=J8eNP4QYq3p zMfHYopN7P%-RnXId>!Y#xYTY)Vb;68VV!l5i8Es!u{nLG(Z zcWXXwAD?BtS3Vq?$j_u2aW(DPHQWZUEGh|7AfZSw${Ka{bcgsu-es_5BL7SunV(0F^QBP~dVa;Pq-F$?CX;(H5=Uqq12@kYJ z=sV;Nv;W7Q!xs}o0_hjs4G$8S15a)c3qT?BA?6jTeseiYPQjkCY_t}@yoFAvO6e+G z<#Z1m6;6A{eAR<3h-y&8uQIe8A_+&RY1Ra!Jgez%;nu{oE3?!g-Kj>_BD2|944S-% z5?Ha|9JElXcs0m1 z4g35%z5Cfgq)Pd#g~ct*3CW)Bj#)Igz$&8XWQ|v-6qFyi= z3}-g6%PaMLr&)<3kWkS!26R~*t|h-5h*7QB9qq@iVcYrV}-SWVp` z+?X^wWf(4WPPM}*3RWa|mQtdj3%-88yj0V0n##Tk@4|D_Ur_}OXw$(KiXj>I`6c0r z)NeDktFLlCv>Q*VqL7F$yYprY!tEiW9H6Pv7~CC!x4vLsFQV0ZYABZVo7djvp?y1G zi#iC8CI!pat-%3AQe*oa76)9KbZ`MDXw>H3OOW! zn1*@Oe2Bg{<2~)546LeEsm?r%IcmB!Z@ZffhSJW2UX-egK!{vcidmS$IkvqA7*Jsb zH?TxP(pEGeRhwP^nAGJjoDWx-k^3JDO#6FP3xStaj`8DOmEHr=CR{zhogtynuHC=u zn*q?9ndDK=S2f0)Ov8^n>_sH$*;!N)qR`a3%owkpI;-Q#(08i|b_WUQuzoCNj44dP z#OzH)j}P96EKU~hW9A(Wz{%0rWdj42i11FcJy>q+xMvdZqBBUAvihp zJ)N@EUpsBcgw?*N6G*;62vEuV7%A4tL5K8ZSNmw!P9|z^2%YH`UQQM5aAlk`oDFtY zabI-B{jN{BFf7Cedp$lFoB?P8za$tE_E}265ctI7PK&oI_Baq^A@<^Y+Mw8rl2R$U z9j>&=O-Qp@qubsRp_duXFv+A+a%%wBa%e15uo1K7-yVrtzpuSZ@?^FYK}v+Fuhye~Up+3lCUrr& zR$Boy3YXo4l<=z!IF`);9%pxfs!7W03#qU=f!yW36MD9Q;Ks_MVXK>1EnL~x^hxdp zY0QU54YJ-%SRHMQEGr6rwBPIiErtfp%@m_jTTX5K=cz8V+i64njy~wW{2r;OZpQV1 zzLVF+-rf-fPYvx&l3t*^%>xwSSBf1Jk${iGDTLQ_8-7Nz9f?NL^6(JvCIP@S=$5TG z`1m)wd@S}m7iO0!Yq<~_0Z9UtWQih3WYV$Dl!hq~S8P1=vL=BS=XN6&9&Iz+Uv(<# zR69#)Wn+rRnh=h99FYwnJnlRPouoCJ^eCgPyOdoloGa`Hr<7heRU@E2qb?yLjaoSf zfm*tBAyuksdImuL6}ntOQk*gnsm^V$bJn!QUY~~*pwGgHs?7#j-1Ej(YIUM=3XHx0 z+(KdB*RBJRMB?tYQ(`rm;L~=SxiK#*F2kxa2k0!-O3c#5wezN<+8daA_}LV407@)< zp;*~d8&@!;`yJC;@i@!yP9&KQThjs)qZ50Fx+9MhMJF4g4?Q2Sw#QbWM$Jd*|miLZ_B8FW08QW8(Id&x&G%$;yr(lK~2IMnsEiD*2rwn zGJ!^*Y{^M$p{TC$M@2TPhzIP6rcnN1RP(4iHP#GbpHvewFSzLXN?3wpJWBe?O^eE? zKH(|9=RyX2)IyVhm?r7A;Y_Swv*{Qsrb0yLzth`~@USkzW0K1jQLHOq6%=YiM6lPC z>RW`gI!&YTWz&wWo>5leGB}sjrF>YkHR(T4ab+zM?Z*`7`S!7w$E=$Bpgs{0l8t|g zM-cxRgK2p}^_Rbq>nwvGoF<~KB3p@jenWXnL`u;EU8d-c zwynIYGJiFI7&lUp7ibKrIB}OfeV5ZU2Vz>*{-oWWz_3}lZ3UnJ?mpZ!+O%aW2F?k| zx*P5u$!3jpSyNT78g{CxDi2zR$AiwCMN1{aUl!}s%%j!8&8u6S4%-h|6sXH`j1bWS zk|j!)YLVV^s?y+L#l|Nw2pcQsnv;!R&I?evIXX+Iy}`RQjoHeG0j+MK4c>2)Ujg0< zicujv@XA9G&I7)GW>%Y%-^vkG{_s8?Xq@Du6W92oGpFHGC$?H(`kYTxzElwD21QB> z<26FYcIWO8O=kA(3szfS{Z4)GkZJ+P1JfsM27+H*hoEksY*uu`64Gy!qmemlZ+lS8Oyhv za26j4i|D;Q7*=om0Zl2nB4N!qqj^%~Z;r+Ucr~U%berl{xDkM&kBHNP)f1;jZ^SiC z02}rFRy`WG>|Y!#+b@{+!lr(WbB479lZOEow}8NI;N{nht@IX4eR~mRc)#j05?vc8 zM@)`4HKOilGb5jGbtk#cW0Y^dwv1uhU1UW7CvrDMQXKV2y5CmDusNy`>$j3maD>)- z|66sK%I-QG(%D3a|n4A~Zowa%^CEuk z0(K3dv|01|TdvPV1xCDBcbQRU0L89Nvcqy z-82=s!`>57m7U3Z@=O0+s2(|RM_%Ex_s}?lw?AN7W-gc12gAuT_jfJ3I;Kbh7w=n} zfj!7Aefg?xgKU2AJ^JGFWe1tGb=r!z&$eIp~%+XkttY3r#YQero8rnSqGe|C&6E7 zUU$qQ9&>3MMR)I!ZNo}%fIRRO(Usm_j9B`If7$e5cwH3CwVwL1Hx~)F z!ia-aH~=gXUo>-;f20GK^}upDn{zOz!c`6Wn_{&fyB1irCCsmkSW8%u7`3WIi^iFG zQF|L??Rt8UqE>&HNK2Tj<;Q=Us7gUm&(6fbOGC!QQ%KxXM9#oO z$3(}owb7S1Fx%J1PgjYrBLQ9sC|ZJorEe~t4~T|x##YD-0z(c9XoLh)rZT&zB0eRh zFe;}sDl$Zm{{NVphSnSZ3<3Z^pauv4^=+=3fuo7Jor{x+)8(d=9I^sH$SzNB!6_Du zQ))0YT3T8jsi@je93;&SK_nf%SmKW^4YB zZY&!e+i0}fLI(|&`;ODK+v9V$+HEZz4c+J^J6m1#&9`Ffa|;&e{b+?}u^Q3dbd}9> zUg^}r!p+UgXa=?Q!t88?G#Syy(_g;>S^lgxan^Rwd#uwPRi3R{?&~asUiQ!4&t@k# zdU|^6ew@4=akO~&hWF!c%?K&EE?!I+yx^9M{84dYy0&jjq-(iEuE@SVQdx9Ss4DJoNdTH`anYpt)EA2fBw7VDUIeMIN>pl|d-5B0JkWk8T{d!v+ z^9jVH6XfXq(0cvzy5z>=qy74h%X9ttE1ng;yWP^cbxk3P?ca|2#+w&{cTLZOXw*=?^A_e_}ls)?o67v6#^qpC(88&#|VEFA*^mjSu@f2I7-{e@+>P7LF-G_;-K_84AUP|0lqj z#HJ|We|s7^6h(;mcYx#56o?7`C%`mFOcBC=2Ux^#T1oS7q#8Mksek#z@h_iB|MBVg zUp{61%cp;Z%;{e~$^LV|rvJ4$=>Kfa0ZQ2vPW!Lu{r&m(mzK06?;lX~e}M-41FG|{ z=t2J%)OkU8n{U0#c1cXjy5>J;DFIoR*V$}N`*TU!O`VlD*#CVt|J8|k2MPxOK*bC2 zpC4zdf%XkiUFKAIwzViux( z=-ZpZ$KOJ-?v<&1*kak*lBeMI^(M4Q6D|@^N8j`EXE@Z?x6O~Q_kl1XCXKHE;Q13W z_ZjzgJvfv+dW`qNXEGcJ$tz6}#V}=vLg!7SMO1X}N1Xk(_(>xh`X@T{kccFOdjKD0 z5S-Z7gyH#~o4-d`*&oRpttygD*wCvOqYF=bTrsc=|H!SlQaytKjAw~35LX%`DIF%7 zRB>%;jkfFZq0#%WSRp{hON4yLk<|h&;r;mvG$e_*pDfCJG4Od_!sN(TO!u*G+n!O1 z7sUXlx8bq*ZadV(z5ZL&C|L@D7&8FINTIn_fy`Y>PB45A#`q$vV@HaTy9e-L{AC8j+9HIKom6W93Wvi5j*}%~LL#tDAK@nq zZxiGV6@ihJYtL6Bgkpe;z_3fsi(wCkfgY9-z%)Ds_L1lw^&;-+xVi1PItT5F^qD1( z0Es z0VH-kKsIa)VJIulVObnmi{LvaB{;`aLPA$nM96Y_;BjJ6Il~8z@^-!nH$ODv()yI3 zUe~8%UBwMfvYc_V46Ll^L9F0x>-lps2Z2xnOYdc2#ozXnF4w-nNJ zS=dtyg76?%5^>T+w?R(rw+G5>5Rdr_d6gwaAf_32~craoT^ z)*`Jsc9YRvo^%z~t6Ze@3%lr8(`6G)OkEh$P0dWL2+HtU=EJ%7M|ORXUohKC{D`UL$NqY1CdO9SDsp}wOn zV4K9I=`Q>o{CEr3FWKm#s=2YbY;(f@YDeAzM+|X02e$&UsI*vIUjF>^mZ|M~D?n$#a7aFg}9Zfx_g)Bkk8)N!ZAviM)Gag>tfaLi_OC!&a|j z<;W{fj#^(2(JzFR1EHxZ>(NUt7O6WRN}%ro%`{8vC__hxa5E_sVjGS&5_YxVAAq?~ z_nqs18uBA^P#LvCK5G>`RCnUlLWwjsOtyt`XBV!hk1r3H?IrToS*+?bB{7g}0 zY>}!4T`Y&4sbIXvvUtmq-!XEk?T`f31Qi3_oO;Z5VKEOu8?NtATLih(KXR&Vmhslx zwp2NwAy!ga9=clB>eN_E8#z~-q~M%ph(17LUYs#>=2MWEAejkw1d*gxK=KTQ8+vV+ z-4u!AQkxus9Z&{fx2Tlu{A4|Yzb2!3@(l5g7Rql;2^B2sX>lhD^(w-!_?^vuQ!1t{ zwQj#I>RIOsCC&$I9_ayYK{5_5k`Xjr&yle9{Vacv!gTn>NSI}IKp!& zO}XNHAPk+nC1nol?|7R!c&Z{`w3R1Sb)2+XH+G3`!TdqJ7VB?MJ99MwvB;+Ry6%M`d8rmZPLh~>PZQi>xd!w(*Fsda zO7>*U#Ot@g{%5|Y+Dsjq%IIbNId63xWVi~BNe%Kv7KC>Nj@;7M9{;)J3&@C1%TkfI z)a6V&T9Jrh+D>&gqD*AG*wxO@2N4qKMllNv-Io=qd697 zSnYIbuqU?vq1QAH>0BHGi=@sJPdU%splFL``nYf&Qwqkb2;@hBeBzI+UOdU+A}6HZ zj=MQz4@uk10ki2A;2F6AFqbV{S$`Wk>O&f(e+Tyfd0pk90|WZW%+vxZmY{3^H!PCv zyB|^(zhmYW?)J)lTaf~Dct|>VOhpw$U0v6L_GI3b_2kUOi3H>U-uS^(tUB~ekz$|o zVl}%VwQrp+F4x7@u*Mb1WvDgw@NXQYiI<&?`{jM;LS)0wL#=$|GB0m zvWTy2$*Nhr!`lji3gc^|$&@5!I>{xDfE2JvVyQb_K%SYieRcWOD>CyGqp6@J*q5uO zmi;HyWU{dP)0`)+^*NB_+yZQ!>g{w#D+z^%CX|IQWOpGuxxKE-7_^P7uH&yKzgkEK zo|C$AX9-!$2>OY9i4~bo6~U{fvqfL0NkD=U+b&p%k~#~wYh@)zEvQXKNiCn7q_B+l z3d05DQpx%^9o{%l00bekHgwZQY^}E18f|O8H*f;xlC` z=|}!*U#6y>>dfo;3CbUloq#c^Y_Ww$OT}-ImHw~ji-m2{WRDw#zC4$$5B<70u?OO? z;a#!a<;yt4?6I#b$aCY~3QUeh%3A`0u;Sf6=u1wO?UMGk^7F}?DyJ-}uD?2*uqZM) zKYi_cx%H$aM(oUVMC*siaR{pfo>## z41Kd0wD)5=kQGTe08Knm6Y=u%@RD|AqFfOorpn-S`^}>O0J;EY6yx#5k zQ5cJU7=;s)<~&vWtckSUM6nbkefYiMuU19x-b^4m?E-)V{22SaXD*(5-K?126lj^V-1p&7aj>QK3so$Bh_e6F{35Y@MJ= z$OV}%Po}!tbvs;m=Q$7k`hN;(8uq#(k+k2LA{_w0_v3%pDGd#rER6I_tu4&Vo%Ng@ z4J>ReY|Zr8=;_@V=;`TcE$z*+J6zP2^&WUR#RL7wvnk0*HfiSZX<(w8{F0pEBwH0J z35n)84)8ZOIT(k&ha?~X!!YsjZEr{WUg14&JzpGi_*S`Hn)RCHHZSQObF}rgsq_KU zu*k3g;Ns%$T=qiy4FVY_!>S~2onVf0yMB)(d~|gFc|k{w|B$vmGcr8*T3?d#W<=wo z@;LH|M958t>-A@~$L$u@lln_tGYqB`LLO{qyYqSb1w6nvFfJ%A&d)C{DlIMSfOqxd z&w=s50ZI})p1i!GQbHnMo)`Z|SV&6B6E7+c@DJEQAuP>|FVgfLJluHnHeXx#-Yy&^llM_aOH#;Jz=wF0Zd8abameNzu>P*&6_R zczC=oT)1qkSnak&ve%Z*Q#Z zEN!jrEvV@!YPz&+x83M_jE;hanwpfdxU|T|kNw5W;`aRT^au|F2P-!-IXyM_N!z!) z#Kzj%;^zAN6mM2`A2~tw@Hpk$aRcz;{zdkQ=knnN;rKB(m?x!!spWdL4 z?T#J4Ki|8u!slY;LG&d#m;mqCl*h%Fo^xik|{%9BJRQR=By+ zc64p^8$wi47+8C23?#|5oCVO7A6)%n;ElcxP&q*Wl;g^y zuQrYu6by z&jP(}4-m0iW!l?Q7(!CiXItDuIy1z$TZ*#Eq=KIF^Jh&8S;gaxPHT;d>er=DYoFxW zWm><__=fx+aAA9;k&=;AYV6$L5$^*W38?m$^j0+4ngJ7^)T0OA7dA_yy{L{1Ev^gn zEhfBI><-0sOuGgA&jT>Zmabxs1yBTKcmSCe+~?Ev63F|>#oe zQ#=Ax`*&x~7WvI>>hTHYPB7r(+%-Z5uSt6A+=a3OoSOSOPeO#yoC`xD$y+4HS8+EE zZDe?#&duQdSlSbQ-d6;?6vnjbpP8UNKIVGkki}lP0Y0O5!zw`9hO)R>vKH2_wF=vU zDcZ%U+z#x+06)*M0$&{@#J4J!J~YOp^^2tni)YYjl>2-uthRPa^Ye5VaPkbU2@wN( z=^Swq-%@LzSLxGSXQDur?|>D%v_rBZdCpIi$x${;4>^hTj;9esmdnd=wWKO3B96B+ zj%fuxWwg7bC0$0<)8~>p7w{%?L0t_dd3#`-ORfy#G@)9h7eMThfAiqaS4rxxL`=kZ zdONamXb*q3TD=D{qcXUX|DojgGatQetF3E*iKU9I&OhxCoI9_?+3#MfvGNdG?V&jM z2a%Fxp=`?21$aiQ0XUa>ugCg6ni;u`?{ofG6@Ssh-;gu~gIy~OGbmuIfp5}VT;%ym z+GZ!`bZw?xS%~{CU-3elf%GxygHJMlhUV43*KKp??MJ43rlNEkAyUnXex!dE(ogB$ z#gk|4KDKXWqnbTd1;ZT|&sO|E!@3?*efz2VeBr5OE!P=WnSfO;owY579(hi~YF3Kj zG4vP5{pPrzs8VS^{1b5t__GY}06OErxNwUw!#K4bT#cRn!f;~g>LrQQ9?HC2#w0sl z3$JXZqL#8Ec}QyyZai8`NZ6f8?gS#4^vxdUhdn9(iMsy`DsLnA(dn;Got_cL(fGv1 ztYDf^B15VGsW(!yz*gG1#Uk77#Ia5TTkTb(@{ai(**Vs(m(2YG+%Y$NF@(;({O6V; zG3xz_dS~QZy55SjdHOvd@RPbqn=W!1+%Ck6NuPeFaw5w(i>rp+eFIgVg)bqF@M?N~ z`JTupMNaL9KJ?G#Sk%CNK+#$~t;Xw_F`|OlI@Zi3@!^$d&VB2O4Tp1bgst`g$s>Vy zwQlq{IK%S^(kAl=;JAi+ZThQKaZ@hCkfnC2Kmz(nkU0AK{D-OLy@QAx;k3Ae+gej{ zIQfUou`)d;AQ!mTDkC3~?ObBI*OFof+dPM}UnSPuA0nME8)O>Rk>{A4@mhHdtJ=G=HG{8KCpQ1g|T2 zgJNL&h)F0_a~PIyTrSr|2`D^ViC3|o0jDXavR!pdJ;1N+L${`z7}bDC@AZl5JHKy0 zE)-`n8ekdAaJdaMDtm*c(d@sFEPy=HH#OA1b zJSb19zVO4CLecyJ>EU|qWZfD{J6xhX+6;Y@O;IjH2o}!6Ck*aDt2OqO9nJtTATTi^ zQO$7VnY`6v#>J6hQ||wRR>GI)-MGwB7?ET?8A62CUtTLPCn^!r%uhN4k1p2DsPG=4 zhs1=5#)(&QMuo;XU#07XX4mnmd%+c=a;jrTnd4Uvn-iL-f~-9n-XmGTi{l4Ngx8WH z>BJwat*!7hc^qmw<0fYbr8EoctzrH^EIs$GPw=eagSdyI<*i+FhIQ7cG{)A%H%C3v zgGeTOg=b}vb<@J1X&TOEF&KGy#p);*o&MHSUjVK0L{J^6s)&pZ$3K>gFb?c!JadFT znXRXjOQWy4H3of?M`u8y^77lT>6*!S_Z}HMZ2qeFt_!B3RGy&0jB?*yON+5b0WWK4 zFR^p8hIZqFl84@Zd!UyDg3x|h^iVn@OSxPHZlX7Fxf-shAs{_YYgB2OjYrA*8AVn+ zoqyWMP)$`-I*xa2Y7u1Y2$+N#i7NQd`Liwx1j#>$vU0FT!;?v_+P~5kMGVd_v^W61>6`;CzdtznadmbnYQ;tDk>h*;G+J(-Y6jhc`R6KdS*^nAA50asf^f)tb+aSi z(@<*q7Aa@=h(nHU78TmlqW~Z!NWRU5?*pn=&Eny+Xq9iy2k`s++{11Np%xT$_HV7%DcI{HKdJC8Tk3QR}= z)p}COx}7=+0sjtpMkIQI?*SUWh9naiz~!PhkR6I_zTMaUr93Q#eU$1iq+dD8+st~D z|KT~?l4+8cfvmNnF1uu=dEB_0@`mu%G?@A;Flry4@wceqT{91vA;_MB!vO&wr5(G> z^kkjQ+XFKFM|h(b-7{$A34z0n0Yhv}46%4Q@8BT&aIi-a$FCKWqv@m|urCmAO$!Uf z{U^zt2xzX4>!CEOfEQJVR06G1?7CM#fv95PAW0&vlW&dYpjLn_=FcoT&OA3b*?WJZo!Nff$7U$Q4s(# zTK(s|$yiPyR+YN|u+xXJW(cybc>U8*vJ-+utm1J-T{E&h#ar6}vI30WtKiY}k}5ff z);JLN1|KBMNTqbx-Np`oB1u}4FYXj=LGrclOG|()x~=D!_z2>YrxAFOhVrP*;vINi zD5VtoA{B)#9zThuJSm0j1uOP>D)V!`@SJk{t@G1aH}S{ZF4R;{u~opd2d~p^QWJ^C z2ZLlVG=dGiemfKnUYtLUiKXFzzusW&fliC5na0Vy?3Fian?BS<&HdER{W!zaUopM0 z2%&k$&biOVd$^J47yAx$zv9gwk{IoO5{BgemS(K7>x<|CwR+DAr}DOj8qL|%=Nz?D zLtiaSJ3SnIDoJ{lZlgdm%Hr@lf%9=1XIcO>0RJhr@~XE?w5f?& zbXxefO;z(joy+1^*F7KF+xil7nSL9n=w8PZNmpW95~p=OKQ({F)rV0Ju@n#5Z>oj|>r zHmgS>?SjThQ$7q{d1#zelz@r($NL{Bq(|{7QK9c@Hjdjj7LX@oatE!FTTq=TYFFv4 zkExtBn>@J@Z-y;xY3iDw>fK@-p)->0HMWrNmPDy?+;@`v*DI#rQ<6?Cxt6-Y;zNM! zu3X~4e-t(gr*Ma1t?ZhET(|2!96yN(=Sys7(FbnUB(J(3w#KsfT1ZB&H$jpEFu^XE zT*!4Bap4z&e>z%G06F`jy|ZR}p7y2#ceHmVBRClQh8d(+%1ts?YUc8Cc+js<7q(Y( zF*^+KCqG%cG){AgRw$i$jt%n1uI)de9t1j6us>W}XwzP{Z0q^E zZyBLps)xYM3BKj`=s+;iXzh%g03+ql1iNq~Q-LZ8lR&>8uUkZpB(WVrk98-J(nJ3wPDl?(7=^ zE$QYg&wupuQQ%X#fOEyn9ZnM{)-Ics);D?w-x^+^8hyv1Y$WyUyK_*!Of*R%W+!M_ zD9#-)Ju5;}pVIqpqoZ?z?b0v`n%>1S1gc#ZNHfVjOHh0sJ4`Ed3naw+=vZlrejUHg z#x4=-#BWhgXVva|!Zgt{0vf5xEQ6+G3@r^=>*sC}H9fAWK4ytscXFfh)I)^$AKzsk z1IMZH-rHDXCDSPai8H7E3H$Saq;LY@MFyeO?6Op%`O& z=NQ3hW0+Hc+jW4M`$|$bcRBRAS?6!k&eN4mjN;50hfk(nw?n!B6kbSCrLMPrlKm6q zaMnWR)iTgw(T*C$GBdx@%A3=daS!c#VuZr~DeNqR;_A9A+_<~DL$Kh%9RfjvYjAg` z(Iz24kU((P#u|5b4H6*1T^bMW&_ITFzNz_UQZ+T_*7>#1T2=R+s{3oNXPX?=PL^0- zU<|{(zu=}dRHu&^!Wsh|E_!aHgn5|CqtDdp-kg*N_9-Z?AfwZ)?!rO!svQ@`hF$K z>dcP|m{gOFImwZaPw9$~T?MnuKV1UEV*10eOY}$Dwmp_xU8f zupcBbVaRTbU*GoL!b;vz!W{JWx>T!_yl5qiUPY!{?r>~RvQXWi`mu1^@RU^XEB4;> z>+X6$&Id8y{8pbJ;;o365%n}03XGXkY7GT)fJdF{pc47ut>MT|1=4TYTm0*0|#b$?+L_hf3iM@gO62n&DxYSp3Lu zAIQOqc1f01wYwBd%oQusFN*M+9=@};oteDP5I!TwA-_;6reH>AqfWnHXBTkxQGeup6Lnq=OLBi*6wP0Zv6tM+Kb7^ zGn4Vos*2~F`;4LZ5vf~j6n%Rm>QKs6ron0>|SNu!nc^D&P-64m`6^p zT3pTeStY_IQqz({*r9QpK>`4s+hVOD$3?PSeuER+Y-Z7D*D$`?61nbvA)Z92fEbd} zbBqFkiH>h3@bBNPj!dricEehfRl7-MukWbW3*(cDhV}19LgDs8Yz5MX6%>AJS3o1! zMjgpkZk}lP&uJu4mw*zP21UbrJVJBapd%L85tYSuSHrru4UnU&fGOPuc50@9N4eoP z`EwX-dM|FaGgU6Mr+ji9+sA>_pSqg4!bTo_a?b%{!Io%#a$+FG9{2w_x6b4>RjI!* z@9i|=-|W`gKGs0%pKiAuJ;hYe%!EEsXG5O79h#|Dng1L+dKV@Vi;=g|3#B&F+vso# zQE`ATsKREL&RLiqZ$so-CecLd^j2z8Haj=uyi^jD?}F_5A|Q2Fem zRw7+;%fc&)`oyO0dPakEC)_}PRbd7jN49r7{IoO{eVT1fhI+Q-;$zOsGR_*Rv@-S| zzs;kOH-9EgmAOEcO`h_1^glPqEv{vssDFXlkkk>*vUANEG^}Nn5umyg^1*ASFfu~G zvg%Kj9(Zu`n9SmQM9EvFL3{aHJJh#<==P=&2DQ^a+2f0}&*##=*gjibt!?K{DL=n6 zFy4Y4UK9;9?{C#KuxG}9%YtlnZbD?l8MM@VEwGPnt;e&6$~;XAU4(a_QvuEYZi0gK<;zdnNQxVl^SgA#+F zCe4DJ3X-6$S2mz)`SK0USKN%-9Ue0b?FPgsv~ndB*>yyIbE#3kVrHtiK2EQhfghbw zs!{QEQPw#RvCyh9p^r_dCZA0!EpXf?l(y%kQZ=e}5Y_EnCCqTAXh6I|@lJjhxDda4? zE!S2zLVl07k=7$s)0}_y#W$ce$3-s@ zx0QBh44u^s&&aOAhTHKXN`{{jDp`ZVObUTUaIUQ9$aXm6B#SbJS@7KSaA;AYBW6cW zAf~9f@e)f6!hk1ezkn4WvFyT=+y!2+=DYp96e;yu9(L+?@-+B$y#~=bgOWJH`urxj zKjEyQs#__X#2h3q4cw7A-YZu;LKn|S6{AireY8vPMa))hDPIF_z(pf3eTL{k;ob#x z2juKiy)ah}HhGshl;I$kfD=7l0z*e9`#P+iWdu9#Vx?WKC-)HbUNZSX#OBt364BJ^ z_@3>{PX@hZ*VE^@^aEdQe!nU?ZDYJqnRUY-Tnih6JO8k}#Op=r092ZErfHAYWJ(+n z$hs$y{?xku%S(jql8c?0Dx9~9szGkp%aob`87+80+aMLF%wQklpOi#FccOI;4e@Hy zON8Aw*b+5Vmbq77^-D>9_?1|@cg*tX)d_-Iw)cJa)AzbyeWPiBqgl}PtM7b|KYBv# zuvFiSW#jQys-nv+jOE|Dn)NH5mf_D@->+<1f3`hs@aj{47fL)$##ob>9C-Xn@DCaG zR5`HQH9ISAm_fiM2cWaP#(OK}#JMB1CE`U;O7LK5zAFn!p1ox7HT@mifvJ)1HFh{4 zA{Y(gT*+QbEPhCbzHS@is0g(+sv^vw`AT{Ah%_?$%j8xpKAZ1P+b7OqsZk#ji(D21 zPiFiz9YjN`_)RFMHUUI%6M#~Kq)^ZMC&&Buo14`?T_33Z_5YXzbCGbPq$31hBuvwIB<^ML*SwG8_1^I^Xd50GXV2#V;9U#=hst;Kh8ud7><8cgU89*^Y2)bh* zp{|LvhEsBTZ#S*!kUYsBQT`+4_gjITO+eD~u~_0HOZf_W4u8SiS_WG2-Ly$gU~A?( z_?tzvAAZ)n$=RoVUQTL+yP13gl{M@h+u42iM8!?U8DN(3>(ZfG(qXv?&v5>y+Ud>cWqM$Yz-=n>e+P6bpcS+JDFOTLxSNv?8!8T=~(caR-$=~M46 zcw`GVL~-1agI)sume$QX<*o&B&Xy3NuGHWXGParHRB)E@?Y^7Q;-o`qxv~54l{WMn z&n`uiLRh$k^ckc*n=}SFp@jkwbyg;2+%k=bfI?*slU*+JrjOC5kMoS}DO0&=V7;c~H5J9oB|O{G$AfEdO^^pMu9NzoEmejJa}&{=?ZvBswcgRkaFQqB-6VGpwqgvZCV? z1mA99qEo8sq9zaF+?T+-xc`)-Fr=v~sJ9a|UBqFLCQMwP(?P=Xs?qoQR z3|S*Z3#$hzF-a12`Kl*bw4zUDKMoJjQ;%fsky1rRf} zk}&+%d_Kn(f6?XUSn{DCZMq3B98?$4^sDf3rLnjqARonDfdVa1vmVcCp2uc<`L3he zgK=fZHP1MmZ%M>QM-V^ypftPzf)QVS6;%J-go9`SsB5e{EO(<|ky+>?j-97lp3t;{ z(fasW<8=iU#$1-H2G8gbHR6W*jTg(fnIYk}TdAYMN^s zrEZNzJ=#_NhxnW+UazVnQd?$_}7C$uBz-5rjpo~SKh=8wxj=z9(7m^OPj8DUyys?ItP3*lFjvn& z78|c*+ud}{Hcugrvy>Cs-ZkDR@i)Lwa!@oL#TLuJzy}GtxGH{?K>?X=okw12NN!Z%vg=J>(>WwI`y)A7E2 zE|{_2F<(2+$M)IOM3%AXSzg14zFABd5m#!%%wnNj*Ih{Kg%8*QWF{W8QcLP^I43B) zule-Dql8EHaD@>Q*kcK|S9mU@uffCMT!E`4o$Nh=6 z=eti=%%3CsS9k|MmrO>5-e!vv*zy_pg;q2@@H|IoIdAkN@nlFt*Zq zF67F9pPdn}5ZsOVN@A;1(gS{ZD8$8^cpNnAKYnLjsvF?zl@I1VD_4p(?`AF3`RJTZ z)nDcGJTF$WeRCtGaw@QNuRA7R5|iC$L$d_*ady6Kmz5L$`glJ^BqpnbM{nTjrZ5?3 z_Q^5WYHL%@M!3Bb{u{wAMMvnSQ%OIZ2fKR+w~y7V`qy&Y8rr2x-SA~CZ)~K!P^%bb z$yNGL|DVHRAL|r(ITZFUvO9HO8=-Fj8b6PiECZ#8lC}JniTj3q{mo8PV7pI#L=J|P zXpPm;z_Z!<1YUzV4pbj{Ik`KaNh#`)H-u)gwb8fdf*-~fVI9Sbq0QxM^O{tTS=duG z@fo;ZRV*CYu|2+eU$k&r8!|Z%I*$RQa@twaV1?c=96Vjv6>Y{AZ`A+H?7AF^014@! zf23}&|L&hF!WDQH7UYi+T;nUx#F@`vVQY(ohYcFw!##Q2gkO3O{OYFKzLr}gudzHLh1;4Brs!<-?6X+!eOoS^3V~!n7I+F)FBEUm#gl`HJ;nL4PGX}np;t_Z9@`09 zo?p0do$kb8*Wk*&Lg(kFX`9ZX$K-Vg$*Cz?eL~$jQmRU-Q$r{;xa^Z$?g==S+9s&k zWS!iU#e~_!e!`Z|=aKUe+j}|DZ_2^&Y8dtmb0bKB3DRwBQH=>pKzy{imJGnHT*`L( z&EE?e{RZX2qHj0EjxJ5;95-!8OAbB?^<@4Olu5y1Zz#L%pGJzH@&?InA^ai^yf%zw zDc#qKp^t9Nw$(TS+Qmb^K9>{K3d8v84e%~|)e7juzMjOXsDpD!C6Lp;*~6ciE&9~o zL^Rc9u$)Xc@AYLnDsMbs#$mJZ>+$T1!}HU{l1cUBpI+d*0nYaQ0-n1kFpt8ufqo)W zT%@_|Nsdtn72;3+X#)Fa;@xi&j!3BX+9+N5r$)NkRe*d2z{vsTr4Gi&L9$H6vC0Rl zHw75*ET^@_F0x%M=XRFSK7qc8Grm`AXK&{&7*s3$DvVZAKQj%lSpR9MYVLN>Rx9Es zs`x4`RiPDOZ;Iw>X=g3_B|6vWz94s9XLbUS0>>W{vXZ=7&t3c4IqSUsLUTEe?}8wb zCt{18Nk&VAK=!&qpo#ECj#5f4pA#E{dPfUe0^W{-vhEQmrR<(xS3gCD zC%`L+DB%6!LZ&neDJclWByV5y+?YTA(P;@FR4DB5JClC>$>ip#Ea>x>HPwJUh7VfA zc$aXDc9~go#k4yLEZApx9|*xqYb(Gd^s%)J_VeTJ29 zWM&N~67=>Cd0#}zArAUQ$2Q$-6TSV}HS>$E;@msRB2=wY*7^9{L)==O2Vo#YUZ!K# z0U@bQ#>XF#vyy+k*(R&P!@njijf2jb&}!kjY|%1N;RIRnF5?Tt!k`|u--f_cPizVq zW6vUjRihP|$^Ejl9RPHA?Ofv&1wdpEIbF0?G6(&x55 zV9a|SM!WqD1kEqb-BW7@5wiU3P9u#xpyVWwhg0t8EmGmQS*7By4XXP#<94$+w}&si z_|uu)Hz)ks<`yR^y^}1fYj*h^BN_-9SCvWO5y9kz# z@Rd|oK|m~y$g69+2+d$BQbt05q43pvk#wbZi^n*!lD4|z>!`cI^4jLn0nQ6N#M+%l zf1Pd^?QSiS#0%Igv-x;AR2MA2x34lO9*XZ)e#kT6_C1RB+-}wkn72tP z-i_>^pY`|F>Gpm_u@<-!b8>|dqbfW?HxOsAmW8Wxza#xYKnda880uW!_h#N!Y&#JY zzhO8&$N*k1SZr?Jcio)0@tzobHvNtDqaCM`G2k-XwP{Vm0cfu|t>lE4mdrPCY8h-5 zwBxt1pVmEzs8*Nh9JH)9_qv}9BL18E5416%J6Y-bC)Up3mJh#If4%Md3My@dZ?Pfn zr%S_C>Qs}bdbqgq>mRxRr`DJAw%0p0TW~w8d9?GX*v@5gz{n=_W1)p5*B;%AtngYk za|a1@a|`brWfqW{El-#rxyeuQAYBnUDPE}IEZ<%YfmD5O#n99vmd3g+84~mDj*;BJ z)4h4@=+h90#*z#1a}kcSBP4&cGF0=V>42mEoFp7uCoYL|HD>P533S?fS3rExMyQdcd zovAAg4^XSodlfV+E&+STd*b#l!v~$c?~acm+2}^xP{8ed!?ra*x<&vjMDHUssw1S< zRJ$eY57PfmK*PjI5B~u}puTLBm+fU|ZSLh^eL2Q8syeO=L40Y0hl2+I2m$c_d4v|A z=#>$KZUg|V5Fq`h;6(#?VPX8&a<=#Md`VFME&7}C@z3dhiMU>@{txEI-zI;fH~ww1 z{4NA#~X@A}t!|Nj|+ lzs>)?x_^xS^--&H{`(@|D None: m2_task = m.coalition['blue'].country("Combined Joint Task Forces Blue").plane_group[3].points[0].tasks[5] self.assertEqual(task, m2_task) + + def test_big_formation_action_leader(self) -> None: + m_name = "tests/missions/big-formation.miz" + m = dcs.mission.Mission() + m.load_file(m_name) + + assert isinstance(m.coalition['blue'].country("Combined Joint Task Forces Blue") + .plane_group[0].points[0].tasks[5], WWIIFollowBigFormation) + + task = m.coalition['blue'].country("Combined Joint Task Forces Blue").plane_group[0].points[0].tasks[5] + + self.assertNotIn("groupId", task.params) + self.assertNotIn("lastWptIndex", task.params) + self.assertEqual(task.params["formationType"], WWIIFollowBigFormation.FormationType.COMBAT_BOX_FOR_OPEN_FORMATION) + self.assertEqual(task.params["pos"], {"x": 0, "y": 0, "z": 0}) + self.assertTrue(task.params["lastWptIndexFlagChangedManually"]) + self.assertEqual(len(task.params), 7) + + m2_name = "missions/saved_big-formation.miz" + m.save(m2_name) + + m2 = dcs.mission.Mission() + m2.load_file(m2_name) + + assert isinstance(m2.coalition['blue'].country("Combined Joint Task Forces Blue") + .plane_group[0].points[0].tasks[5], WWIIFollowBigFormation) + m2_task = m.coalition['blue'].country("Combined Joint Task Forces Blue").plane_group[0].points[0].tasks[5] + + self.assertEqual(task, m2_task) + + def test_big_formation_action_left(self) -> None: + m_name = "tests/missions/big-formation.miz" + m = dcs.mission.Mission() + m.load_file(m_name) + + assert isinstance(m.coalition['blue'].country("Combined Joint Task Forces Blue") + .plane_group[1].points[0].tasks[5], WWIIFollowBigFormation) + task = m.coalition['blue'].country("Combined Joint Task Forces Blue").plane_group[1].points[0].tasks[5] + + self.assertEqual(task.params["formationType"], WWIIFollowBigFormation.FormationType.JAVELIN_DOWN) + self.assertEqual(task.params["pos"], {"x": -480, "y": -70, "z": -240}) + self.assertEqual(task.params["groupId"], 2) + self.assertEqual(task.params["posInGroup"], 2) + self.assertEqual(task.params["lastWptIndex"], 3) + self.assertTrue(task.params["lastWptIndexFlag"]) + self.assertEqual(len(task.params), 9) + + m2_name = "missions/saved_big-formation.miz" + m.save(m2_name) + + m2 = dcs.mission.Mission() + m2.load_file(m2_name) + + assert isinstance(m2.coalition['blue'].country("Combined Joint Task Forces Blue") + .plane_group[1].points[0].tasks[5], WWIIFollowBigFormation) + m2_task = m.coalition['blue'].country("Combined Joint Task Forces Blue").plane_group[1].points[0].tasks[5] + + self.assertEqual(task, m2_task) + + def test_big_formation_action_back(self) -> None: + m_name = "tests/missions/big-formation.miz" + m = dcs.mission.Mission() + m.load_file(m_name) + + assert isinstance(m.coalition['blue'].country("Combined Joint Task Forces Blue") + .plane_group[2].points[0].tasks[5], WWIIFollowBigFormation) + task = m.coalition['blue'].country("Combined Joint Task Forces Blue").plane_group[2].points[0].tasks[5] + + self.assertEqual(task.params["formationType"], WWIIFollowBigFormation.FormationType.COMBAT_BOX) + self.assertEqual(task.params["pos"], {"x": -320, "y": -50, "z": -0}) + self.assertEqual(task.params["groupId"], 2) + self.assertEqual(task.params["posInBox"], 3) + self.assertEqual(task.params["lastWptIndex"], 3) + self.assertFalse(task.params["lastWptIndexFlag"]) + self.assertEqual(len(task.params), 9) + + m2_name = "missions/saved_big-formation.miz" + m.save(m2_name) + + m2 = dcs.mission.Mission() + m2.load_file(m2_name) + + assert isinstance(m2.coalition['blue'].country("Combined Joint Task Forces Blue") + .plane_group[2].points[0].tasks[5], WWIIFollowBigFormation) + m2_task = m.coalition['blue'].country("Combined Joint Task Forces Blue").plane_group[2].points[0].tasks[5] + + self.assertEqual(task, m2_task) + + def test_big_formation_action_right(self) -> None: + m_name = "tests/missions/big-formation.miz" + m = dcs.mission.Mission() + m.load_file(m_name) + + assert isinstance(m.coalition['blue'].country("Combined Joint Task Forces Blue") + .plane_group[3].points[0].tasks[5], WWIIFollowBigFormation) + task = m.coalition['blue'].country("Combined Joint Task Forces Blue").plane_group[3].points[0].tasks[5] + + self.assertEqual(task.params["formationType"], WWIIFollowBigFormation.FormationType.COMBAT_BOX_FOR_OPEN_FORMATION) + self.assertEqual(task.params["pos"], {"x": -160, "y": 50, "z": 240}) + self.assertEqual(task.params["groupId"], 2) + self.assertEqual(task.params["posInBox"], 1) + self.assertEqual(task.params["lastWptIndex"], 3) + self.assertTrue(task.params["lastWptIndexFlag"]) + self.assertEqual(len(task.params), 9) + + m2_name = "missions/saved_big-formation.miz" + m.save(m2_name) + + m2 = dcs.mission.Mission() + m2.load_file(m2_name) + + assert isinstance(m2.coalition['blue'].country("Combined Joint Task Forces Blue") + .plane_group[3].points[0].tasks[5], WWIIFollowBigFormation) + m2_task = m.coalition['blue'].country("Combined Joint Task Forces Blue").plane_group[3].points[0].tasks[5] + + self.assertEqual(task, m2_task) + + def test_action_a_out_picture(self) -> None: + mizname = "tests/missions/a_out_picture.miz" + m = dcs.mission.Mission() + m.load_file(mizname) + + assert isinstance(m.triggerrules.triggers[0].actions[0], PictureToAll) + m_action = m.triggerrules.triggers[0].actions[0] + + self.assertEqual(m_action.seconds, 10) + self.assertFalse(m_action.clearview) + self.assertEqual(m_action.start_delay, 3) + self.assertEqual(m_action.horz_alignment, PictureAction.HorzAlignment.Left) + self.assertEqual(m_action.vert_alignment, PictureAction.VertAlignment.Top) + self.assertEqual(m_action.size, 100) + self.assertEqual(m_action.size_units, PictureAction.SizeUnits.OriginalSize) + + m2_name = "missions/saved_a_out_picture.miz" + m.save(m2_name) + + m2 = dcs.mission.Mission() + m2.load_file(m2_name) + + self.assertEqual(m_action, m2.triggerrules.triggers[0].actions[0]) + + def test_action_a_out_picture_s(self) -> None: + mizname = "tests/missions/a_out_picture.miz" + m = dcs.mission.Mission() + m.load_file(mizname) + + assert isinstance(m.triggerrules.triggers[0].actions[1], PictureToCoalition) + m_action = m.triggerrules.triggers[0].actions[1] + + self.assertEqual(m_action.coalition, "blue") + + m2_name = "missions/saved_a_out_picture.miz" + m.save(m2_name) + + m2 = dcs.mission.Mission() + m2.load_file(m2_name) + + self.assertEqual(m_action, m2.triggerrules.triggers[0].actions[1]) + + def test_action_a_out_picture_c(self) -> None: + mizname = "tests/missions/a_out_picture.miz" + m = dcs.mission.Mission() + m.load_file(mizname) + + assert isinstance(m.triggerrules.triggers[0].actions[2], PictureToCountry) + m_action = m.triggerrules.triggers[0].actions[2] + + self.assertEqual(m_action.country, dcs.countries.get_by_name("Ukraine")) + + m2_name = "missions/saved_a_out_picture.miz" + m.save(m2_name) + + m2 = dcs.mission.Mission() + m2.load_file(m2_name) + + self.assertEqual(m_action, m2.triggerrules.triggers[0].actions[2]) + + def test_action_a_out_picture_g(self) -> None: + mizname = "tests/missions/a_out_picture.miz" + m = dcs.mission.Mission() + m.load_file(mizname) + + assert isinstance(m.triggerrules.triggers[0].actions[3], PictureToGroup) + m_action = m.triggerrules.triggers[0].actions[3] + + self.assertEqual(m_action.group.id, 1) + + m2_name = "missions/saved_a_out_picture.miz" + m.save(m2_name) + + m2 = dcs.mission.Mission() + m2.load_file(m2_name) + + assert isinstance(m2.triggerrules.triggers[0].actions[3], PictureToGroup) + m2_action = m2.triggerrules.triggers[0].actions[3] + + self.assertEqual(m_action.group.id, m2_action.group.id) + + def test_action_a_out_picture_u_no_file(self) -> None: + mizname = "tests/missions/a_out_picture.miz" + m = dcs.mission.Mission() + m.load_file(mizname) + + assert isinstance(m.triggerrules.triggers[0].actions[4], PictureToUnit) + m_action = m.triggerrules.triggers[0].actions[4] + + self.assertEqual(m_action.unit_id, 1) + self.assertEqual(m_action.file_res_key.key, "") + + m2_name = "missions/saved_a_out_picture.miz" + m.save(m2_name) + + m2 = dcs.mission.Mission() + m2.load_file(m2_name) + + self.assertEqual(m_action, m2.triggerrules.triggers[0].actions[4]) + + def test_action_a_out_picture_u(self) -> None: + mizname = "tests/missions/a_out_picture.miz" + m = dcs.mission.Mission() + m.load_file(mizname) + + assert isinstance(m.triggerrules.triggers[0].actions[5], PictureToUnit) + m_action = m.triggerrules.triggers[0].actions[5] + + self.assertEqual(m_action.unit_id, 1) + + m2_name = "missions/saved_a_out_picture.miz" + m.save(m2_name) + + m2 = dcs.mission.Mission() + m2.load_file(m2_name) + + self.assertEqual(m_action, m2.triggerrules.triggers[0].actions[5])