From cefc34e8d8ea31a56c3f89b6a4358d730411e7c6 Mon Sep 17 00:00:00 2001 From: Maxim Lysak Date: Fri, 4 Oct 2024 18:19:40 +0200 Subject: [PATCH] Working on a first version of DOCX native backend Signed-off-by: Maxim Lysak --- docling/backend/msword_backend.py | 361 +++++++++++++++++++++++++++++- examples/run_with_formats.py | 7 +- tests/data/lorem_ipsum.docx | Bin 0 -> 14817 bytes tests/data/word_sample.docx | Bin 413932 -> 403297 bytes 4 files changed, 362 insertions(+), 6 deletions(-) create mode 100644 tests/data/lorem_ipsum.docx diff --git a/docling/backend/msword_backend.py b/docling/backend/msword_backend.py index a1ec3891..2cf5d6ef 100644 --- a/docling/backend/msword_backend.py +++ b/docling/backend/msword_backend.py @@ -2,19 +2,52 @@ from io import BytesIO from pathlib import Path from typing import Set, Union +import docx from docling_core.types.experimental import ( + BasePictureData, + BaseTableData, DescriptionItem, DocItemLabel, DoclingDocument, + GroupLabel, + ImageRef, + PictureItem, + SectionHeaderItem, + TableCell, + TableItem, ) +from lxml import etree from docling.backend.abstract_backend import DeclarativeDocumentBackend from docling.datamodel.base_models import InputFormat class MsWordDocumentBackend(DeclarativeDocumentBackend): + def __init__(self, path_or_stream: Union[BytesIO, Path], document_hash: str): + self.XML_KEY = ( + "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}val" + ) super().__init__(path_or_stream, document_hash) + # self.initialise(path_or_stream) + # Word file: + self.path_or_stream = path_or_stream + # Initialise the parents for the hierarchy + self.max_levels = 10 + self.level_at_new_list = None + self.parents = {} + for i in range(-1, self.max_levels): + self.parents[i] = None + + self.history = { + "names": [None], + "levels": [None], + "numids": [None], + "indents": [None], + } + + def warn(self, message): + print(f"WARN: {message}") def is_valid(self) -> bool: return True @@ -28,11 +61,333 @@ class MsWordDocumentBackend(DeclarativeDocumentBackend): self.path_or_stream = None + def update_history(self, name, level, numid, ilevel): + self.history["names"].append(name) + self.history["levels"].append(level) + + self.history["numids"].append(numid) + self.history["indents"].append(ilevel) + + def prev_name(self): + return self.history["names"][-1] + + def prev_level(self): + return self.history["levels"][-1] + + def prev_numid(self): + return self.history["numids"][-1] + + def prev_indent(self): + return self.history["indents"][-1] + + def get_level(self) -> int: + """Return the first None index.""" + for k, v in self.parents.items(): + if k >= 0 and v == None: + return k + return 0 + @classmethod def supported_formats(cls) -> Set[InputFormat]: return {InputFormat.DOCX} - def convert(self) -> DoclingDocument: - doc = DoclingDocument(description=DescriptionItem(), name="dummy") - doc.add_text(text="I am a Word document.", label=DocItemLabel.TEXT) + def walk_linear(self, body, docx_obj, doc) -> DoclingDocument: + for element in body: + tag_name = etree.QName(element).localname + # Check for Text + if tag_name in ["p"]: + self.add_text(element, docx_obj, doc) + # Check for Tables + elif element.tag.endswith("tbl"): + self.add_table(element, docx_obj, doc) + # Check for Inline Images (drawings or blip elements) + elif element.tag.endswith("drawing") or element.tag.endswith("blip"): + self.add_figure(element, docx_obj, doc) + else: + self.warn(f"ignoring element in DOCX with tag: {tag_name}") + return doc + + def get_numId_and_ilvl(self, paragraph): + # Access the XML element of the paragraph + numPr = paragraph._element.find( + ".//w:numPr", namespaces=paragraph._element.nsmap + ) + + if numPr is not None: + # Get the numId element and extract the value + numId_elem = numPr.find("w:numId", namespaces=paragraph._element.nsmap) + ilvl_elem = numPr.find("w:ilvl", namespaces=paragraph._element.nsmap) + + numId = numId_elem.get(self.XML_KEY) if numId_elem is not None else None + ilvl = ilvl_elem.get(self.XML_KEY) if ilvl_elem is not None else None + + return int(numId), int(ilvl) + + return None, None # If the paragraph is not part of a list + + def get_label_and_level(self, paragraph): + if paragraph.style is None: + return "Normal", None + label = paragraph.style.name + if ":" in label: + parts = label.split(":") + + if len(parts) == 2: + return parts[0], int(parts[1]) + + parts = label.split(" ") + + if "Heading" in label and len(parts) == 2: + return parts[0], int(parts[1]) + else: + return label, None + + def add_text(self, element, docx_obj, doc): + paragraph = docx.text.paragraph.Paragraph(element, docx_obj) + + if paragraph.text is None: + # self.warn(f"paragraph has text==None") + return + + text = paragraph.text.strip() + + # if len(text)==0: # keep empty paragraphs, they seperate adjacent lists! + # self.warn(f"paragraph has len(text)==0") + + pname, plevel = self.get_label_and_level(paragraph) + numid, ilevel = self.get_numId_and_ilvl(paragraph) + + # we detected a list + if numid is not None and ilevel is not None: + self.add_listitem( + element, docx_obj, doc, pname, plevel, numid, ilevel, text + ) + self.update_history(pname, plevel, numid, ilevel) + + return + + elif numid is None and self.prev_numid() is not None: # Close list + + for key, val in self.parents.items(): + if key >= self.level_at_new_list: + self.parents[key] = None + + self.level = self.level_at_new_list - 1 + self.level_at_new_list = None + + if pname in ["Title"]: + + for key, val in self.parents.items(): + self.parents[key] = None + + self.parents[0] = doc.add_text( + parent=None, label=DocItemLabel.TITLE, text=text + ) + + elif "Heading" in pname: + self.add_header(element, docx_obj, doc, pname, plevel, text) + + elif pname in [ + "Paragraph", + "Normal", + "Subtitle", + "Author", + "Default Text", + "List Paragraph", + "List Bullet", + "Quote", + ]: + level = self.get_level() + doc.add_text( + label=DocItemLabel.PARAGRAPH, parent=self.parents[level - 1], text=text + ) + + else: + assert False, f"need to add a new paragraph: {pname}" + + self.update_history(pname, plevel, numid, ilevel) + + def add_header(self, element, docx_obj, doc, curr_name, curr_level, text: str): + + level = self.get_level() + # print(f"level: {level} => add_header(self, element, docx_obj, doc, {curr_name}, {curr_level}): {text}") + + if isinstance(curr_level, int): + + if curr_level == level: + + self.parents[level] = doc.add_heading( + parent=self.parents[level - 1], text=text + ) + + elif curr_level > level: + + # add invisible group + for i in range(level, curr_level): + self.parents[i] = doc.add_group( + parent=self.parents[i - 1], + label=GroupLabel.SECTION, + name=f"header-{i}", + ) + + self.parents[curr_level] = doc.add_heading( + parent=self.parents[curr_level - 1], text=text + ) + + elif curr_level < level: + + # remove the tail + for key, val in self.parents.items(): + if key >= curr_level: + self.parents[key] = None + + self.parents[curr_level] = doc.add_heading( + parent=self.parents[curr_level - 1], text=text + ) + + else: + self.parents[self.level] = doc.add_heading( + parent=self.parents[self.level - 1], text=text + ) + + def add_listitem( + self, element, docx_obj, doc, pname, plevel, numid, ilevel, text: str + ): + + level = self.get_level() + # print(f"level: {level} => add_listitem(self, element, docx_obj, doc, {pname}, {plevel}, {numid}, {ilevel}): {text}") + + if self.prev_numid() is None: # Open new list + + self.level_at_new_list = level + + self.parents[level] = doc.add_group( + label=GroupLabel.LIST, name="list", parent=self.parents[level - 1] + ) + + doc.add_text( + label=DocItemLabel.LIST_ITEM, parent=self.parents[level], text=text + ) + + elif ( + self.prev_numid() == numid and self.prev_indent() < ilevel + ): # Open indented list + + for i in range( + self.level_at_new_list + self.prev_indent() + 1, + self.level_at_new_list + ilevel + 1, + ): + self.parents[i] = doc.add_group( + label=GroupLabel.LIST, name="list", parent=self.parents[i - 1] + ) + + doc.add_text( + label=DocItemLabel.LIST_ITEM, + parent=self.parents[self.level_at_new_list + ilevel], + text=text, + ) + + elif self.prev_numid() == numid and ilevel < self.prev_indent(): # Close list + + for k, v in self.parents.items(): + if k > self.level_at_new_list + ilevel: + self.parents[k] = None + + doc.add_text( + label=DocItemLabel.LIST_ITEM, + parent=self.parents[self.level_at_new_list + ilevel], + text=text, + ) + + elif self.prev_numid() == numid or self.prev_indent() == ilevel: + + doc.add_text( + label=DocItemLabel.LIST_ITEM, parent=self.parents[level - 1], text=text + ) + + def add_table(self, element, docx_obj, doc): + + # Function to check if a cell has a colspan (gridSpan) + def get_colspan(cell): + grid_span = cell._element.xpath("@w:gridSpan") + if grid_span: + return int(grid_span[0]) # Return the number of columns spanned + return 1 # Default is 1 (no colspan) + + # Function to check if a cell has a rowspan (vMerge) + def get_rowspan(cell): + v_merge = cell._element.xpath("@w:vMerge") + if v_merge: + return v_merge[ + 0 + ] # 'restart' indicates the beginning of a rowspan, others are continuation + return 1 + + table = docx.table.Table(element, docx_obj) + + num_rows = len(table.rows) + num_cols = 0 + for row in table.rows: + # Calculate the max number of columns + num_cols = max(num_cols, sum(get_colspan(cell) for cell in row.cells)) + + self.warn(f"table: [{num_rows}x{num_cols}]") + + # Initialize the table grid + table_grid = [[None for _ in range(num_cols)] for _ in range(num_rows)] + + data = BaseTableData(num_rows=num_rows, num_cols=num_cols, table_cells=[]) + + for row_idx, row in enumerate(table.rows): + col_idx = 0 + for c, cell in enumerate(row.cells): + row_span = get_rowspan(cell) + col_span = get_colspan(cell) + + # Find the next available column in the grid + while table_grid[row_idx][col_idx] is not None: + col_idx += 1 + + print(f"{row_idx}, {col_idx}, {row_span}, {col_span}") + + # Fill the grid with the cell value, considering rowspan and colspan + for i in range(row_span if row_span == "restart" else 1): + for j in range(col_span): + table_grid[row_idx + i][col_idx + j] = "" + + cell = TableCell( + text=cell.text, + row_span=row_span, + col_span=col_span, + start_row_offset_idx=row_idx, + end_row_offset_idx=row_idx + row_span, + start_col_offset_idx=col_idx, + end_col_offset_idx=col_idx + col_span, + col_header=False, # col_header, + row_header=False, # ((not col_header) and html_cell.name=='th') + ) + + # print(row_idx, "\t", col_idx, "\t", row_span, "\t", col_span, "\t", text) + data.table_cells.append(cell) + + level = self.get_level() + doc.add_table(data=data, parent=self.parents[level - 1]) + + def add_figure(self, element, docx_obj, doc): + doc.add_picture( + data=BasePictureData(), parent=self.parents[self.level], caption=None + ) + + def convert(self) -> DoclingDocument: + # Parses the DOCX into a structured document model. + doc = DoclingDocument(description=DescriptionItem(), name="dummy") + docx_obj = None + try: + docx_obj = docx.Document(self.path_or_stream) + except Exception: + return doc + + # self.initialise() + doc = self.walk_linear(docx_obj.element.body, docx_obj, doc) + return doc diff --git a/examples/run_with_formats.py b/examples/run_with_formats.py index df76ebe7..4d0f0be3 100644 --- a/examples/run_with_formats.py +++ b/examples/run_with_formats.py @@ -13,10 +13,11 @@ from docling.pipeline.simple_model_pipeline import SimpleModelPipeline from docling.pipeline.standard_pdf_model_pipeline import StandardPdfModelPipeline input_paths = [ - Path("tests/data/wiki_duck.html"), + # Path("tests/data/wiki_duck.html"), Path("tests/data/word_sample.docx"), - Path("tests/data/powerpoint_sample.pptx"), - Path("tests/data/2206.01062.pdf"), + Path("tests/data/lorem_ipsum.docx"), + # Path("tests/data/powerpoint_sample.pptx"), + # Path("tests/data/2206.01062.pdf"), ] input = DocumentConversionInput.from_paths(input_paths) diff --git a/tests/data/lorem_ipsum.docx b/tests/data/lorem_ipsum.docx new file mode 100644 index 0000000000000000000000000000000000000000..da47be3a76d688b2d384047b8a39e04e6415165f GIT binary patch literal 14817 zcmeHubyQ?a@@4_uxHaxH?yilyL*wr5-nhFvH10I+QnIDwX-jnw0O0dS000>P392DzW9?{U z?Wm*ZYHQ@6MeAZ^`8oFkD0wyj^!@w)J^lxeKwZL!bvHet@Ll2~LM%{8|5t7aC1^NL z5{>);1cp1P@=M%6>uWnQsGJf=EVLyd3Dey=lXAcR)N-mN)Ter9k|T8PB;R;#Gd8NF zg&i7iLrl`m1p0OUAyywt=GHb$DOM1AqWYe=F$L(a>3Qk?sH*pXD9XfWWn#BTCcJ=W zG^UNawso-Y>m;@mU+W>T;kC1oVB%{QSUj!82r&$o9A;Ea5~Tuk>rg@uJq~8G5AyMYDZ+?NSJmEx@wxfp3h&d*&9O~z{E z60ul=iZunxalM_`TU<^L%OAJ91~JRq=Ivjvv@9Pt+W;^e%y?_1iOri#K-^em^WhHe ztvp%Xg8=|TmR~F3|USGHt7eTcS^h8IdXW}Q_9MVO; zZ6s)&VpQ?UWYolD(L+QyAvv&BZj_AxgM~+k1^6yr)%+Fy&I-~pC94$xm2)F0Kg?K0PyL3P@HY-4e1PR48B>t z+pXUWR`c@48OfXw9AWY9HU>?HtL0u0;R0f8tN4!w zFZAqEOzwbwPPb*`2~2IrGG`#Jl<_e}2k9zB&VMix)A_Qx#h5=tF+FD_HlvWgYa~Xt ztC)$_SRx!4tWh9oeXevCM6%Ga^a$r;VZ9@QHthkjXZlI6vCONbljv9ia+legrF*VQ zv5EYLtB@QUcWJ58;v4A+*@B9f_q`aWkX@!)atmIVi2^g}>D+$rxJ?IK_f{_JY%U*; z(%i98#%xY23LL`Sr=4?A5cULN%{#^DiTvd=@s;wgf-o*oPXx|Jo7`^(y%)bCERlqk z?V?}?So6q8C>vQkfib+g8uHZIH|$!F^0w@bJS&G#d*{BY6byB0Mz} z+=4Q3%CnnFYd<1Z?{-FCXr=fX$Ya5kTy9?R05Z5mHqnGv|!8=Ac&H%pkvO zOdhpyfJZ|ceo@`QdnhJ7=#BwQC08KNtZK>F-T+&9Fme+5YZwo*GV8CbGJ+T>tZ=BM z7GB*mn1dKBxp`2C&3Y76s(?eLOojjnq6N6p9b^2A&QH$DAK0MNFq0)=g#ACO_M}Ro z2#oC2qQXWo4?%^qm(dIhG$R^~4np_oGKAZF!c1?LpPRZBh=B^jLx&qX7TsrG%xwt5 z=Kq0NGHe7e@yqbuM9Y=?+|ANYpvNq#>(sD8VQ}18-wPsN1aTZc*f!F%W0ZBm%sZIQ z3GCL7VshdRz~)&8yQR|ogfyI2rb#McU0udf1Mxj9=wrUwx&RZ)_OI74MjUPhKmcMDvJh< zq{Sa7Na^}my7u!iAxdRr>fVciV5==IN_58!RW!KJI$~dC=Hljv{`n#;J}a@EAE<>cj4(h>YkQoW4jjh z*&ZGB`j~a$%pLwK@95K@a1f|v(FP^IT?9>bmLjukL=#%`_Y@1*3b2MqIa5kwB~=9l zNdix2fwE#KOKAA^#s;v_PHZ>C={|GSgd{AMDS9NF5PpAd9q$IEJr~q~&MQEo_~GVk zt^!bW>`HlTgdD6Y_Yhw(e+g&s za}jYh(9qJ!o^E<#OT(sb(6RwD>HI$)+?X}S&(2;s7->X~TBe?MVZ!5wZY&*N`Wbb!WllVa7NJ|>2ZKwk*ckU@9yNm$+@>{A$+t~rWk;+q3l9b& z2-%yQ42UQHC}n<7$AW&4!8)|8J}c5JX~4$a;Wu4GkZxM>;Y2yPR$vQL=fyBU=l9pV ze%<|HGC{-E-RHt_>G&1Js(F%tPOsYr3iAP@CdSnqX$b*U+`y}{gtPd2YqHW{1%2x>eGH8{x9pJ{u8%LuQj*Zm*%n~ zO^WMw0nd>ScN`}~@*HyXvH&+6JoQ& z6T)ayED*^8H<@UN}SID{istlahHHiu?oRw*t zU3z3Kp))si>#36)u@x+c;1alzwGr(vL$152mRh2eG-nEzlk+SQH8yYjfzO%jAsOMe z-_vIK@&cw01TeaZv2S|cx;MN;#PqH@Qt}B+3&@6D?q0yKGiJu!e>$u_&t*v9gkR9| z!3U7z3De3vyqu#+J)YKUXyj!ax^TmuY1*~vtRn<2yvlA*&(BxD*jRdc(X&V^R@&b%(aQlmg>|7aZR?%U3oQHiN7u-KLK8Oxbd zWhpw<>sbS}1}S>l@Z7%HHZAC4^>q5}md*05_IAztKT@Z8!&NcO-S0p=3_^_@_bcH!b%(@q5585OCil}s7pmZt5t32gLv{11)!llHB z)z#3}w#=L~myw*k@fFHtm!D(^u1_%Jz+pDx$(E#xjP~DS?pFr4(*721pSbVLD1#}R zN#9qYjOcvB5@HT}kKbUEy1wDhW&_5-qd>rG`xY^Jz%HSRt6}&to?cQYW?xuYGHen* z+<>uAmb#=fudldMFSE2mt0r@X_O$`O|Ewz6p;2u*=OT)#4Tv0_^^2U~E05d5dlcy3 z3Ac&QbKN*N05J9$06=|LhTpZu(bUMwi0=26;WyHKtTq;o&4$u}{>U5B#EBQ(@!iFr zw^rIIp5!QhhkWHSVm@{1^H2)|foz-tU7&!v8^!g!AO#%r=#tN^XUbe)_~ytT99JaVg+8N0RdDnN;8M&D#!M~_mF2hJ`#D2_ zk;T;Ee3=Nygr5T21b{ZhfYA)hdCS<{ncL9_2}N0oSZBW_*-QEkjn3GQ;+KD1YhNfz zn15vP39-`b$l@(DbwyFUN0M7jmx){U|YdS zq7zS8;8S0;=Q=H9FICsNfm)R_)YvX?5_lFG_YxgicaPxO{-Az&ORUYxHq7Rd*I0}N zh7-^>^XArVz<|OcebQ#62eF+#b;xK6Y%w1vS`>Cr{ZDxmIFg#2XbJv!dknrX5WV!d znocd+#l&EhTW&|u4eYD@^h6nskq^q>x4`a`H&yG>vE@tSeOo;)wvI2ZY6m(pxLxgU z@6oHGU-(paZgqD|cD3K`Z+`yt26=tF310ZxQN8Vo_I9{Wr}OeU&{2#IUT%}s=JtBL z>#XzgFrxs|I<`R$gTIAnXA6_z$H|-kQzzvka(qG@1k$S(>a^p4!B1kqe#u8*5RshU}kK#bqSZhX_MP(lPY7qE!d{1o^7xJs6 zgEL#}YSsYbX|=Qw8z1A%iPmoVlsRrB4x{?(H?R!&X*sZ{ZSv^I3{S|*`$sDW*U%a z?%>`^o4nbJN}ot2wC8a|dwl6rEa zd9SA8;pYO2>(fI`YEzjpZ7F8UAViVzG^mIUSUIhGT@wA>o=F(g7bFq=MVDr6Z}$5)LD)|B_P)4t8*Wj zq&t_A@oDEYc|cg*&+>{Vqhivyb#?AGNUhQZ8XcX63P|!LAVF-(D6w2aOi?Ar1VN69 z69IK98X8;y&-cJrbvI!=89<4}g*k~HagTJ+wa^1atd8qlH+P1Kl*3Y{k*jpyjXsxE z%wRy8I3aS7FBcbU3*F+v*lYnfw^5iC)=hu#dA$T7c9XA=F--a}w@QTsivb2Oz4&>F z7{5pLaGO$re@m3cggPn6>-#7Y6Rlee1e6p4$q_;|A1oryuH*Yj(Y`D7EZCyJCzSIFoRE;*c1`S%16vgGi37P4d` zKhF9sk!E#k;cYnCW?_O*utqMqnjtRVqkWc)Q4Z#rF{PA~U44;u`)T*A=6#rAU#aQQ zFMPAbW)t}Mr!f;%5?AeAl;Ue?O%+YU-&_lOpYS0u%?}L0S^5?QXiiv)wRHJoQmk=P zT}^t0v%u5jO5sD4w2Cz}=zs^mR7JeLDwjGCHvXXWuBTtrYDc{`le*fZ>8uKCegl+hPmX#K1ZuON%F;f=;T|g=rlPYq~x68sqb_3SF{o5yJqjB z7tcn@`pO71)%<37T64XZ*Y=&=jt&S_^*y~YZ03L zzcz5$6dv!(hLAtii9JyMhz+`49;i_?t0~+uMLkQExll2?66sa&Vrpj5bUAl7+?u*@ z%KL8K{@nngDegOCd;kClVgD3yaxijqG_y8w_|5p$DX&;>vm$!ZO?uN`Yl@;vh7pz3 z+U_(C5uTzQp?Llv9wzM$=aaW<6@F_Il&D+n*XnH<3>O+p`ND)V4tuk?4U?B=LXG;# zV=oZhm#w=M1$8qmoi2n_T=!);6))e$T4j zn(?Q~E*eult&sm0pZXYBv-EP{tw)@}JJa5H&CiR<-fzt1;rSPWO{L$#Uuqhb_+ zNcF6wDMc3YTd%v+I~vbUq%d*~untz-k4Oq3{I>NZk@l9y?n{7Gj<|grtF08dLLiJk zo24_E;kPOmNtgcY*xX);E)a%8P+|{ToDM>c`*y(37c?5w?kf)tp1SZRrH8@3N8resMv0#EErf~hFTmZ?PQfXe70j-NDb3(TE*6=c8O^s>ouW?M2M8ByITc zm6vCGgrIPy?Q=#@HcI>)vMD{!%7)GO;u=un(fmmr#tCTC5OajjDXww$YWL8Mz+bSs z6^{6rjYWNFnyKRyi{;3dJEH4_ogqM~#}!Fh7(*Q0&BYx`-CeqIi^3Qg=gP$$IGRTc zgPc36=$$li5=S1xX#eZyE2T^=y3QvA^u7> z+c{GL+}rTJZuU|kSDVw`#(2@0KCaeOCuua&+puXT96s}ojYn__&6{KbyAgWGpvDaGoGP=@S!A^-poKLCLD zw}0?x2S-;+qu&>iW3BhFwa7oh)+kv{_&A}2!b2tG6ygoa74^6z32YOBy5xkQAhZB= z`F5}UAebc#L~hfmFpCi-G^nZxO_{8I$L-tgiLWDrPs20RQd?JD=fOR`0|vZM-S@8^ z=ewtmV+Wlh_Gl2)68c^|E_+KG`&sYNYkd5Pn&&TDDP(}HW6Ogq1T@!n4o>#L=Z`uy z$H9hu2GtIk`I1TDl?N|faRmrRbJ)CU6{>jS-Q=TL2vP6|WME+NPW<9~SCji^NZxHb zb`{46@_10a#N%k2lvI;=E!o_pW>pf%StcnM*NoFHl4$)TqqeXvdC(ge5Vjuxq&(i;dg)jZV0vl;P+&OY`Mps7SWy}#=727&k9N$Ij|6XG zS6IquJ6)g@itR#pjEk7hg0)T}eBB0E-{Y+lzS@#M4dIw=qYa>06Q4P^@SK zr;f*j(*wb(gKMcf1_kCD9SC@tPcLd)8y*;8ySscXFMJED7he*E_x*|5D4uFp>1i7@ zhh(fQ!&Ny(ZFZ`9G-PlsNE<@t2VH8^~*5#KB{Kp zC4NGMF(kB&A-?ua4NK^9;i$@7Gvy5kz)pp-uFNC2{|%1d10m+V7LWZw(hrc|k`6x}5K$q?MQ zNHB>(BBCt!_*SvUOb(x{5#$KJ@n-Hb)?URmu_2rp*-y7@bG;7d8TN6beE^L{q~9g< ztQidn|61rVu7LNHK3#plmq)*+-Ksqf>EY0KI#lI?gZNd)R}2Y7BG~xIgFqMwiTx(- z!ECz20*WXc0l%m0O;a54%pO-b9rB1NGMu99waM4-APb8;`8DOY6O38*yi`Je5oQJO zNYidutf^MBxBOJL_X{@f7uI3b-&|W@uEYZGA4?1t+nk(HNiG9~&b*|0o>b?)x)Y_O z7CVo~J7v|(b;sZA8!tX4SD$E-cGWtI+DTEx7R}!b3meXTiCB0ca|DZ&&?Lc&ZI$36 z^i6bmA-NT&j^7162_nr(sW5TPGewmro03thn}=C`H8*heMkxJYi~9pJ1vXU=itD~s zb6kRhf>38}T$%JlQPz6f)DAMQQ{dQmEPm3b*orx1ka5~i%c$o>(U3_F10Z9 zw!V2M8igc-_|25S+Z zt=bT?f($I&hEd%9P#o-xBIw%%XVy#n4}Ww*sHm(^5qEw?Jb7Ief-Zg$A`*~KajM2a zc4GFhN-l4E6SV;aAaKi8!#8t+U&sW~Yj!2*I3Vjtwzl#@ct4a91m58%1=Y|Bk(6*E zRjDu0YfQXuc)iKqeYp^$6znK-Q1Vuk)H0HWSny7%0$K15&0a(ahB)Z>;J@Z`#JdQ` zUecv4Og$oSM4@QHRkDfZGP`|}^^Dm{EHVASk(<^D8e<6#!&gHgm3zZDPA*z@4hd0q zUNj*2ixE0Ho4D}&H8BVT6B9Zj4C+t7N2h{(&QU-2A1mEh@-jgOXb{@u8^b; z7Di%LEZ%GA_~mS8(X*7V+(Qaz-X+sVkzJEKXS}S5KEmWvL5Bv*v5!ugkra&{s@4!Uj>h_Q{fc$(BQFmWMP#)ofGY`>GYH#i_I=^s&uv{GC z+=6BKP)LZ4%sV;X9!XAD|A;{c)qjdLzJwtC|(@L0o zSSuk>a&*iwHZRM5G^+XM8gXHbq{vdA1;rK2FXqUZ$$d z1lZ}&nwy;tk|U69(pM(Kvdg?F`cq(MKotME{8DQx*p?LA0uXLN8#o=0BQss z!-SL_6vb-t9HXS2LdN-r;eDf&&qI8|l_&Ag%d^`g>-@-Rr%DDWJK?8Xzvu?@!JrCc z2QC{Fyq`j$CUZie=4J;%6HE#OBAVuOf5ea}n#3bhG(96!4B2{r`Jqt;`~&i@?{HL{ zl<&z11d^NP2td}!5`0iEGH+WH{C~j&AQNPLo8n~&pw){IL1`2rebGwV=O(rOe{dXX z{~!08+RNHQDL7$#B4|G}Yt!#|DyEt#{&@(rU&s+z%L&t7s&4)nZks}kpuHU#Oq6Kj z2nJ;$mt2HYzgy>qtD=SE%W?5AqV$Bz^X)nlL5uNDpvd6|z+-g|X;!h{idF~sL43V& zZ00CQckYXIc>6a=TMQiFN3DX9ty~m4cF=w+y&uM0b;&^Cqtq|yTMZamOaV-*Xeky! zwtg#Hc4Oy@@m;PfkB!@0(!)oRAOdNe^N2FXkXF`EO_bdXC?YD;$BXg%o8A@u`4^`77yFJw(gpenI1k|FP}*GdV!XKDDpldCR7&3 z_1BPPx=wswD&w$}SvW*X+>H7mVe3%g0=ZH8U85MySSsQW{R?*Xg(?q5wO)&3h`#&O z=$v1Ho6T-XpG^ctX*E}7ff@!%3j)GVEnF?ll&b3KGgJ2sj~lhR%7!62Km5#Mo0N86 z<>ZMSroLX-2-3rKD%J^CHy(DD66tG&G#;2LC0haSc?k~zwh5Agg&A;EK< ziFEi@>3H_|DE&2>y}>P@$vV8BD5?V?T9(q)vpTO3;g?D$>x0jbzL|&a<*;X`OiNt1 zHdxn%#)HiY)J|FwC3+*wF1809iYPbtM(-hrF^?J7#tz*PNFQ-W{`uYLLvf-*?PK=l z^R<#4e2UT!_qp4t(C3A~ePTGCK?lk}#hZ+SD4C;5CI%LT2mg~-D->>^yP1=lU?nuQMr_H{h1Er| zt(k^pjcD520^3x=p?rSiG!dbMG=KTg=H8P@v%NTf{7%ZWauVKAQrP{`o zvncW7XtZK#t650(M`jUq5Hy}D>Il@Pgc-1@287CzIo9v;2<-73^@jU<0zx1ZB%dUU z{M%7{^MzExEECcZ<@8Cf6D79O;V5|I<{w~s@Nt9 z&l$0lvGq0LyQs@p*Q?St;G}_>dp?u_r;00bi>BZnhs*aQoo;nZmYcoDQ-#&rS=`gI z?I8jcVXBntQ=yS1$}ilCc>_MR0!mh)m}x4%nI)dFsrdjZF;Z6zI=-BNtFZ!qQLRbe z)wuUi=`gj^8;zyTO}zXx7O^RiEfp}2Ka5oyV8>HUt7K-w1Q7TbTTS-gT+vev?dCDS*EGA(xZ!qaZ;zPRz=#4c)f4mk_*4d{G)(M`#OKIUtEbwk#& znkU&=%C>-ZCqfI=cgQH~eFG(b(<0>(=NfyPb(zclz<>Wef=t5Gd>Qv>d$)KN-CBIO zGs1Eq1MxD=sWi1;hOC6`aJ1s}hu1XQz4we8`FWo5!ihWkBH|EywCA^Go5GCxVPK2>THnB?%*;ZQjy4UZA;%e!y??=i%{H`KDd_svug z2mk=(U(Ua?k-oy8!idL-V^J%g5eLo^AK{bEu)T@xi=M}qmZyqimzxaEU{0$56e~$#6}xRs4bsp8IF(+R>|HE$3;Hnj^i-?d zkcTFVGxDM&b~z}DRfeINx{$9JS7^|)_1Vv#e#zLK`0+4k5`L<)60(@6JEf_EhqZu{ zwWit2Gn`Nm`UOLpw&s(N4Ng64?KhN82u+?~Vpf&V3c9xqc!0~!ex{GA=3+ong#Y3f zxs8Gzr3*Ix^CJ_WYK>fohkIZXf)2lm+Mx_Hm~(;rLVZh2(2|Mx(hh2zt}*X&zufe} zth6gef)L6^HsJebXx+Eo+G|1j2ZDP~==ILt`9*!H;}f%p=4o^qDzqzoR>?x)MOhF| zo}fPN*hVa}^>EzVl!en{X}WbA{gvmg7ub_>2e5Hpx7`6g)=`%cEf%Z}SO%Hn@SppU zNwQuw6k?r0q?{1k0`P>`g=Jphrs?yrO!!37723gOTlk9_bNBP1}4cT zIdXboyg_RjCe^IFS3(jdJzp-X7ZAKOk97WHZ24v0QTp{=FNWVYSdspv7sl^N_=k%lrXXSkQfv)9eeVcCf9V!n#Hs1q^Cgl^KG8PS{k&-Y3nR)`|n^tAonT2I=z6 zpNaa{1sJ~3G`TQ%6b3ly@igQL=T1!y!pqdXqN&?h&Z+f$1h^@mbSg+4GLfd}_$KVk z`xLLijzwU9M2R9}RxI&^*qH$wpz3z@>0udsVbo7=-5E5;GO^nmJoLM=8PNoktPu;P zX55~m^Llmp4J(Z?uO9G*y}WCN-lQf{AG7}hrn4fCO<%Z;h86Wnome+A$|gYw=;E7x z(kqgL9b_|b1BST)OQ)iUj#+{It-t}?ZZ!Q03~g|vtBJnEs$c#9Diz@$#$C=6APlalCzIZF^$ z^298Bvt=Z{L`{4$di6*g?D>g|$qpn#k`cKk%&}Oy@a7^g04e?XAGM|M7J@C<_NpbNSSgP!f=YrR`YErvcyZATdp>Xk=!yKPw@fFJ#hs|7foCf=WGtE12Xxm}B*9c|sZ(XJy)O=NyqKV68Yg<A*Tw8dkUo*ofTqRV zRfr7u^a>21Z6ysw@|f=psu@f!d^cMx9fz+Vga!p{1qDDG3i;C_0>EOyO)oSW4)vm~ zKZ9;f`g`BPu#K(Zm2jc)Q6Mo?;nl9Ar3K__qRwzr+8U*7pY(062Z;qW`xfzrRcRd#cwTvWVZw z$$w1z`n!m~Z0|1o_0KmVQ>%YVQx^Dg%uEP8$_&--sS;>#@ U>hW8Z7!086eWitF`|Z>J0y7lJVE_OC literal 0 HcmV?d00001 diff --git a/tests/data/word_sample.docx b/tests/data/word_sample.docx index 62c403febda67f8cfa325add3e6e98d439f18608..a795c38c942101feb8ef17e4dd19831e120546df 100644 GIT binary patch delta 9053 zcmZ8nWmFv7vPOr&-Q6-saCZm}!7aGE2KPY{Tn8E4-Q9x??vfBRc<|sBlJGd^-gnP^ zuX@$$-K%Q%kLq2$>-%<{7LsnykdUY=BO(#N0pNgeaB#G6OcbVa8Srp$8z_w=va~tLah#+b z3imy-GSzV}3ybBd_Rr49u***nIP3L!;JGpzvSu#WpcQdxO|rDa=zb{k?lOi9i$OaL z22Z}hs={N3JpK+T5I3Uh0g4{O3L=h3J$j!lmcu^V`a#aL^Kpw|NMY1!qNNf{Qh1jB zOcQCG!HlH&M?%4J0}c1R&YNH0u+?@kDjdZ*np#90dWv&zskv#x@}$#oXPkz!GBGU*>CT zPu-gLb}%Z0<6Y1O1LSt)Dg2nwUcDeVn~fMZS4gC{Z3TbkYvT1GIdq;GK+uea#DNG# zRCsk}h7Jd(%LfOC`|<&OT-~iWtXwUrs-|4fT!n?P}aQsaBKTkmQXO#8@n|*qzJE>Tn&| z0~ofNpWISSm6nN-TFd?MhX%UuiUwd&Beme(eA7;RO>_eW-d*JGJSTmz$L-zx=Noe# zW#9F^8XP2=82>ir-IH;pDEBfZuO17b+RX!dqsuIg;irrPG*kA)3}$i@#+W*XDyKBU zM15meFg)8*OP;6O<)UCqNfG(GxR5fudOODDMJj0#@*&N#m;kgAQ#d5N<5e(o>U;jw zTAFHnnrk{5Gp{f!xWvpUe;sQpo$5J(CE}9o5Im@M{PmXUCq7Dsqo5wvuY~ zXju=!79_?q*`{(Cq0Hf)lb4N(!wjj~8`zng6TihIr1s8+K@6=gk5`B5WXbewiT+l< zyEouex4~(>tzkpkT#c?;wh!D!R^09Fw~S0w$yaJYdYDXn%fjX}PuoX;3D6T8`^kq~ zb6u0)&fJS-zzPwA`%C^`62`0O+|q z4P7uH43gXS*MBee8D1QRYA->_I+nYY9EVi`0kagH+3D3M0A9t*-X?DOx;3P%7HzOS2;Q#M(B*o z>8$xwaosJxs7hEnXK8I{8J{GzI-n#AL7RGzPoAL6t_z|lPf6ew8jE2CIqDUXr8<|0 zI=`XS%U^S!DNlpYmrUq&dxT3csfM8%Is+7qYy*+U5bKrPkR|}=$KKUrk#N#(X{ko? zjfg0yOyoBHC|Ox(V^e`^O@i5``cW4Wwn;~;C|qn7IvqD};OnJS531?-`B=C6W%?Wf z;+@ntu(BUefPj~FsM<2d()%1YP7M^C>9A+wh`8+V9}T4l9yJ8d0Pi45jZ;93olaVA zHd`9jZyzoeEHdky!;l!hnW$l`xjXqvedBcOv}%l6?aW-qu+B?T3g)=z&PDa9UW+jk zUI3L82pvB2$IEJQAy8hum70w~SABrYg}Kpgy=LRVY6aujMG`X*^6Ae#G)l*TjlflQ zol3iY$i5Yf!T}^V>lY7=KhUSpk5k%Mn0y-$t~s&S83EfZORwwCpKH6Z3f?H_l~k&x z3{Xp_)rP@i8Z^7hqZ@3->DCMcGV%0=uq4D+ht8fS+%^1SX~{2^%BU0 z${e~33Xs90U$#zF;$5Vg8{P(x$JgEi1h8ALF-glxB3U8o,yy1+ey*qCVFkJF4} z_k#-`Eo{@?2BX`fVfbgE4B=In$^@Qa`jh8l=EZg!K5cwR9%GaOzzn5;SG`E z9#8SZqMDCGV$&uj{`1dK2}ez7B8uc&UgO&`tu^r~PEoI8WRL5>LCV+wRjQ1B>e4M2 zEM%}ci!KEB`@WA=W|$5QhpXbC0P=TxC4K@+dNw?|DmED=DH^Aunb8uLSuIMQH(iLd zQ%p@YOv0}Pg{wHw=i}ECxP~yxDqc-yy!{L+dth}{z%Zxg7**43iMy76^YOLv@#q=%+*En}XXh*9LOGZYuY_&6c)NP1!*Vwzq``{IIA?rqAd zF!E?G14__@n^dSJsUZU4XbzUwb=X+Mfn7v=dt&HV*UMg8U!=3iIdn9e!4e*G#mWlC z({0>K7w7D=xY0oC!VZp$!5#4kRBH_r>YBgEvrsv3!1+i#D()Jc>;xN&dF94VC8(x= z(1_*GFOGy&|LVK|m|C*fvzJ!zF)ok>zS3`I2(6qrsYV`Xb!1@HfpsNHzyu6AAkX|> z9ua%MVPdL~F5Z+EG#|wUm396hn{^JR$fub^tyS+6gg2)}8qXV1Z%ZSr)^CkqIp=x6 zD7=uG4#VtMtw}HK(DuMw3d5?2hN{S6jk*4D{@U`DIVD3tKMXBbtom)^SeLvbnjOWv z6ISW+u2E{x>a^J)2WJPo>j3L|f+netMgIr#w^~8{oMJ-C-%slU!`qQDNPN-2m(CI- z7d7LT&sx8IH)+cWel=q=yWQVG?^KAm+!sUAAJEH`e5b?#lQiEys%UM(!9^urM zD+tHujLMNIR?dDT2S|q62;X)VPDWgJ7M_gu5l|Qxo?rGZ*Sm%qUcGM=<-|2%_0~IX z=4A^|<(*C`(W(oycGSh#H21Xwqf$`y-gnQc@gK{(BnX_6RDI~HC;KexBVPIy@+a_>T8o}>c}=mE%}N%^%Bfd5gqStxS4gN3m~Zo%VhtMD zmwoL#MLHL!$6T$5%E)NrK9=Dx@#`kk~qH!Cufrf z*?m&q?R@9eWYzcnB3^IasKHfWjrzW?H-LUvP{VSvQu_y%<+WR@q_m14tjf-3zaMN?v2bG;GNE1hfC`n)?UaaL2TOmN6_-%@93Y;E zUxk)PpSsJr2acdpJvwr~& zR*fr_c#1wX*ObHbVL|DVXJ6OQxQBu2Pa4L~@JMvvL>7eGa6Tw>#o;5iAU?IpMqd>6 z`LNG-Tk29o`J4D3j^IEEmHgzvdRN_`IWP_Qrj^M~u!AIQx1N4U@;6&O^Hwerj2uXmL_cI#^Ww`FALG3{gF4)l>F( z4BlsEA%+Tq9Y6J0)PRGM5f{7VktpUHGnbQ4@W-EF>WJ6e>tHPSxb@|HYC7-zyT0MG zbo;J|y7;H_rZw-dMYTAxM3k_rD_ACFgzo9!Wnw63Vl@hWJgBRC z^6kS>+_=dIV9`Qpy~QFR)50Mxp#SD(Q_2!`7>k=(`h?6_Wve{TM4!b75c*)wgKGhNnlKZX{DsXK}4C8?`c4E8iE7f(n zN?6EjoE=ilI_0>1RndEvfkL$q6iB(Kn#qo=D!y)`3-0aQ_#fbVEU2abN=QQw zqljFJn!A4dDt?VgvuZQ_mXn43gGfFwzTtNE5g{f5+k&Fk=Zh%@YdxRY=3vtY*l88b z9Vy2>9ip>gKI*G+cJVNS)F$*4fh0Ho!Ek?r9^?fJ#;4nqKw?^OF(*#Mx!$Ue z@6}-!A`hS3T&+&b9)YQhPRr=Pt3KPH_LM!;8f>|#n9~i zZY*`a^UOr3?IW|rd!=@dr?1!k1gq)VNh6$=1hZ%K>37pRPwgi`E#_}E${JdD!zb)! z=hszJcW~kG7&9dOWHlMU8CK+8A4%YyniX*Y0k15!gzB_J-w)uVYjXIa9APOveUOd} zZh6=LiJ!lpOA?g;jhZYXfXfQOhUPS^2cCwq@W5N+&u|4CNxg8vB~8*@m2?&ceJ(0H ziQH9J$q^@Hlkp==A@@wCi#+H3+uN-ORD`r(LPN;{-|0t%a3Sp@uyR)EaYd%8y1AK> zDT;4Ntpmd4ZY-*n}HmxC}l(36I$D!mK9ZJ>6(%s}NR*o;CG~4LBB|11xFYgOP-+O}c$HtkkGt2c5|qx>nh}8I(cdZF z46I_$8Hd7RpLwHJ!9|Jau3u|JY5h?I(6Nm9B9;tEed2i9ok@h8 z&mHvk``NA%dfF05lYY|567m6d312@wE_8-?vCQ0s(n=gmfwd4i#l28tsM=CdA0YOL zo|XDt1~qTsuj>VJ?PKHvnSRDEeW#sa^Ke*+U5d;0*;(?H~cWz#+>5$LdJY3@zI_k zQbE4rU@(60Cs@}l&Nw|QCt&yIK9>M3%!rHpb)A&633nCT1g(bZVFc%=uceK>xk0kP zg4p|Vd+uJ?!!GLdqcztMFaL0{1yS^4WIJfi&@G+}w zE!JcVn{~P$X=Iy-j>7BBUFi$1L&0CuB)bNdhb?9Xl}z+zgMYhsV>2gq%xUX~Y_Y7{ zTG@;m*wVg<8A>(xf`ReqKH`xFNh3*HG%EsS18C{@UJ{~(n;EEswq$703!4z%9xEhg zgZN^P00dM2QI`Mv)(cT>~)n>5-pCfNUBGYa{;BI z3e{0D3-;urm3%A1ds`esXXDN8=i5a6`EKO4p+!Q>0X@sxkSINy&VR0QA+7cl(!CJK zs4&CyRdy+FdpvyCB(H;}}s#yYVMG?CHxc0cv5r2GwD|V6zJFz0ftmE{3YH++ZXdF`h*E7H(=5 z@)rw2v<&dF=XVX>qryW0gKW7}!|$J)4yJvwTCs1r5EF_>)8C=nOG8&K5!*AMq1&9i zme_MbdBOvOeWq)&9P44LH-Pedu8*!Ghwp8qA9lC>g(|ysJ;SfH^WzC_s24=FBT$im z9+z^iS{(!wme5zP_P;d*`%S3~34R@vyEfF$hQ_gkxGSXNvwy&OD;IomCjCazIk3T~ zhPYSaH;rgjS{DNut`SI-!)37iD}pfb&2<^gx1Zmhv2VLcCM8-Zkaxd0kOn?6uzlJe z?4*KQErK^fUW3IC!9FN*l0NbMbz$lWX8`e;9vG9);-ZOs3o#XPJ% zJ?&j=J^rG_TJ$zucLZ^QC64}}3|(tLlHlT%^pGc7tK9=u8@g;k{6kfg@@-lZbw9v; zjrjO>ojONV9K)He-?JMJA~&klW^=sqqO`RMQtH6lULqx9NM*w|3%}b8Zbmi|7AnB~ zQPE*XIQ{1QZeB)tj$j=8ph7JX0TiaJY@s%a&|tbk+7 zE@{w`0MnBR*d*TSUMVU?@YrmwhK&_p1H<%?U~!`Pqg*b6Kh6Bcq%ZwMVPe?M*h|#C z92tlRM!B-M7)BJ|M>DA1m}}k#Q{_%-Y%bHqyO-P%+LMg?k;mP6ihRp!w{Qhl_LKP+ zRLV5{I4}F#Fkayz>LUE_$#MZFZzJUS_cDn z_)>T>AC=b=AS8_VM1~$yrjZ5J(mTRBj^?5}UI6cXhPbMQbJ7x!ZkTmY+2*yilY`cDvvSKv1n*jdD^e`c@*MIQ*0mZ6sKubhI z>52(T-1X64ZquUDaC!5z513!gHgJShM$8*(PT{sFZpkj$J`)V{o1hn>7mjaUU7+u9 zt{w4Z`_Xy_j<%Kb*NdB6P$*MQC!33HuIXrQ5}Ik!U`0!0Ju8PskE=6+kJeZ}lPpW$ z6~7_|QKELNF$`N-qp{D6$PpzKe+UK%ApbF9RtcT|hR}yIFpEI*@$wh4fmJK(co>bb z6klKxkD(j7+$3X~=GYU0bYfrzPnQWkDi)LH3?56eQe*2upgc|lXc*n z?p#o!R$=RwPd9gD^PkqY;4TA~Nn$FwW$z6Az>lgc)&AytDxYL2E2RvF^5efln^VRt zcyrX$Xb0%Bu(E=v>BIE}W3uSLp;N_2p2293&&v@oH!kvg898YQ(Q$8lnPk`GKYwI= zov1|1)=tvwtFh|YY@*5`MKcSc(Ld$r(-O4|1VtI$^pd0*Dm78=!2Wy%f)-BjsNNwe zSczOZjB(=KHp&bFY_7$$YD(t)!QVVGyTivMN-HMFHk7oN&UUnaaXP)WFQjJjan~u0 zZf4o?773|B0Q*7ia#nX&M#v^+6LL|kCYO&PMfYs>6FK8UsZ9DsO*O1y8xJY$#o0zr zWrBQx=DtE}iJthp;CE(?1tX^@6H_yi-TEy}{o`0S09AfF>%x?ewXfZqD$+1>o$RcH zrub2bf6(*h8j?L4aK36o+H8Gb)d&LK;RT-8F5B_6;HQZ%@MUPQCz4KG1E-v;65^br z`=W+L5xLR!GfsV1zx^Qg+KOW#(O?usYDvO+f>{KUSSD{|D}YqqO%@LXa^+zigJP*y zP(HM2VO;%5t0`B&T{oNItx^FaUAys~-~Jh0!V zlG61&U6*1`Oax_70pPUTApsKL+sCBe1kgt!!(IEhK(*+UNd$$k9~fp7;t0zc`RR-6amL`)p#Y9u`46E26T;BRgX6&?`P)>~iUwS6$XP z&?J6TZJ7TvLc3H*_n4~@j|?0W?GW4o+Tl7I$5uoG5u9YJT%bdzko~YNsGp{2>&V9- zZ_%xC-*J1%brK2`IS0`Yaz|ipkZ<`T7Gt-DH;q&NQqA`Vm^D zzOfji(=j@092;2@HT){=UC_=@@5QTSc@|L&%L`UFxwf6fMEvB`WdLrn!IN`;?nAX> zWAzqN7YGm1qdMl(L?o<2f6~wc_}$m4R{p4ZcdDR%Kk`N|5w&`_q>w!&$QLHBqglXB z?bRJ4y-ZYzGPN(F(EY-77JAm`XmPWA>L~OzE|254C!EUlRVVIK80tt(WO+;{#yuLw z(Fn$u$RybBo5hosKnMS6k*K=M^xF-M)s+AIRp|li?m>b}lUng%#`H11Al}=b)D1J2 zEZ%1LneZo9q_AI&Ke$5ceq^c%^jT#LYqhX0YbBrJ_&BG7H1C4-7cRM=C~o%HP;GD9 z;Zbv;)R#uYehuv_ZbmPAQJLAIS$nD!qti5qeiKt7b!uJKJqT>7xl8>nQzng}MwYs* ziego%ZKl4qr22GCNznXv;9HaK=x1{fI|#wyRxOj*&Tn2aRcI}p6-_#>E6xXW-EZze z7279GF;VPULU%VzuABPmZV3F_TyCX04COBPGfAhH@V>L?>#y_Ot92u=$h;Al!x8xS z^x}EDO8~;(DFb#cIvc}xuHsXRZ0oaABvs5a`puW@a~dt$YWAC8>}gWhF?neGqYnOi zP+pYQBE4Ez$GH@F-%bY&pK7U5Gq1+uI(}MABZxqf`i#s{r66$B?6(q({o{tu>m9*U z#nBp~hSBTKm+&QN-f{kyWl5P|KBs6#HF2x3wPEV;SdXCJh548Yw;QS)ceOxOBml(3 z95bgZI6ae#I-wrK$l_>e%-P&07`+M500{sou+`x?ru=R}2bv=Rphd`g2knypyut>s zvl@O*;3NcPcoSkI2tscp0J1onm+N{*cm8~IWF1Z?9|G8*ijn{ZggZ;9t0aIFAsYyd zkpxUDo&yh$OR}c3{j#RDDwpXuzuX4p-JFxMUD+xo70X8RTDLqrL_|yg_hNx>%lPlD z99R^C(C|k$zjk7VzxSJrY&t{PRe&XPa6${D0L;+ebO4O@FX(_vL{wd0MP>gND&eAC z5d@%t2ggDFi$Dl+D3=Aw+T&n17UAK^(s++h87w}~1}J6qjVi9D7O*c*KYSA+Gwts9 zcEs`spibrUfT)lt_5)ed^ry!suV_EfDN4F9)YpUx+0!JQT>YxSVJBXKrL<#-vH%qs zGLz5+K#np{EwUjpUhI@ZPK{qJU=xqHT2qbD;fVSWRnqPfvLxk%oVNbYm@-ZBN?bG> zOL~-&XlR6XoFsPqOC?8?|Bcx+8z4jgia`= z4NpCO=pkkf1zw3yhhGVIcbkeQxlfc4+mC2^H%_s8@K2KlxVDo|Q-}KZ_4h@SlH+5C zh!VOT~4K6XO&1GMF>a$Ev$B8#xB; ztNt7;0uZ&9$Cs)4VFf}{Db-~D9Mtm3ccyL8ua~F_qf1_6G zJShg&>;`q!m4>tuxw0{-EeOs4b3`l9s>b3_VYItfhtC4`rLyI-pHgkZA4%8>`7rPM zd+TFWAXAHU1_X*!8~fLy69?2w8o#)dn@?$(`5$4}rl9u}<(G7sI;;6iq??PH0pC)a zklQ4$6%NzS2O3i$@N;_3tfNF+jEF_Up@v{~(S)pN*K?*!w=D8Sg#j`4(4h1|hjK@1 z(c4_)jR2)GT7vG4P~YZ-d{W&E&7X=aHDKv+IQ5MEfXV5B#u6<7?k@bEP=tdahi`%f zd+nj(2Jt-VGU!Y4r(fM>$!*^)pWP+u=JhKqbDAmNk?NY{lm3*fIDB!QBq& z>$254_VOX^v+;G#ar&+E6E@=(D$@CByzD98_YkXAef!O5ZXDoe6ysw(BF z&4eFCCK0C75T}SyihGb}<2G&FW<0`gq`_TR4obO=y6B>)!MKb;g%6D5EK{5-Tl z2|z{h|4-~+me&6Y3Y1qFKu__1$;1CO{&i2pgB~jZ*eU*I!Csc1*9*LPsR8~=un3_Z z$^eE}e-i^Q9xV#ko>z#z}m$M8mtT;P3fS-!T86nO%ACA5#4@1N#>F@4f>lrV2m+aqkfsDz5@ygTB-%I28YQg+2Yti^Ijs*}~fW z1&BdIl>h{E|0!g;;NYAU+`B% zkd83%ikM<5I?ILeX88FBP%9TQ))UxVXOu60$@DsmAp0)&WiL{p!);$gYHOyJOUc`4 z-w7+z$`N&LbZ{{IICy#TfbD>+UQF<07>O>dLKIseXMVtkjYp3{Ab1U^hKY2lfK-$Z zw1F`;Dwsi)=~Fb|nS+ys`a_kSXiuTywlqG7Xg*X2k-5M>Sf>sTy@2q=S<)o~N7?V{ zVzW|4YwzL~g-zrp&CKaptVG2{gZ9wfn{XPn@h3*L*-1G>2FC#|16SgFJs!gPMgJdb z3){j@<*a_1IrTeY3sU)I+PTTQ&KZJPtu+nN2FD$hcpN0a3%j@G6Rp8Uc0=6MM2$aOUp-UkFvIY%cs+H)?< z`gN4uk$cgCUQEF^J^>*c>v%E8lR0>(cZF$R##=p2mFkLK!_X`nM}%et6RVcDh?`MU zfiGKjeIn7HSI@H+ik;ijz4wM0iue%dEqkDhpfFn$8F$LxFIEepr2>T(7?3ulF#N9< zEA=jV%q)E$*+w-tXlJm%{r@%o@b+bNz_r$&F`B{}Djn6nT;au%tRL}|Vz-@-bFT=Wth#CDs)Hdk zPatIZjfG_@P@4*7-5_!kO5;WNV&~RhvIUF0N`HZ5Uhv> z{YT87MV?=FP>B2?k6d~K<~~B_hQ1%LAvhWqRA}i z95HKHq)EZ}UkOY9W0e6yLX-1;@IXLRVn9I1-`|p_ql+1%nWL$@y}5%MgO|PCw9ci& zQ78JRVd3rIt0pX&X%dS29|wz~%V{8MPaf8ukWU(`sQ5P0s9>>i=4g;NqU)*al!wGr zJIYxy1&R%}Kzakg{5S5@`wv7-_b>+UwTxo!oPEtzus;--;u`?HT={_4)Vx>JW!Y7< zS`>J}96K+;mxD*buiqa&8j*hL_Yx$5R<9e~GjkNO)LR>Fn`g2HEuZT8r+Me2BK?!% z{OB>_S@*wm+(uKi))(vAQMqq@xfm^G$S)~D^#a`SbQYS}?KA>s*$kT%?rQKM0+^uk zAXLAQBKbg|xX1v{NRt6fsl4iH_(0qVARyHUiRVX&4#u9oGHcRoE zM3M^+Q_VXP5wA^FOkH@w47VtQ=K67$tMmekEBzRoC?(r1w+I2LR!^ZZ32*|WK-@r1t^sDvSj_LhrrEc>x(BI}-7Ar%t;J50 zc}9Pdn12H(n0_VQp8IRBcX?={5&kvcV(?#tL_bZ7uuW zIWYFmRPDN%tlZ2`I*R&sz&6;bpYs9PI?a9rE&y9+e_Ke&vigMm%5@_{nB$`BMY~&3@^Efa^CHMixE?&L2YNFTq`YcetmdAjd{kO8^ zR>X9hav8`&f9{~-Vb{F z2*L?aEr=orJEng;{|#BfO64AdXo)&Sf*ohqi!bvWTt`!7Fk2II4M6WiR`C0 zV@^#g&}_4cC19A4Vk2?!GFyw2wZ7=k?O8L{VZS$?xoE0pikxc(-JTpt7Idp5I7}^V z3Mmo_lCy_V>`4b{qgF_!D+=piU>$*Fx2HiJ~e zfODwu;;+$i1?J_xG+)oSvKz`-DiA=}M!1ZyLCC(YwX1GEsHF0JfsW5S*J!oRbJPVy zw?@SuvnsJph%6``vBfQtVNrM~+qCDRjT@X(MlX6m^j6n&b&IQxd*bf{o#eDcU8~Hs z$rVPZ$AHh7+pJatu?R<>L0>%l)$`9un=Iumy&z=~hOZ$e>|=E8y5I^1#{X?(MqMgo z5~LLpn%XNGBO~+&VG$Xg#ysJa?u!LLbPDM4TWa#qKGlZwl993VXySBXxMTeAI`S6# zVK=!fF(Rvki1>z~#h+tTlHN1-wW|8J5T&wUzM8jI;U>Z+E)W=Ar^Q1SqqQHqt_$pu zI$s@9%vrSy%PwCl{&8;5|54VrD3qgK?JX4!(dblt!@^vh`bHhsoz-BDdoUQV;*l)}o-2Bjh#THKbAm*Kw5h9PhO(MZZ-&O-#&bbR3Ak!QMTW2Lxe z1$9D5bF+?PxJUxZv+LZgqwgBv^Aa9|Qw1S~W;Ksuo*`7H&BK5_!3=gz;r9^DpR;|7 z8^NS3Jzi_yxQW=!SyCfg!WG+lCXeUHt$IrW*?_<1$Is4-wlwG-T!P}7*ttF%iLcvq zq(o)gGL0y8nmCf+&-uP1yYa?)NQ4mTNHMy#cu?8S3xhp3mVbt#JM|YJ;2ai|r{j^U zHA0Hz0Bn3H)Pz6Ue;wX`B*CaVZe$WByx*;ueN|+Kb{;JIh|rtTE2Qt;lp0yLaSHa) zd_kUE8|Ky_?5juW&h_d#FqskgD8(@K$=F!VL?q>)lQ>vYK`qW)#L;9gb6o-_pkdPz zLWPh!?HSDUc#U;LH$)AHE8+oY!*42Mfu~Z9@)-(oYnH86S9kV4rvG;Rxu&C8UAtH< zy0ynW3E>}Z+g)wWVX{K}80`tJJ`0Tnygh#cje>8JQGC!r{kM>-&5sf~`K+&MclcUx z1m;Ak7TY2y^cD%N$-E8Nz!$+I1y{dlAw7bmSWvjnM;us@oOT8f@Rir(JZp3Q5V+7H zi$HSB3oYVa`RYxs0j}egI8zV(;JSfk0$&I)e}RU{DMmFfD%1IVMn-=}xqC)^nW1jS zzY;+smF#t>8cM91?|F4EI^*0qtuxSnQspna4NCf2Ku@f^)p5!W=#8iBe9hP&@b)O^bJt<`^(Hn++<#^|=k7+=*>MWhO9f>*FLyo` zbreyAPMI$bii1k)ZqRu;sGWH@;k&6R)@=j!N(5QGsKlGwm38S!JgMn3tG>AeE-}Rr z7@@)tXUPmW(WSIVFX<>g?cgTXbH8VlswG>rm=~P*bKHwVFg$8vpwC*4h!@HzSha4X z1_vuJe2f#T?F=JdY4WmBI^%9!gqaKb#~iFNSE)fK)rsjTz7$=8*N6a|$>rhvHwzubT z+=DN`fK@6T#MiP$jKmjR{W?{*uokBcYNeGZmBJ0jr0>uk6KlS!;@uzval0h`SLIcb zR;JNmch;>ALy$;@32z&!Agt*l>Du)`-a8@?(AU?M)|SH-7t%+X(5=1q0M;c4iMTz? z6^Mk6TLF4hKTx#!gxu2A8Y8((d|qdp>Vy=auaVFM!IDeVWfm@h)#b@SeMS4@`QV5U zvE;GWM~lufg=K)@!UAGZxm{+qArnqrxLf7wi3=C)0)=JpY%Hl?u zEm=myfbiKJpq@Yi@d!%v2dSW20xfTR^sV+;8K>S0m09Z@vLO2ICXrd{m@@C>mFF5@ z`tD}wxoR!u&;k!QP^Fq_TaMf#dncoQAyjeM2T}O$-e-ME2T(H?!Gs#^ zDCh&D&}UxIwpB=lkE2R^j%v17Y%(bKhl*pJpb`}rGcXqNRVEL!Gfn70Y6UZZB71~p zMagxn7d01X>D8-;$2(pQD8I2QX8QW!M)VY-%QAf0FyH}eC=*mX;sRaY_?bVyyib;@ z2~33mREJ1aI8Kg8M5;7&6s5ds&^cOd2(^v+SBK+GgS6Ik*Vx_ijDJnXKy&CP=gddU zz?Se2Smx4L+1Ul=^SB@dC@~=bvot&ri9)Hev>e=u963ZjIXiHbpa57%TMn!bAk-l8 zx37qzv@{<=mK58oH-n+DG|^G23DkO0>d5a*n~Ag}h-5YCkst~f>~bV;+lzoAvVr#@ z3=!t&&UBebEi6AkeyJF0_A@Aa zTC=R~m$EKlZfY+okW{GuI3GmcCR9B7AvN;0l1LZ}5pk+*Nvu>Lm#m6N>~d%dDB=cq z-!NE?Nf%Z{)&0e zXz#+CSTZ1KkRF}^vg=lW^repdy}RxWwPOeh&XRC4@72c4Zab576c z9;+6|q5X-T`(LsQkM6R(w*sV9K|;JRw^rTl$QIwVX#LJ!nzaCCkG?xMs`b#_Zl|)m z>CGleEx;;0J}ss!uXgA5Emn(w=t02dfxS9kJLtgiXT3MkR|Yc{1Uk49(=E|m3Nbn{ zAcqMn@Rsr#AL(xuGg)FGg?dh{>TS7)FVGqnF#6U62Y2s>-7LMfq!lGSCiD8I;FqPV zziVk#8>I+EF1@|i$vTE{rX=(h{k5UsEv4&LGE5UxS#DC9KgnXhw*QBVKU7C9?HGDe zx&;$90ZVVIX<0K8P?V`iQg1OdhTdHrpnE76q<@DZGY}LL*$Mv~O)+afQ>qG4kF;HK zvEJ#KD;5LVZGH%X3!F8@Lkr$+t-p!csL_hW}XrUT1J08Tk&Zl&P zYZ3eC-I=UI5oRo@SHM~zep!}sQ_(3Oxg4`YPpR~wW*sS$0C{>c|u{e7u!-GLf>!%`)cZrYIq^2mT@S^ef#Sumzo;r;> zJ#F}NJ=&gAuIiB50XvaY^~Xe3Y)b7f1UEW)#xZuYuYAxawz|LgEL@GtpUayZ=2$xW zNRKt^3$4rV{v>V?VoO9gQN%R80D+d(&c@u z{t6vZeVg=pjGD;6mo;h2@WUj$7;jYDd!&=}Upi0K_eB=?BJPuHQps@8rJaqBsnRdd zbQ~5sE;!k3ko?>^zj|TbtMsQYY?ZP$3SY66KUT2#8SKaZtS%XG*p_pc#oVd6YrwoB z8bf3e*U~ThE@&Y8({f2L*vZGv?O5O6W#XnN*LT8etQ8_NVz&XGBvWzbG6Rb^y7qVo z4uj2)^Zs^#zrF4EMzKoY7Pv=wEl9Mh>Ix6W zUR7S2^~%w-!fyzj%LNPol84VUg3=S^K|Z zP4sfevaa2ETLS_0luh>1;MOp(5`VS@Osx0l`vbamC^O4bsp;tB3RyN>**aLuyg&lQ zuql*w6Y-z{6dMvdL=r$-b}pem@}tna;xEjX~jn zCJU9G=b5)_h>0_UIuY+A0$aoKw&JChA4 zMvo`?j7L2navfz}{DemZqxqn24;1>Nau)^RT6uQ{=$%+mX3et>3F7w0E=o$bfgVw8 zpb!geM8gc&R9fF=0GC&|OVQY^%wN8%C{G(4ZM1*%U=2j9POMHs7xmMOX~3d^F0a1B zLF$|jFjKSOcB}!#mR(BG2Hog83B;$)cK5wOkZT)AYgfk)N8l3sP`#2;w*BN-aQ~P4 z>qG&FY2LdmOQ07hJGZ=2ZD(^Y5$FWq2QPukp%8oNa3uUpfR@cW4vs;Wst=ZxnR9zx zYk3N|IZLc3%{O+aWvAdY{`oL6wQ=yiEIt>q2H#eWwZw$ zpFr<&?!s&(Oekx@N{`+!a)#CUlf8hYq!{HRya%=iJ7nId0|D$Y zw_H|8ETOJ2bwT0hgD-R@@?K1pIa{3dMmTm`O#c;m@{n^oR)p%OLYL=-y(ii91>JP@ z>hcFSLkS-OEyM&j!UPxi8zA2R{RUWv2`+fg2HEMYAqNk z@9TB*6f3Un4Cq>(Mw@fl-E|E;7%d)MbPNsBTTFaZIbTvuf+OnGRp+AH!``}UyJt6l zVmLfm^npOmkGn=FBa z)qJJiy`>Djxc=~wbtjM&M5Nx3R-F-F|FrI6{OzNz=5*KWkgg5cGqd8B#V%N{2^FZR zt!a=N)7%3tN9Vz${k=bqjWk-uA7Ys)h$X6+;$g(F?iU4A87i#GyZ7TK+>HG#DsUWg z6ugl@i*fD<+xlhwr%JbV$H9&@yl3WjUK3oce2xh)->NzLZ z^2Ee*XC^vU&*p1p^W6gH26#MlAg|}d1oefH6ot=(!#A=A*;K^KZ%&^~R_XUgT!Huu zsLM~O`wd{gJUH{MNmP+Q(&R~02DBJ zPv-~1kKd45_PZzd6+f;|tu_;8y6y7YJY&iw>GGcf-w|#+UIK4dR@UgNZ?k>+x+Q4` z5U#KL`gR|{=TIBlWA2NLTMaR%-@MyF*7Rp*_YBkl?kW0oL?l`^(6#AinL(eNk@a6# z95IT+e*)^?;{5U+>e;=)A9W1oc7+LS3GD>e{nj3M)!V@)?l0lsc3HyNT?LdbyDap4 zG3ub#VeI<$oms9Wr4xkNrLRd{NK8cGeFx|6Y8&7Sr~KGdHpVaveD|`D1-h&p$r3sEuU&9>9EM`!r%} zq(I=~k!yO-g7V_ga#vG@8bSq>NUw#l`xZq%u*aa*%j%L|Y}Ajg_zk zYf??ZN9TvciBS}iaTQC9A$_66^-?!~vMY%okf4?<1*)Dgr=18T5&;|kBw+z&feX0+L6sl_bR0*rV2i#7$W*1&6kqOvap)&e%6qflCSOtX z@XLPoJM@%JX-I4AP#|_H@>sp6>~&mj@crB@&B?eX+|Tv{O$Hh#s>h6IB3cvFtgc(4 zqbZkHsv;%RLFrst&W&&HJX7YLOzc3RS!?YeD#nIkwvwm6gdHQbxlAzM+F)k_w8y+R zMStpGaE5?I_g+DWlfB%WIBSy=7X6jJpy{exlV2R*)b$j1h1d*kui%vp%vjkbY_R?_!LV+UD99=$xC9Xz}acpkwq!sh^Cjcy+mlK20$gWj3TH^QFJ7X zk&SsuX`sr~`3{G0Mc?!7JfZUm#9$$05Mz?LhyoOn>Lk{8iHj6ioPRS;Z7HhK3)y zr0M_InRMu9&Z_OmYMI#}@m3wC3;2;>ac}Zus?yM77TL}p3+XLKRU{%t-dIQ%CYKbx zTw|s8Rec+}Te^`dEo?2MMjb>%h;5}DD;6we3ig+{(X@TQG;&WhuLkqdJk1WaJOpZJ zBb7F$D^)KPiY|yAU?R6vNq3SPhAJb260u`*rEW4w$hk*nn;;r-vdTLJWlQcfbS$&WTu)VIhNVXmz@eD z>U7t+X3;bNlr#95pWQET=$MG*T$W5?kSpvISajyty>Yj3Ft1S{aVaUtGgK9YD;hxu zlQ>H(d_9m)0oqkhxXEXlQF9DwfD%+>2{V?EiWkhflN1HTB2Z(}hNj6h9m1HJx6FkY zhJ?usf-J}za7=wKOO6ZSJ!#`KHe}}>&b4bioIr=o@?Ds+J)HYz>u`*Z= zs)Uta6M;xaT;IPk9wsy})QRX+(nGqA&GE!d(@$^YF|0#C-j&n94gzn%7wTBe*FVVu zAWGhlDGL+`2psnRwJmZrcXP9Luyp;`L1(MRp5qo5T!5g_m+1bPEPjQw29|7uZI2!& z+ZK~$r{zYnY0;~(lFQ;%10lI?lP7+-nW&*jHsMPW2{n)7u7EW2CNq;>jd`k`Trsk0 zSh=2k#=;t4#>NjlE|xqRr3hVD0@9+mW3A!Sr$rII1!HC!iaJ%=yeXE(_L41LUYS{X zI;=iRq;Z)jYE*N5EP2pWH3631*2H@jyd%PkCyTB)UV^a%LTytymYh)tS6}BW`J(w4 z{F2}Ys6y0M_x7*iBspzDW(W!<$U3=ETh#UA+h$^b7I^Yb142^@$@+E5Pw4R-+d|0% z)kRkX_VZxu5cp&gvI%uUucz2^tTzx-PssDS3TL#@mZlOTe7XJtXB4GtoGpYAjLv3gsUW-NN{vs<^6tM& zc_#V;`r^3EL3Gc9&V&m4_I93slK2m(<47?u;o}V>D=bb}o&_`!-yDcP9Y5A1C=6cc z9j$ISw-X+O7!gd0qbXlKq^6Z3dx+jmU+`%4<}2uQRzf8Xu}s*g?3Z<}Oa^28h`&hK z+&xqQ>1EA}FjQ8sfz$2tC4$^p2TpFgM8rk|BzdJ1YHaGLZY!R{ygwB4LKeug5SIV` z62e(ycbep=56|L)j;L2jR`w8l?)8AKhn$|j|$oM*S+5|^icCI?C>!3BVx?!7Xv3(c>?Dq zK!^So(LJo~vqjEpjW0HD3?6}FCydvuQ&J;wGP^g>_z?z^*X<~bEIJTCE=$GX zf>*;wyB6BccXt*fpnCNB&%uQHJ`mG00MkviM2S-@%&Vm|{-$+}<2z+cL@- z4XAmS?a%XAUp8IBxMwVNq7=PUICozv#9h~i*fDR&0pF=zn+b8)y~GgiaO#E;>i~nQ zCvf%)Ie#d_5V^(fyZvKX-M9@Kk3WaNa_jjd9s}+0TVSPgw=O*J`X|DU-|N)rkepf-8R z<{zR+*k?$lKRu+CQ?^bOlQ!tm}=w57G=+Aj)7n-uGOS>9ai(`}_rfihX1Epe@ zk+S;OeA0L&+)+K`|U_zlliZ82X;SDKcMQpg{j-MP(S^LqGuPS8*?F!GM5h zzxf^io7?f>ZJC_$WkE{k8R^` zu9Qsc6&ckbns-#y+f6@jGGW5>cfn*&35zA|LM zcqK}%9E5K%1fgTV*R@XuO)+~XH6m4~j5afNs?ORkr^@JLrcwqmd9FZPV(i7=)SRN> z$D*olVMgqWY!&D$Z^md~N5Yb%6d@9KttG#)=}VPN>g1(pR&8|>Z^p$Z){gB(Pm8Uv z4mK_DWK@LVgKLskC!3l&nt`==lCS3g6iw!7_gi5%t=>+^_Nn6fKBZx*G&UyC$s2{!hI;h%% z3nA(3{djQjfvpmW=nYUc2YRTAH1K4EuqF*sc9P^T`~;PiT_QpF;u zSu2%+rmU!XvdY|obe||b5caZwp(-0v8M+pf6|-HGnjG6C8q;$YYR8;p$;u?7>Y}(+ zG*+2DTSn0)Q~S1y2BH7Ny0wCyp#vz|)`5v*imb1&}R+orLE0 zTTv)UIF3K18I0iJW4*Gt(uNHjs79FFa@~Di%t?X1GAeQ!5`0;^nr6TN-_!-dW7Kg& zoHA;r&G=7P^!HkzA^Fn=qQ5Ks6tKZ=pf+9=W*Sa0(W|mFWr?16A-j9@*!m4op3SE9egui!tN5u<(qIwfJMcDE)%=>mCmAv2mFXe_GpC zQev6FmeeBhB$>p~ngCPuC}}E!`UGJP+D+dj)=d6JXwMONR7suQ$Q$1%BfKoL8V4r< zUsINhli%@-*sxW^_swOWML%;wu*~WLV@F!8!^EAz7|$~)_0o3|kgLz`eOk=5jVh@$ z{AaDM^>UeUj$x(o^vVI586z74N(t>=IC@DO=A=Yl; z6X~89K87}(4f9(N3@hvJ8;Cx7mv+*Dq?R}z-77n1N7-EZU-qV!xVXB|dEy$Wf`P|7 z^XqHH)g$rybNrvvfMtf@zTjOSO7~s#%@~P-XPjxSwF zycYhcx1Psh`rcv~95MK{MvO&cfEHb>DqS@1Jy)czFH1IKeR;{#9U`i)zwMT&(cVDP zBN}xu?{pZ2{rSKGU%tLUSiw6}v?#y>ckUfgIPtmV{KA6|5z(RI=lL*ThuHn=WcwZQ zKf*XJ#djDV!+^L31#te7{z>&6pZd{(fN=k37-w{Fw>L3&`QDxV!$Qm0aya5Z3crPY zz=zwRM&Yud!l0ZUPCyt(e8 zYM*XQ1n3O;#Fi`;0@Lwr0VSTps5USkyCPDycZc=r2hv_{wlU^$EYJ@G{2oAz3uFn1 zs`m=8cZtxxdc<)8>4%x?53b}T@|`%+E`1fQ_+@T|R^LJGAXh9s7KNlx&3+c@Lq~IG z(0!1fc1cNcH-XmRI3dmN_MwtSD=3vYa1`5FspOfRQRR(U%6EJ=SB^TqCq8Ohobt9o z(gWtkT~$#X$xv1H-h|gS_lf{I2I^V!vh1JC!1&q>i?vpckUZ%SAywhEbI^_DVsl$) z9&>7M4K>%Q_~HDG32*XOR8{ba`x-swcz-WvfeNW0h;Y?EiLwJG-vh}}vPy@Y zcqGc3#Zk(nTBS=Oz1AT zODh9)GsYI~X)N*Rp}fGVID+i5)R2`1oX*u$`48<^8cga4l3j`&=#L0s*jtg3OSA&$ ze;uD+V=M5Y`3=T$h0_2MYG%93a~R1_5%Eem*~OJziZo(Yp#*^YO~dLPb;GM9tfbAJ zz#EvochI%wq&;Et$pMwj#bXy;$rxgDUe9=b?G=i`{35G1L?PuKG|AvWx7XVpr|lt`Pi(KGq`5f^H;TCv<8 zO#vGV;G}84@P?e0lTLsXexn4Mbyl8@(k279`UKKb;ZZR*0UY?*&eHZ24H)7 zreUA$#r4*FRm8$JupNOo9-{|%k7Y@Yy0)WW@e?n9`Uxmp=Kuj>gdAWnTUI*i+<8yZ>i(t=uv=S zfB?~vWAqbg?U!hF+2eg1&D5!S1ofFx^fkv$V&OX8U$Ta*4|i!68M-^041#LZYiopS zKowPrsJ5My`a;OACA}kI#S3=HIZ&%2r@1ov)+;@K<}7J=@oDt5!F3B}U=U~}kdecL zC*JT4*4lFOoHQ!lIG^ic>A3c(9AYA#GL$;+%fh?$v~Mj;@E;_sbZ3e05Qm*k-?d-R>mB`EAp4wcFu_T-a^PHR&`Ak zJCNqM1Z{nG$EluX->p7VKru-J?XO?@diIMCtnMl8ZHm?{w>!Nu4d(L)XZI%hnEUZ107vq` zi_6~MhK^rB9PX~@8ICvl7M16>%@54=3FI>zGrSU3DJogdt*{e+U$HD_A{u)7t-qdp zu71Db-`^oQs+_9z)s7(pJz=2Qz6$Zn(EU1^f#rpnv)jPJ3F5e6AWsRi7$>~y_nO(yHaq?08ceOf z9)9IX=1>kL?Hy-yQ-Wk;s{9!5k?HN{es!f<8Qw~`lK5GI!xEq-dYWJ}0eDr0XSV)| z497bC+EB`-bb~N1h?oJoK#M4mV2dE-V2dar|GuJsU%}WSSmzh;X1OF>xrWhxRK>tM zqCG+MjA36NZU5pn!S?i#(HhIk2TpgcK>cL7aSJdU%TqX;>Rj6J#rEXUKI*zwk?k&H znYvt|*}@Rd!(>m&7QY49=;W$m)Z~o*&X!I{6+ut|Dxb025$nxvkJ@y_D=FJQ8pHuuz_y>SX*Q zB(TXlk}#}EDj({mA5~dOg$vP2NAMOWsT2g_QD8T9)MqVPODh2IoTzd6Rvjd@%RB`Y zu_DU`ql-?j$W~jYXcA6jTGxP&W#Rv8km-^ZGF;n`>%oMkI)*2^F#p0Tn5VV``l7?b zFZ!Y*o}zN^`)Rw z%D;5#+yeNofn1*}z^@WgoEN|{kkDeWB`U#W=<{#F{}kl`mEZrZ9ha! za^L6GwcCWb>Z9E^DG<0nZz9cccKm80b9<`6; z4b6$u$$p)JSBEs_ZOh;$pK5^aaFJImLJh)seT<5(%+4^!C+BSGLk*-`LBKnaKLdh1 z_NH4bR-xvydlTl^)hycQHR9cGPiBPfR;k$naQr&j^9SURm#RSNa&q)2A{2d#a&H5srJ;ih;5ko`jMv)Fw?;0n^w2QS0YX>SshvOfmM zWu8WDJR%@@=2h))Rbpr^_v@op%YBMn)l}{1!73vvgVSXO6kWEPkJVU1U`XF!o!~lb zZe_@0OJ}vpjb?3(cQL}>5mf))%b0<9O*8Q>et^Xx&u=ia)ey?UMh3d(BY_4n0_G!V zKBKYkULX;0N6=j4<6d7>OJZ6~SaND)-@y6?9G09F(5m5&rI5OT*a}Ep0KFnCYAe|J z53xAbqNRaCM{ge{<)het-9n(U&tl0fb1i{H*>$)f(>X-{A{LM9B2d{DOIb4m0H`KA z{V+n|Snsf4xr8?tZzfH)w&zriuf=yk5@)zC5x|r`LBgXaVcW!4b z-`=oP^IQ4QuP`l^;1M3XHg-e+tX5A+WWSsNE@-=U#y0nHTQTCVV-;I260wFFD46ME zatyvq)(kX48 z{XQVa{_TSH#)qhw;RRnS`{$Hm|^VjYa`Ttn?Jv0<%8WS2_WnSbT z^(JKj-hv)G}EB*$1h=5>fnqPGN z2f*~D)6z;x-X*}^e)@{?-p`+!C>DO4;Kw2ASU7p?3N^l{@iaV60TZW>-_SPG9dxCa z3-j~fo$@)hMqf5~p^tzJhP_Yu|^qrFE^5Hj{m4-(m;n~TIMEm%-@1bKv z;F+dG;gw^)@ja@7#jcVV7}rK>5D@Nj5;{FfhsZ8QkMIpxcD-$5QTTt&2g0$O*hsYu z)WWxn)W-DmBcpA-=JH*qMH=2R7SqZI>IpK7u^os zW*s3v%RdOVsj}>A)VV;$(2!-)sK`93E(@4{4((bvLOl&nQUnN%ro{Y!OivJz%uLY1 zu+eK{L%TQ;IYDhK8dI0uR{HL~@NYpLQ0cs~sPrEqgVIvq+k)>0R{s_#g3FyY)>QvR z&{CQ)e4F^6o&N9kP8&cJ?!R>6{9BA5ve)b2!2CCH7>=V!ANRk7ejL(H#N8f!YHI*+ zJ7_cFF2&in7W-HnB|zn`TayE;Yv)^cyL}S&P&o(h=4$!dHI0Jmj^lj3W3kDA&|A0h zEaD1_qyfbKuOg*-7?0H|l0jDc}uHf`Hb6{_!?O?d(&Kdd58K zJ&y$UqX*A7-;bR~&~4(4;!-(v#czwc#Y!CC!Gk|#(xKRZ4HE4YFr`6OTq>kJ{wN|MWzl}BbkTJ?=JIOdV_D26LH)AA9 z_|VQ19vv#%0HT`o>UrZMh;D4{d`H`I+sksu?QFKp+trOI35y+6Gy~3Y4d|VIj<69m zjR6i+>`YFGMfVOHuPo(R#N^VbgZIPsp8_?yz}j+ z>PaK&?Wlc@aU{g{w2dn>gGeFg>%JSUmz(&;AFXlge?fL%cQ+GiH6LL0(?q-uu4l6# zv9_CutE(-=+NpA=>$}2>!?q2^>kVXG?U%Az1BgcG_m<$cQsAdprkNJqak7-s)#;o0 zR|-|}oop9{B6W*!H#qW4>n2v*3_bfMH2tR7+*g)Cxa|mow>-Z)Ob3re*^#<|h?m_( zyDhn+@toPH*&7&v=fh#LsX~~fN|d~PW*Z>UC`GA41P5d3 z>(n36reiLipz0g(REuZO1Xv=i7*P+lN8uzxfp5orj-97+68Jt^&*CvUECKK2*QHWGLW6U}St3(%_Ks z|7UL7F^K`;2MqAGMq_dY0Rno2{(qI$EF2x&)QnB+%>PwdJ5KwrG)i0sVomm{)$+8b z=7_eXe05Xt4JdO{0oBur+XUg*s%ydy|aq4=-+xRc%*sqs?Sv5S*_SDo#$k zN5Ro?hp$uNp>HdO16ret&ZdOQpp;8>6AD(X6Ee351jKO9P82cm!|2PRH3TXP3T*?& zQg8h=l}m^PV%@^ae>#d)#LI8z0&rwu5bZpPj0{^4Jee)&(n-l@{~czZqiXCLNz4`6 zrDzU-#mjSoH1>z(`RY!RNpTM%t0h8=8FV#zi($C_$-c2WdW~WSirLQRz|fE_OTzT^ zLbO`#1o)FI1x`0qk57#ez%@h)W4|Cj#GEgAFoJj`l#L2M&2kasj6WN>KUx%39(#xf zzt_~=aU6ase->}$aAxQUyk|6yu}VA?PdE@S_I${dFp|eSd=KTG`^%fmChmtXL|a&V z93}&n*Phmizh>}6jLsD*L4@dX(mv;yhKqJg4`4}`e$)94%X@@-JV8;hL4tsZB`f}h zSHgl2+c`sdrfYX1WYcE0)%`9$4jLzun|4)VaVlJidMU%r%x`Y-QlD)2yLwL9KYBfY z+1sMeQxHRuyt22)FmtyB>rH!{eU0*ndRNAF(HzUwJH9=VChq@04O_`2#E96GXTz80 zhQsFudnAh37N$Knv5pfis3%$27TkHe@ANE-XXI5hs6M{ir)4ozrLU77c zRU>J$NGo-jL2co2KPD9ZNSHH#e0;u}yiKq61;whM$yW!&W4?dh$>^#Axcg%n4V=y7l zJw1ot>wgT|;eZc82n<@B81z)<^GZF5mam<#r)7%^y9GIQlZ?`xSdSO zCh=-5p&3_k!y{XfQBaPbgxcBjs^>6Jz{+;jPJmWBNMb`L=Ode6y`aHC8<`{%hsV}w zMgeO*&+kjYuFw6vWK2m38g;ccZlR6~v3itXD0V2EB<_)4j0NzKzg4~fb6e+gy&%?4 zHAOydDyC}ce^MT7SKG-m@RHU^B+om@+d4O=DU{w#<}Ps?FC} zpGAoDHq|tR@fnl!wmz=Vh_gnt8S)YD(ko#kk;))kVnV_HC4E8 za?1#RYdg&#cte~{tftiVj zP*RcoqOG-_@yM?yWm?-u)w6dIJ9&dLu0m{bXzpvYvAfV8gf$ZF3+c(<(A#nFN%~2* z`OUL6{t_*uoph`N6{D=WWS%K!QCyr#w+=$2}@ zjHA{IUzUiYC1b_bd5dZ3zdTDU%pD#McstvT4c;G6!T3SsO!zMP2P3JaxP;S%k%T`R zO{{V6e#6h6ov0{c`QH402I^?6%Z%RIJ9qEKW&jHZeT@MPHOl#T&bf^+Sj#=EGN6Ot zoa^Lu&RH&8m)hsIU0--bDZlP*%Ue1YN7gH&Sj>;PpsX+0?Mm|Pr>vk3nn%hm7QGYD zS9oVSce}K6?MMQ_1GAU#q521zsyzLP@M>;|@&MCkUxIP1PRud`yXi}-XNPAeQZekb zk~x2yD_8R89tMsq_SqI~>ALBmbv3((Lr?Y;71NY58Ey&CFP#Uzqo;$9)*ZvN+aZ_e zC(@%w>T-@9_Lp4BDbwk!+_sUq;ds8!vg#2XMp^G(=N|L=R#z6@D$J%uXu#arecv>ulAmiBYl}9Xk4T&0?T$O6KN%_#bGSBH z+qg?I7yDD$)g6fq22+9=Iyu*{lzwC&qk;ZZz+#_Z`?LioU2L#LHN-mmR+13x+^JTh zUFBSO_Co297rLeP0F7lC_{|^_TE8w1spN5k-nAjxBs-I8+V2EyX-jI5I$|FepZ9E! zYEC{tzMMRhCv7h>m&JRd7Y}jXm;B*=x4Uym+yC0m!Y1#PsH!Kjl&gyeR-#sfEM;bm zsN=$^$-Wa5;>wRb89VygJ)SQ)`>5;vrNA+_;pVZF z0T05Nxx0>THxP(&R})xzAs4hLb9!SEi;8!h{eC=Ha;=l=7_&SaA#U8wSx`5UH4E|O z_@ku7DzAwi?>p=Srs+h}~+!xwt zm#eCoH|x7>{F+`+fzz!f2hyMCi! zyzP{3xuRs7ER%4IEF$MQVKANAd+YFQ#EGRe@9(dUx3>l9#5^f@>LKZOOKf~_`UC2l z>;C_-`6B9d%2zhD8GP~*rse}NUE=Y^Q)ud}lif{oFVm0vTIsi5%N@^^g+7|kSzk?k zI}ksCO>ZrT=sZb_qq-SyvOmmtQmV&N&pqTqv-qz$QPdYaM7Qxc?su9Tt$Qn6U}ov4 zbyr|@=`5e{*!MLzpo(?Z>!}r{<=Y}YWx982i+1Cn$SW~iPi2>Swnd(mM58Ic?+`QRSmj0Lh)&8=b_6-a=fm0(Hq>vN^(s`4Ur zHC(CS7!q*Q4qO=ac{d+xgEg$1nz`gh2Dj@1c(}?j&|eoYfTyW}QMy1E@kfoxpNn{1 zc`>{$kFo*WsCX_Ovpj7;n%VD^$#+blgw{xB;o)JMlQDkgQ20+Qf@?57%Z!DBYG>{>2ptt0wQuqlNuO` z190fIS~VyaWkWO+Xw3PCG4#M+aR45@R?!2sV0|R2$eW}Yf|huI1}`@TnRtK-Czyb@ z@xUIq^9S%(JYYstta^|mLw{HKOU&d`4Fq@!2N+Wn`G9gj45TKsrhf7XK>kFP0hLSv zgENKjJ^XJe2Mm!UY>ZTLNGY zcS3+M1OQJ|TtSz6snb&E1=wr~V2FzAVsd~1QUQ=d0L(V6&M)LPja6s^(g?t2qT*yj z4oJo;0yqQ!gZ?}FgJQl)Op=?G8CXw%o*8+50)uJGPeXhC7NC>>P<5ua0x(FYh91T` z8%_>khexoOYjHyV{cUT2!JwMxf0!{DTr>qtzyc_eTLpVQcI`8s0o@6T9%Kg4#)bCw I9$Y>A6R3A_b^rhX