-
Notifications
You must be signed in to change notification settings - Fork 0
/
local-search.xml
307 lines (146 loc) · 463 KB
/
local-search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>数据库的隔离等级</title>
<link href="/2024/03/18/Transaction-isolation-level-of-DB/"/>
<url>/2024/03/18/Transaction-isolation-level-of-DB/</url>
<content type="html"><![CDATA[<h1 id="数据库的隔离等级"><a href="#数据库的隔离等级" class="headerlink" title="数据库的隔离等级"></a>数据库的隔离等级</h1><span id="more"></span><p>在这里讲讲数据库的隔离等级。</p><blockquote><p>以 MySQL 和 Postgres 为例</p></blockquote><p>数据库事务的四大特性:</p><ol><li><p>原子性:整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。</p></li><li><p>一致性:一个事务执行之前和执行之后都必须处于一致性状态。举例:假设用户 A 和用户 B 两者的钱加起来一共是 5000,那么不管 A 和 B 之间如何转账,转几次账,<strong>事务结束后两个用户的钱相加起来应该还得是 5000</strong>,<strong>即从一个一致性的状态转换到另一个一致性的状态</strong>,这就是事务的一致性。</p></li><li><p>隔离性:多个事务并发访问时,事务之间是相互隔离的,不应该被其他事务干扰。等级一般有:read uncommitted,read committed,read repeatable,serializable 串行化访问。</p></li><li><p>持久性:一个事务一旦被提交了,那么对数据库中数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。</p></li></ol><h2 id="事务并发可能导致的问题"><a href="#事务并发可能导致的问题" class="headerlink" title="事务并发可能导致的问题"></a>事务并发可能导致的问题</h2><ul><li><p>脏读(dirty read):读取到未提交的数据。</p></li><li><p>不可重复读(read unrepeatable):<strong>在同一个事务中</strong>,读取了其他事务(已提交)更改的数据,针对<strong>update</strong>操作。相同的查询语句得到不同的结果(针对单行数据)。</p></li><li><p>幻读(photom read):<strong>在同一个事务中</strong>,读取了其他事务(已提交)新增的数据,针对<strong>insert 和 delete</strong>操作。相同的查询语句返回的记录条数不同(针对多行数据,注意区别不可重复读)。</p></li><li><p>串行化异常(serialization anomaly):成功提交一组事务的结果与这些事务所有可能的串行执行结果都不一致。</p></li></ul><h2 id="隔离等级"><a href="#隔离等级" class="headerlink" title="隔离等级"></a>隔离等级</h2><p>数据库有四大隔离等级:读未提交(read uncommitted),读已提交(read committed),可重复读(repeatable read),可串行化(serializable)。接下来通过在 MySQL 与 Postgres 演示来理解它们,并对比 MySQL 与 Postgres 实现这些隔离等级的差异。</p><h3 id="MySQL"><a href="#MySQL" class="headerlink" title="MySQL"></a>MySQL</h3><h4 id="0-查看-MySQL-等默认隔离级"><a href="#0-查看-MySQL-等默认隔离级" class="headerlink" title="0.查看 MySQL 等默认隔离级"></a>0.查看 MySQL 等默认隔离级</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash">mysql> <span class="hljs-keyword">select</span> @@global.transaction_isolation; <span class="hljs-comment"># MySQL 默认隔离等级</span><br>+--------------------------------+<br>| @@global.transaction_isolation |<br>+--------------------------------+<br>| REPEATABLE-READ |<br>+--------------------------------+<br>1 row <span class="hljs-keyword">in</span> <span class="hljs-built_in">set</span> (0.00 sec)<br></code></pre></td></tr></table></figure><h4 id="1-读未提交"><a href="#1-读未提交" class="headerlink" title="1.读未提交"></a>1.读未提交</h4><p><img src="https://s2.loli.net/2024/03/18/teTXc3Sry9nORmN.png" alt="read uncommitted in MySQL"></p><blockquote><p>设置完后,该隔离等级 在 <strong>当前控制台 所有事务中都有效 (直到修改为其他隔离等级)</strong></p></blockquote><p>出现脏读。</p><h4 id="2-读已提交"><a href="#2-读已提交" class="headerlink" title="2.读已提交"></a>2.读已提交</h4><blockquote><p>由于屏幕不够大所以修改查询语句为只返回需要的结果 ψ(._. )></p></blockquote><p><img src="https://s2.loli.net/2024/03/18/Om3QFiRVnx26Kbs.png" alt="read committed in MySQL"></p><blockquote><p>解决了脏读,但是没有解决 不可重复读 和 幻读。</p></blockquote><p>在事务 1 提交(第 12 步)后,事务 2 再次查询,但是结果与上一次(第 10 步)不同,且查询余额大于等于 900 的记录,返回记录条数也与上一次(第 11 步)不同。</p><h4 id="3-可重复读"><a href="#3-可重复读" class="headerlink" title="3.可重复读"></a>3.可重复读</h4><p><img src="https://s2.loli.net/2024/03/19/KMRmLChXYPGQWxc.png" alt="repeatable read in MySQL"></p><p>第 12 步及之后的操作都是在 事务 1 已提交的基础上进行的。接着如果在 事务 2 对 <code>id = 1</code>账户余额 减 100,结果会如何?</p><p><img src="https://s2.loli.net/2024/03/19/Q2OZ1JjwiaGRFXp.png" alt="quiz1"></p><p>**没有报错 ψ(._. )>**,那么结果会是 600 OR 700 ?</p><p>查询其余额:</p><p><img src="https://s2.loli.net/2024/03/19/aSsIHJr7Uf8wX2M.png" alt="next"></p><p>结果是 600,没问题,因为 事务 1 中我们减去了 100。但是如果单从 事务 2 的视角来看,原来 800, 减 100, 结果是 600 ?!这算不算没有保持<strong>一致性</strong>呢?<br>由此来看,事务的并发修改操作还是对其他事务有影响。<br>为什么不阻止修改并抛出错误呢? ( Postgres 的 可重复读 就是这么实现的)。</p><h4 id="4-可串行化"><a href="#4-可串行化" class="headerlink" title="4.可串行化"></a>4.可串行化</h4><p>最高的隔离等级,最安全但是带来的开销也最大。</p><p><img src="https://s2.loli.net/2024/03/19/oBua7XjAlcg2R5E.png" alt="serializable read in MySQL 1"></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 等待超时,自动结束了</span><br>ERROR 1205 (HY000): Lock <span class="hljs-built_in">wait</span> <span class="hljs-built_in">timeout</span> exceeded; try restarting transaction<br></code></pre></td></tr></table></figure><p>在 可串行化 等级中,MySQL 将所有 <code>select</code> 语句转化为 <code>select for share</code>,使得查询操作持有共享锁,一个事务中的 <code>select for share</code> 操作<strong>只允许其他事务进行读操作,而不能写</strong>。通过这样的<strong>锁机制</strong> 可串行化 这个等级解决了上一个等级的问题。</p><p><img src="https://s2.loli.net/2024/03/19/BILZONqCYcAGldP.png" alt="serializable read in MySQL 2"></p><p><strong>并发修改导致死锁,其中一个事务由于死锁操作失败自动回滚,释放了锁,另一个事务的写操作就可以进行下去了。</strong></p><p><img src="https://s2.loli.net/2024/03/19/KyIU2c7XlvzrRoh.png" alt="serializable read in MySQL 3"></p><p>这次在超时前提交,修改成功。</p><p><img src="https://s2.loli.net/2024/03/19/pia2jTV593Y4AhG.png" alt="serializable read in MySQL 4"></p><p>由于事务 1 修改了数据(第 5 步),它提交前事务 2 无法读,之后事务 2 写数据就不会写入相同的数据,这样也保证了串行化。</p><h3 id="Postgres"><a href="#Postgres" class="headerlink" title="Postgres"></a>Postgres</h3><blockquote><p>创建了一个与 MySQL 中一样的数据库,并随机生成了 3 条数据用来演示。</p></blockquote><h4 id="0-查看-Postgres-默认隔离等级"><a href="#0-查看-Postgres-默认隔离等级" class="headerlink" title="0.查看 Postgres 默认隔离等级"></a>0.查看 Postgres 默认隔离等级</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">show transaction isolation level;<br> transaction_isolation<br>-----------------------<br> <span class="hljs-built_in">read</span> committed<br>(1 row)<br></code></pre></td></tr></table></figure><p>默认为 读已提交,比 MySQL 低一个等级。</p><h4 id="1-读未提交-1"><a href="#1-读未提交-1" class="headerlink" title="1.读未提交"></a>1.读未提交</h4><p>与 MySQL 不同,Postgres 中只能在事务中设置隔离等级(即每次设置只对当前事务有效)。</p><p><img src="https://s2.loli.net/2024/03/19/TZUcFNWrQiMIBha.png" alt="read uncommitted in Postgres"></p><p>当前隔离等级为 读未提交,所以应该在第 10 步查询中读取到 未提交的修改,但实际却没有?!</p><p>在事务 1 提交后,事务 2 再次查询得到的结果为修改并提交的结果,900。</p><blockquote><p>In PostgreSQL, you can request any of the four standard transaction isolation levels, but internally only three distinct isolation levels are implemented, i.e., PostgreSQL’s Read Uncommitted mode behaves like Read Committed. This is because it is the only sensible way to map the standard isolation levels to PostgreSQL’s multiversion concurrency control architecture.<br>官方文档中如是写道</p></blockquote><p><img src="https://s2.loli.net/2024/03/19/wUkZKClIFOsxhgy.png" alt="御坂如是说道"></p><p>即,Postgres 虽然有四个隔离等级,但实际上 <strong>Postgres 的 读未提交 与 读已提交 一样</strong>。因为我们<strong>一般在任何场景下都不会使用 读未提交</strong>。(这也是为什么 Postgres 的默认隔离等级为 读已提交)。</p><h4 id="2-读已提交-1"><a href="#2-读已提交-1" class="headerlink" title="2.读已提交"></a>2.读已提交</h4><p>除了脏读,我们还需要验证其他问题是否解决,所以继续演示,并且不再验证脏读。</p><p><img src="https://s2.loli.net/2024/03/19/beplJ8EvIdt3A2Q.png" alt="read committed in Postgres"></p><p>由于不需要验证脏读,所以事务 1 修改完余额后直接提交(第 10 步)。然后在事务 2 查询,发生 <strong>不可重复读</strong>(第 11 步,虽然此前没有直接查询 id 为 1 的账户余额,但在查询余额大于 900 的账户中能够看到 id 为 1 的账户余额) 和 <strong>幻读</strong>(第 12 步,比第 8 步查询结果的记录条数少一条)。</p><p>所以同 MySQL 的结果一样,<strong>读已提交等级 只解决了脏读问题</strong>。</p><h4 id="3-可重复读-1"><a href="#3-可重复读-1" class="headerlink" title="3.可重复读"></a>3.可重复读</h4><p><img src="https://s2.loli.net/2024/03/19/fF4zoaP52xb6eRu.png" alt="repeatable read in Postgres 1"></p><p>事务 1 提交后,由事务 2 查询结果知,<strong>可重复读等级 解决了不可重复读</strong>(第 13 步 和 第 8 步 对比) 和 <strong>幻读</strong>(第 14 步 和 第 9 步 对比)的问题。</p><p>并且在事务 2 中,继续修改余额(第 15 步)抛出错误 <code>ERROR: could not serialize access due to concurrent update</code>,这样避免了像 MySQL 一样 800 - 100 直接变成 600 令人疑惑的操作。</p><p>继续验证 Postgres 的 可重复读 是否解决 串行化异常问题:</p><p><img src="https://s2.loli.net/2024/03/19/BMldJsmyVnrxbgj.png" alt="repeatable read in Postgres 2"></p><p>两个事务都提交后查询结果得到两天一样的记录(id 不同),这是 <strong>串行化异常</strong> 导致的。如果能够串行化,两个事务的修改将先后进行,所以后一个事务 加和(求 sum)得到的结果就会不一样,一个 sum=2700,另一个 sum=5400。</p><blockquote><p>在添加记录时如果不显示说明 id 的值则会默认为 1 而导致冲突,无法添加。为什么不像 MySQL 中 id 不会自增 😥?<br>在事务 2 中添加记录时如果 id 设为 4 会导致冲突,说明事务 1 的修改已经写入了。在演示时就翻过这样的错误,id 不会自增真麻烦…😕</p></blockquote><p>所以 <strong>可重复读等级 没有解决 串行化异常的问题。</strong></p><h4 id="4-可串行化-1"><a href="#4-可串行化-1" class="headerlink" title="4.可串行化"></a>4.可串行化</h4><p><img src="https://s2.loli.net/2024/03/19/ZtJLP3Sr5xpwdmK.png" alt="serializable read in Postgres"></p><p>提交事务 2 时报错,并给出了提示,在执行一次相同操作即可成功。我试了一下再次 commit,提交成功了,然后查询所有账户,事务 2 添加的那条记录没有添加上去。这两个事务没有插入相同的记录了。</p><p>Postgres 使用<strong>依赖检测机制</strong>来检测潜在的读操作,阻止它们并抛出错误。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><table><thead><tr><th align="center">隔离等级</th><th align="center">脏读</th><th align="center">不可重复读</th><th align="center">幻读</th><th align="center">串行化异常</th></tr></thead><tbody><tr><td align="center">读未提交</td><td align="center"><strong>允许,但在 PG(postgres)中不行</strong></td><td align="center">可能</td><td align="center">可能</td><td align="center">可能</td></tr><tr><td align="center">读已提交</td><td align="center">不可能</td><td align="center">可能</td><td align="center">可能</td><td align="center">可能</td></tr><tr><td align="center">可重复读</td><td align="center">不可能</td><td align="center">不可能</td><td align="center"><strong>允许,但在 PG 中不行</strong></td><td align="center">可能</td></tr><tr><td align="center">可串行化</td><td align="center">不可能</td><td align="center">不可能</td><td align="center">不可能</td><td align="center">不可能</td></tr></tbody></table><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p>参考:</p><p><a href="https://www.youtube.com/watch?v=4EajrPgJAk0&list=PLy_6D98if3ULEtXtNSY_2qN21VCKgoQAE&index=10">YouTube-TECH SCHOOL</a></p><p><a href="https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html">MySQL document</a></p><p><a href="https://www.postgresql.org/docs/current/transaction-iso.html">Postgres document</a></p>]]></content>
<categories>
<category>数据库</category>
</categories>
<tags>
<tag>学习记录</tag>
<tag>八股文</tag>
</tags>
</entry>
<entry>
<title>Happy New Year && Happy Birthday~</title>
<link href="/2024/01/01/Happy-New-Year-Happy-Birthday/"/>
<url>/2024/01/01/Happy-New-Year-Happy-Birthday/</url>
<content type="html"><![CDATA[<p>新年快乐,同时今天也是 四宫辉夜 的生日 🎉!</p><span id="more"></span><p>♡•<em>¨**・°: 。・ : 。 :゚・</em><br>𝑯𝒂𝒑𝒑𝒚 𝑩𝒊𝒓𝒕𝒉𝒅𝒂𝒚<br>&<br>𝑯𝒂𝒑𝒑𝒚 𝑵𝒆𝒘 𝒀𝒆𝒂𝒓<br>_・°: 。 :・。 :゚・_•.♡•*¨</p><p><img src="https://s2.loli.net/2024/01/01/WcsnMlxkYUIj9ar.jpg" alt="辉夜酱"></p><hr><p>对了,还忘了一件 “妃” 常重要的事,今天也是四条真妃的生日 🤣,也附上图吧:</p><p><img src="https://s2.loli.net/2024/01/01/J1KXwBgWoyHNubt.jpg" alt="四条真妃"></p><blockquote><p>四条真妃不是败犬 🥺</p></blockquote><p>图片来源:<a href="https://twitter.com/anime_kaguya">@anime_kaguya</a></p>]]></content>
<tags>
<tag>日常记录</tag>
</tags>
</entry>
<entry>
<title>Christmas Tree</title>
<link href="/2023/12/11/Christmas-Tree/"/>
<url>/2023/12/11/Christmas-Tree/</url>
<content type="html"><![CDATA[<p><img src="https://s2.loli.net/2023/12/20/SqpX35YmD9HEVKs.png" alt="Christmas Tree"></p><blockquote><p>It is a Christmas tree to celebrate Christmas and joy someone.</p></blockquote><span id="more"></span><p>我一开始打算用 <code>go + fyne</code> 画个GUI的圣诞树,因为写好的程序可以打包很方便,发给别人看也可以直接得到效果,不需要配环境。但是学了几天,我发现 <code>fyne</code>不好用(这只是我的主观看法,没有任何其他意思),跟着官方文档学的时候遇到最多的问题就是<code>fyne.io/fyne</code> 和 v2 不兼容:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">CanvasObject (wrong <span class="hljs-built_in">type</span> <span class="hljs-keyword">for</span> method MinSize)<br> have MinSize() <span class="hljs-string">"fyne.io/fyne/v2"</span>.Size<br> want MinSize() <span class="hljs-string">"fyne.io/fyne"</span>.Size<br></code></pre></td></tr></table></figure><p>大概率是我太菜了,不懂怎么改。</p><p>后来我选择了前端,这个更方便。然后我去 Github 找大佬写的 demo, 没花多久就找到了一个我想要的,简直太棒啦!我在大佬的项目上修修改改,加了个根据当前时间来显示不同的画面的功能然后就直接拿来用了。我在修改注脚的时候发现 <code>@Hao Chen</code> ,本来没太在意,然后我加了个超链接跳转到原作者的仓库,我看到原仓库下有个网址,是 <a href="https://coolshell.cn/">酷壳</a> ,然后我看着原作者的头像觉得好像在哪见过,又看了看名字,不会是陈皓大佬吧?!然后我又想起注脚,哦,真的是那个 “左耳朵耗子” !几个月前刚听到大佬因心梗去世的消息时回忆起我初学编程时老师推荐我们逛酷壳等一些技术博客学习,我学习指针时还是看 <a href="https://coolshell.cn/articles/11377.html">《C语言结构体里的成员数组和指针》</a></p><p>解惑的,皓哥分析的很详细,不过当时的我看的很懵,因为刚学,不懂gdb,所以gdb那部分就略过去了…</p><p>没想到,我学编程的路上一直有皓哥的帮助。R.I.P</p><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p><a href="https://github.com/haoel/christmas">原仓库链接</a></p>]]></content>
<tags>
<tag>日常记录</tag>
</tags>
</entry>
<entry>
<title>最近计划 & 想法 记录</title>
<link href="/2023/11/23/recent-plan/"/>
<url>/2023/11/23/recent-plan/</url>
<content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="抱歉, 这个密码看着不太对, 请再试试." data-whm="抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容."> <script id="hbeData" type="hbeData" data-hmacdigest="2ade4861d666f3f64677b19061e49a75fb27e2ba7b63ef364412474055aee2ac">f386c6c45fc09957aa9dff3c5ab71ed0b64b1f9db9d1af0252d3649bb6874811c56e6eda0f35c84ce50eb7ae9a65ccdd02cf5b42b914e8dedb0a8435ad70f44085b938382f83058f5b5e2c8d2a01e159c57567914cf24bb2821d1af432e4bc7eafb3ea27a85058c207ae310f1abc18e8ca7b1c3520362edbd6c9cf46803b7d2a88f2bbf2d9a506c6c7d7456499b7794f3d84768c68bcac6a835394c312b202699b4e5e6c63412730466332b6d4eede591799c2edf4cf4bafcc22c4be59ee1090c8fbdb9d7b85a0f55a3a64ef371211194c9817e443e26a78b5fc16edd4c603a89293e0bcbf210946daea2bfa4a164b41b231b6d6db4d2d455a0b640a17e74023eb16ccbb24c42235b79ebc941e2c6b1f2c95ddfc8243002a07de1d62bb3e5c6fb2ec8d869940f20dad4ca8e928e4892098e617beb29ac7a8939c3d7d84d00b6374b7e1349e375a3741956bbc15894e3115224db8a0ce0862ee30513069fcba2eb09f4729e4df832e25c4d67e969a1b58092af3401642c6c5511b66698629d25ee79fa5ecaa0fa92b8818bc99f0dbc45e9b9ba166a2f3af202a591f3cd3c3d4e77f82365fc6579c49cc1c8f892a03db9431e74ee33a441d4156294e11c9457f44ce37ccbe87c1c66e8f087ef2cdf25a990147ef620eb332f4d6ae0b9a7d1768e4e5b55d7f536b02511601c9ba473d20980d496273ce228443e51ecd9311f714463d7f829b696333ab3008360adf8e7cb4b5bc9e24b6e49e694695050c140d5df618f4e7a5d03298beaac957c5cd85ca6015761bce9aec81337769b3fc5dbad26eb477c407a2324e665df708e03968bdfb8c0cd5dac920de7fd4903d825ae57f2a62c99d425abade95c00e3202f601002a4c08b0f1900d326f1ddaf746a9d4b532235fc6e40b3fe604d3e7c2789697cf48dc3708abd9e76011c97b7aa41057bdcd75328158715f0007d7bf8a1ced293f313b03cd56617a9aca140fb7a6b120ac7f3b3297d39f4b93ae37166dda53266e152802bb3487f9ed799371b45e7cfca4d298ebfead41738633390d765007ab5238f6cafe8273e7447637148688894316a0d89c228901a79fc0706e9cad65fce22f83901cbb0187c9a1498d64f1409b49e14b935a5e1701327c9314cba746b5dcbd1f09bea01df3f2aa801887dfa1e1018e64e611baa2af572a01867f0bb57c1805fa7bff48000d1a7cbe683804651b802cf6e9b3fee63c2fe410d5d3920abb3301ccc75874d14ff0a1d186bcf04b044cb1339010c3059214a8445cbc3f7a8beb354a9a76f5f5c8cb08a734c60c47c1a99dd9d7f33fca45cf17128c53487fa96cb6418fe3d432a3215217087ff4de3d3dc876694888bb4e4b45d5d9673a6fe831e8ecd359ec24c9f127abb6705647195e2716b3ab8811b320244049ba1af7946406a66186fed9b930f6251fe1e4d7493ea464c58e0c9051fed90099bf6b85e13431474165b668ac3af9e0da5e85ac6f717d2fa017f04de5b3f32dd7183f8ccf6343830ba91da33254f7bea1f84c198d0147a9b269e705dafd08732b2f112338d86f0c3dfff835c2097c491999cc77f68cf24ed8be7fbe5e532bf5d53894b9e184ef03e64f7dd377f09e9c322e62fed50cdf93565acba3a8f322c53b2a7c7602e25bf80cb59e2551022f6cee87f7b7ac691079bbda430000b20d5baeb1b4c5dd4adaeb338084f0bfdd0766778889c96f302f497f81f17de78eb20f8a8512321d0f6941bca1252ff06812225cbd20b80805309e85c8bcb684e5d4dd4decabebe38e426fcd7d4ddaf4b474bb6cf023c806a176fb71115eb3407a71f93f048b2b3becc13d8ddd53baadb54923731727e615356e3a417377b4f816061c16aa66b5c55c1f1e4915b5cf99d27d7665a43109dba41ac2bfe605747351ebbf20731fd17058dec6cd8f85c79bf15285485e165eafe9355a8c2fb824cfd51e5ef72a34de207c4633f904cdf06849043b6e97c8020a823048a07f713df28f245d9e1368c1dabbeb2c6e41a0ccb560151a98d8d77ee90d60e5a626a31ad4c9b3ce211dc59a6fd5dda7c05be4ec3022b0748026631066202f0ebb37cd5435033499940d34596b7afc8b7bd96ea0bf27960f5df3d688542785c6eed625c5dd2a9974552bde1e8a4f007852696b943cce5c9aa449754313e52d75bf201b8417095bf04378676d55c47d6e6286e0d89eddfe028cc10d17b087b7dfc1c99612a34060c18eef818032225039633e626107e13fce3b624be2c17add021f7b4481251e2e2110c2d13afa8661f85edb3fa98887c3432809e4226cac3c14fa94189e93cf10a6f580e6858db8bc3a4a9bfb0fa7e5041b9dd850c343d3e5a86042459bc6b5651727319728b536290c81adbb4f860cfc1e4852778fc685f079b939048993522742ccc98eb78326803e64159f304b86982900320c9797e468337dcec8a58920cea25935c5b0ae0c0ba36ee1632d62ef5e09425591ec4774168667adb9e3e0b43550ecaf49a77db962a7346ac285159e90476a3c8a4f98dc703eb6a58d4c844765a7658de5c241e6a722b7806e6592fc08600d6371daa4ad66bc9564d60f2fcbf6214660822a5213ee0d44260b194ec439c2fc18db216b3c7ee0224d0cc86b48d23a8fdf360f8f5703c1e004538f6a1ee1d61600d3ffeaad144e3671760c40474ef3d45d4203e0a49a89a3fe155285f1caf5dc71cf27f7d1e8db6cc9688b0c9d65c29cc50668fe5bc359663f31dcf6249094a5e9de9ab9be3cfdc3e359f592a36ac8813125778aed6d05bf522958fe5497ad585e277a02bb022ee2fc500bd8bce1d0537e2669ea30d2e3adfdf8b7ffa2d7dc3f0060e544bd32aa3b80c827b9c97c9926fa357ade31bd43ec38b5a7159322a79abcf3d83d2c8ae0408c2493555fe63227704ae2025b4199e0b6af33a1f12378ee2ec7451e15bfaab839177e051c4574ef36d4b16dd127a5418c27e26e72d27dfd621f3a272aff454a1b9be0a3e0da1a3afbd562ff998b3abaaca8209c429623cb9a61814ae80a03166db3bcb92bab41ad1d1d1097f4079267f345f9ecb39665f0876cdb42c8c62e7a5937de1574d122690174768ef2b657fa8c8ede53a7bf79bc4904b4332d864ef425077c6e7c51a382e032ce360b45ef290fe93002ed678dea3f652cbda0ea6338e9cd5ecfd68339f32c5e0d116b6b3d4b398705e09b073d31819dcd7c5974f8a4f001ec17b4fe9b9591b7f3fbca70438e3de4fcefd6cab58cb28dbd4e37083b0fdd332053f88b1a1e9224d7728ea3c38c3ef22267925a3b7b4df60777ba3638e106e0948513f268a0318031c6c51f51ff3604a0fcf64eb37b3e1091d5cc0b3aaf7ac015767ed71884e51db1ed572fd2ac829c6c506543fd4f212ec858cf2029a1d3bec1008db65008c02d0eedbc4e3eb16ca02a05b2fe93cbb5ff866587ec32f6c04588cdd8cfc0cf597cb332fbee30ceefe84a178424c6a15684a41598c3042022f101659350b71f9944d0209dd8147e5d67d1213b02d32778caaebb659837f8c07b0cca7293079cb656173caea17b406e7ab90acbbb3a259591a09ff3fd7999ed3cdddb87fc0bf482c7612d474fed5002ca8c5e2d86b886c6b9864e2d821dbb5605673ea03d0ae48ec9948331cb8799cc555646c66c23496b90171f0f6e85fc431bb69f0ceef8487af7cd29bd227d827b7be095badd837f67ec6803c1874382ec86052b3ef499667c75218b07932a95f765d72346e4921b2ff4901ee00055090635eabed0dd82ec8068e5778adf0ce011a533b360e071bd4aa353f14372557810dd0316490070c9fbb73f2832df42becfea7ce86546835f1966c7695cee151cfaa5e0227ab8be58e4f516a4262ea61949dca9bbd0fa3c54e28a00f1085571432807e124d273d054c57a577f540c421f91ba05ec809e02249979e33f53ef4a368e4261ddf016535aaf57f31765754e0c374c8d3cacb60dca6dd57767f5ae12c0d0239b4e020c9ce27d06b408c1827454598604fb5fbec029d395b5a8a75d7516397a3b1c1c89e600c2ddeb65f85fb0a1cf61a5382062beee85b7b9360503f996b5cfb71472814b39835606777b738b94c858e2807d3788361dff690b74bba53f32f8b74acce8a5419b94e2800d1456ef9d31c30d4305e5efa89dd4199689e34d36b0b4134554fb61b936b46a27581c663633a8a1d1428d840407dd7bb17fd2ce89c87f9e82b2052bcff8cb21571415f73a7d0b5a0c280955a63b03c71948ec929ca719e770e2e4354c3d292d1276412951a519a6644d33027a82d6d5004e4012d185ccebcd31fb9e6cd85307e5a21351d7f6f222bf84a9aea8999fb9e9072b98da333d49bc34f0af9ed61fd1d19915b570d7c95dc7f451a90d51798e28b303abf007ec144776227d8624dad67993d3cefac4731f12da9c71c578f11b24f64c5e72fda4f4bab82091a436e9165b7a4dca20026ce6e2dae51167be18039cb26a679d2717ff5a9c536b6eb6530a9eabe97dee9d4cecde5b198587b798247e8d7ec881a6763e4553723f64cce9098b0231fb7938a9476b3dc886dfc6aa5362d78ec280a25a6c4f3f7298ade30061a012a6a8e02f5d546c6b9f871488e3ce2945421ad48679154903ad3212d4bebf8758a1bec0c05d5ad3f19c3e12504dda2196608f44b9aaf8568701c614f66e5468485f4f6b2c05a20c47adf4a0881b84891b06e88dc6aece170014ac1bc37db33e06f404a615f74f822273e0af5e77cbf85a6ea2c1795876c672a0c733f22fc50b191744c735373f075827ce00062a1dd7f175d679cb6a55b4ded0b8686f739993e0fd3d8c53933365cce97c3da92a91f962962ef910aaf18ef13fbc4dbf611deab3becee34e3c363eb4e2878e76cc23d4ada51012e60fb59832972065e3db4d7315119d2f3bbeb5b075c4d921a8258f34a40d55e5c670d5b580bb9fbdd85715b83f</script> <div class="hbe hbe-content"> <div class="hbe hbe-input hbe-input-default"> <input class="hbe hbe-input-field hbe-input-field-default" type="password" id="hbePass"> <label class="hbe hbe-input-label hbe-input-label-default" for="hbePass"> <span class="hbe hbe-input-label-content hbe-input-label-content-default">您好, 这里需要密码.</span> </label> </div> </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
<categories>
<category>记录</category>
</categories>
<tags>
<tag>日常记录</tag>
</tags>
</entry>
<entry>
<title>四大请求方式(2)- gin+gorm实现简单crud</title>
<link href="/2023/09/16/%E5%9B%9B%E5%A4%A7%E8%AF%B7%E6%B1%82%E6%96%B9%E5%BC%8F%EF%BC%882%EF%BC%89-gin-gorm%E5%AE%9E%E7%8E%B0%E7%AE%80%E5%8D%95crud/"/>
<url>/2023/09/16/%E5%9B%9B%E5%A4%A7%E8%AF%B7%E6%B1%82%E6%96%B9%E5%BC%8F%EF%BC%882%EF%BC%89-gin-gorm%E5%AE%9E%E7%8E%B0%E7%AE%80%E5%8D%95crud/</url>
<content type="html"><![CDATA[<h2 id="写在最前面"><a href="#写在最前面" class="headerlink" title="写在最前面"></a>写在最前面</h2><p>刚学了 gorm ,想着完善一下<a href="https://kjasn.github.io/2023/08/04/gin-%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-%E5%9B%9B%E5%A4%A7%E8%AF%B7%E6%B1%82%E6%96%B9%E5%BC%8F/">之前的四大请求方式</a>,加上数据库,做一个简单的 crud 。</p><span id="more"></span><h2 id="连接数据库-–-init"><a href="#连接数据库-–-init" class="headerlink" title="连接数据库 – init"></a>连接数据库 – init</h2><p>通过 <code>mysql.Open(dsn)</code> 来连接数据库,然后 <code>gorm.Open()</code> 用于初始化 GORM 数据库连接,当然也还有别的连接方式。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">var</span> DB *gorm.DB<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">init</span><span class="hljs-params">()</span></span> {<br>username := <span class="hljs-string">"root"</span> <span class="hljs-comment">//账号</span><br>password := <span class="hljs-string">"thisIsAPassword"</span> <span class="hljs-comment">//密码</span><br>host := <span class="hljs-string">"127.0.0.1"</span> <span class="hljs-comment">//数据库地址,可以是Ip或者域名</span><br>port := <span class="hljs-number">3306</span> <span class="hljs-comment">//数据库端口</span><br>Dbname := <span class="hljs-string">"crud_demo"</span> <span class="hljs-comment">//数据库名</span><br>timeout := <span class="hljs-string">"10s"</span> <span class="hljs-comment">//连接超时,10秒</span><br><br><span class="hljs-comment">// dsn userName:pwd@tcp(ip:port)/databaseName 这些是必须的</span><br>dsn := fmt.Sprintf(<span class="hljs-string">"%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s"</span>, <br>username, password, host, port, Dbname, timeout)<br><br><span class="hljs-comment">// 初始化 GORM 数据库连接 并设置一些选项 </span><br>db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{<br>NamingStrategy: schema.NamingStrategy{<br>SingularTable: <span class="hljs-literal">true</span>, <br>NoLowerCase: <span class="hljs-literal">true</span>,<br>},<br>})<br><span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {<br>fmt.Println(<span class="hljs-string">"数据库连接失败,err="</span> + err.Error())<br>}<br><br>fmt.Println(<span class="hljs-string">"创建成功: "</span>, db)<br>DB = db<br><br>}<br></code></pre></td></tr></table></figure><h2 id="结构体和API"><a href="#结构体和API" class="headerlink" title="结构体和API"></a>结构体和API</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// ArticleList 文章列表 简要信息</span><br><span class="hljs-keyword">type</span> ArticleList <span class="hljs-keyword">struct</span> {<br>Author <span class="hljs-type">string</span> <span class="hljs-string">`gorm:"type:varchar(10)" json:"author" binding:"required"`</span><br>Title <span class="hljs-type">string</span> <span class="hljs-string">`gorm:"type:varchar(10)" json:"title" binding:"required"`</span><br>Brief <span class="hljs-type">string</span> <span class="hljs-string">`gorm:"type:varchar(30)" json:"brief" binding:"required"`</span><br>}<br><br><span class="hljs-comment">// ArticleModel 全部内容</span><br><span class="hljs-keyword">type</span> ArticleModel <span class="hljs-keyword">struct</span> {<br>gorm.Model <span class="hljs-comment">// id creatTime uT dT</span><br>ArticleList<br>Content <span class="hljs-type">string</span> <span class="hljs-string">`gorm:"type:varchar(1000)" json:"content" binding:"required"`</span><br>}<br><br><span class="hljs-comment">// Response 封装响应格式</span><br><span class="hljs-keyword">type</span> Response <span class="hljs-keyword">struct</span> {<br>Code <span class="hljs-type">int</span> <span class="hljs-string">`json:"code"`</span> <span class="hljs-comment">// 规定 200 -- 正常 400 -- err 399 -- warning</span><br>Date any <span class="hljs-string">`json:"date"`</span><br>Message <span class="hljs-type">string</span> <span class="hljs-string">`json:"msg"`</span><br>}<br></code></pre></td></tr></table></figure><blockquote><p>这里把 ArticleList 从 ArticleModel 中拆分出来,作为 API 来用,接着往下看就知道了~</p></blockquote><hr><h2 id="测试-–-Main函数"><a href="#测试-–-Main函数" class="headerlink" title="测试 – Main函数"></a>测试 – Main函数</h2><p>先初始化了几条数据:</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {<br> <br><span class="hljs-comment">// 添加模型</span><br>DB.Debug().AutoMigrate(&ArticleModel{})<br><br><span class="hljs-comment">//// 初始数据</span><br>DB.Create(&[]ArticleModel{<br>{<br>ArticleList: ArticleList{<br>Title: <span class="hljs-string">"go语言入门"</span>,<br>Brief: <span class="hljs-string">"本书是go语言入门基础 balabala..."</span>,<br>Author: <span class="hljs-string">"作者a"</span>,<br>},<br>Content: <span class="hljs-string">"第一章:认识go语言............."</span>,<br>},<br>{<br>ArticleList: ArticleList{<br>Title: <span class="hljs-string">"c语言入门到入土"</span>,<br>Brief: <span class="hljs-string">"本书是c语言入门教程,面向入土"</span>,<br>Author: <span class="hljs-string">"作者b"</span>,<br>},<br>Content: <span class="hljs-string">"你的第一个C程序: printf(\"hello world\");"</span>,<br>},<br>{<br>ArticleList: ArticleList{<br>Title: <span class="hljs-string">"数据库从删库到跑路"</span>,<br>Brief: <span class="hljs-string">"本书教你如何从删库到跑路"</span>,<br>Author: <span class="hljs-string">"作者c"</span>,<br>},<br>Content: <span class="hljs-string">"没别的,直接跑路吧"</span>,<br>},<br>})<br><br><span class="hljs-comment">// 设置路由 和 请求方式</span><br><br>router := gin.Default()<br><br>router.GET(<span class="hljs-string">"/articles/"</span>, _getList)<br>router.GET(<span class="hljs-string">"/articles/:id"</span>, _getDetails)<br>router.POST(<span class="hljs-string">"/articles/"</span>, _post)<br>router.PUT(<span class="hljs-string">"/articles/:id"</span>, _put) <span class="hljs-comment">// 居然不是 update</span><br>router.DELETE(<span class="hljs-string">"/articles/:id"</span>, _delete)<br><br>err := router.Run(<span class="hljs-string">":80"</span>)<br><span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {<br><span class="hljs-keyword">return</span><br>}<br>}<br></code></pre></td></tr></table></figure><h2 id="查"><a href="#查" class="headerlink" title="查"></a>查</h2><h3 id="文章列表"><a href="#文章列表" class="headerlink" title="文章列表"></a>文章列表</h3><p>不设置条件,通过 <code>Find()</code> 查找所有内容,然后放入到 ArticleList 切片中,这个可以作为一个 api 来限制返回给结果哪些属性。<br>此处仅返回文章简要信息即可。 </p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// 文章列表</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">getList</span><span class="hljs-params">(arg *gin.Context)</span></span> {<br><br><span class="hljs-keyword">var</span> list []ArticleList <span class="hljs-comment">// api</span><br>DB.Debug().Model(&ArticleModel{}).Find(&list)<br><br><span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(list) == <span class="hljs-number">0</span> {<br>arg.JSON(http.StatusOK, Response{<span class="hljs-number">0</span>, <span class="hljs-string">"内容为空"</span>, <span class="hljs-string">"无结果"</span>})<br>} <span class="hljs-keyword">else</span> {<br>arg.JSON(http.StatusOK, Response{http.StatusOK, list, <span class="hljs-string">"响应成功"</span>})<br>}<br>}<br></code></pre></td></tr></table></figure><h3 id="文章详情"><a href="#文章详情" class="headerlink" title="文章详情"></a>文章详情</h3><p>从请求中拿到 id 然后去数据库中查找,并通过 <code>ret.RowsAffected == 0</code> 来判断是否查找到对应文章。一开始我用 <code>ret.Error != nil</code><br>作为判断,但测试时输入错误的 id 没有提示,还是会返回,不过返回的是空值。</p><p><img src="https://s2.loli.net/2023/09/16/ZA4xUDhwE89clpk.png" alt="p1-查询错误返回空值"></p><p>控制台也没有提示:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">获取到<span class="hljs-built_in">id</span>: 9999<br>[0.626ms] [rows:0] SELECT * FROM `ArticleModel` WHERE <span class="hljs-built_in">id</span> = <span class="hljs-string">'9999'</span> AND `ArticleModel`.`DeletedAt` IS NULL<br></code></pre></td></tr></table></figure><p>可见是未查找到时没有进入第一个分支。后来知道 Find 方法不会返回 <code>gorm.ErrRecordNotFound</code> 错误,当没有匹配的记录时,它将返回一个零值对象。<br>有两种解决方式: 1. 可以改用 First 2. 把条件判断改为 <code>ret.RowsAffected == 0</code></p><p>修改后:</p><p><img src="https://s2.loli.net/2023/09/16/IKvyTwjW9rY8GNt.png" alt="p2-修改查询部分的错误后"></p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// 文章详情</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">getDetails</span><span class="hljs-params">(arg *gin.Context)</span></span> {<br><br>bookId := arg.Param(<span class="hljs-string">"id"</span>)<br>fmt.Printf(<span class="hljs-string">"获取到id: %v\n"</span>, bookId)<br><br><span class="hljs-keyword">var</span> article ArticleModel<br>ret := DB.Debug().Where(<span class="hljs-string">"id = ?"</span>, bookId).Find(&article)<br><br><span class="hljs-keyword">if</span> ret.RowsAffected == <span class="hljs-number">0</span> {<br>fmt.Println(<span class="hljs-string">"未查找到id为"</span>, bookId, <span class="hljs-string">"的文章"</span>)<br>arg.JSON(http.StatusOK, Response{<span class="hljs-number">0</span>, <span class="hljs-string">"内容为空"</span>, <span class="hljs-string">"查找失败,文章不存在!"</span>})<br>} <span class="hljs-keyword">else</span> {<br>arg.JSON(http.StatusOK, Response{http.StatusOK, article, <span class="hljs-string">"响应成功"</span>})<br>}<br>}<br></code></pre></td></tr></table></figure><h2 id="增-改"><a href="#增-改" class="headerlink" title="增 & 改"></a>增 & 改</h2><p>常用的几种类型都可以直接 <code>shouldBind()</code> 来处理,所以删除了<a href="https://kjasn.github.io/2023/08/04/gin-%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-%E5%9B%9B%E5%A4%A7%E8%AF%B7%E6%B1%82%E6%96%B9%E5%BC%8F/">之前文章</a>用的 <code>_bindJson()</code></p><hr><p>同前面一样用 <code>ret.RowsAffected == 0</code> 作为判断条件。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// 修改文章</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">put</span><span class="hljs-params">(arg *gin.Context)</span></span> {<br><span class="hljs-comment">// 拿到id</span><br>bookId := arg.Param(<span class="hljs-string">"id"</span>)<br>fmt.Printf(<span class="hljs-string">"获取到id: %v\n"</span>, bookId)<br><br><span class="hljs-keyword">var</span> article ArticleModel<br><span class="hljs-comment">// 拿到修改后的文章内容</span><br>err := arg.ShouldBind(&article)<br><span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {<br>fmt.Println(err)<br>arg.JSON(http.StatusBadRequest, Response{<span class="hljs-number">0</span>, <span class="hljs-literal">nil</span>, <span class="hljs-string">"请求数据验证失败"</span>})<br><span class="hljs-keyword">return</span> <span class="hljs-comment">// 验证失败,直接返回</span><br>}<br><br>ret := DB.Debug().Where(<span class="hljs-string">"id = ?"</span>, bookId).Updates(&article)<br><span class="hljs-keyword">if</span> ret.RowsAffected == <span class="hljs-number">0</span> {<br>fmt.Println(<span class="hljs-string">"不存在id为"</span>, bookId, <span class="hljs-string">"的文章"</span>)<br>arg.JSON(http.StatusOK, Response{<span class="hljs-number">0</span>, <span class="hljs-string">"内容为空"</span>, <span class="hljs-string">"查找失败,文章不存在!"</span>})<br>} <span class="hljs-keyword">else</span> {<br>fmt.Println(<span class="hljs-string">"id为"</span>, bookId, <span class="hljs-string">"文章已被修改"</span>)<br>arg.JSON(<span class="hljs-number">200</span>, Response{http.StatusOK, article.UpdatedAt, <span class="hljs-string">"修改成功"</span>})<br>}<br><br>}<br><br><span class="hljs-comment">// 删除文章</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">delete</span><span class="hljs-params">(arg *gin.Context)</span></span> {<br><span class="hljs-comment">// 拿到 id</span><br>bookId := arg.Param(<span class="hljs-string">"id"</span>)<br>fmt.Printf(<span class="hljs-string">"获取到id: %v\n"</span>, bookId)<br><br><span class="hljs-comment">// 查找 id</span><br><span class="hljs-keyword">var</span> data ArticleModel<br>ret := DB.Debug().Where(<span class="hljs-string">"id = ?"</span>, bookId).Find(&data)<br><br><span class="hljs-keyword">if</span> ret.RowsAffected == <span class="hljs-number">0</span> {<br>fmt.Println(<span class="hljs-string">"未查找到id为"</span>, bookId, <span class="hljs-string">"的文章"</span>)<br>arg.JSON(http.StatusOK, Response{<span class="hljs-number">0</span>, <span class="hljs-string">"不存在该文章"</span>, <span class="hljs-string">"删除失败!"</span>})<br>} <span class="hljs-keyword">else</span> {<br>DB.Debug().Delete(&data) <span class="hljs-comment">// 删除</span><br>deleteTime := data.DeletedAt<br><span class="hljs-comment">// 实际上,不会真的删除,只会标记一个删除时间</span><br>DB.Debug().Model(&ArticleModel{}).Select(<span class="hljs-string">"DeletedAt"</span>).Where(<span class="hljs-string">"id = ?"</span>, bookId).Find(&deleteTime)<br>arg.JSON(<span class="hljs-number">200</span>, Response{http.StatusOK, gin.H{<span class="hljs-string">"删除时间"</span>: deleteTime}, <span class="hljs-string">"删除成功"</span>})<br>fmt.Println(<span class="hljs-string">"id为"</span>, bookId, <span class="hljs-string">"文章已被修改"</span>)<br>}<br><br>}<br></code></pre></td></tr></table></figure><ul><li>一开始我设置的 Content 字段有默认值 <code>default:"这个人很懒,没有写任何内容..."</code> 但它又是一个必填项。</li></ul><p>结果如下:</p><p><img src="https://s2.loli.net/2023/09/17/iZDhmCc5vpyNO97.png" alt="默认值和必填项冲突"></p><p>实际上,由于<strong>接收请求是发生在将数据添加到数据库之前,所以默认值就不起作用了</strong>。</p><ul><li>另外我犯的错误是在第 10 行的 if 分支里面,只是输出错误,而<strong>没有返回终止后面的程序</strong>,所以在绑定参数时,对于必填项但没有填的只会输出错误,然后继续将这条数据添加到数据库</li></ul><h2 id="删"><a href="#删" class="headerlink" title="删"></a>删</h2><p>在执行删除操作时,实际上,不会真的删除数据,只会标记一个删除时间,每次查找时,都会加上条件 <code>DeletedAt IS NULL</code> ,即没有标记过删除时间。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// 删除文章</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">delete</span><span class="hljs-params">(arg *gin.Context)</span></span> {<br><span class="hljs-comment">// 拿到 id</span><br>bookId := arg.Param(<span class="hljs-string">"id"</span>)<br>fmt.Printf(<span class="hljs-string">"获取到id: %v\n"</span>, bookId)<br><br><span class="hljs-comment">// 查找 id</span><br><span class="hljs-keyword">var</span> data ArticleModel<br>ret := DB.Debug().Where(<span class="hljs-string">"id = ?"</span>, bookId).Find(&data)<br><br><span class="hljs-keyword">if</span> ret.RowsAffected == <span class="hljs-number">0</span> {<br>fmt.Println(<span class="hljs-string">"未查找到id为"</span>, bookId, <span class="hljs-string">"的文章"</span>)<br>arg.JSON(http.StatusOK, Response{<span class="hljs-number">0</span>, <span class="hljs-string">"不存在该文章"</span>, <span class="hljs-string">"删除失败!"</span>})<br>} <span class="hljs-keyword">else</span> {<br>DB.Debug().Delete(&data) <span class="hljs-comment">// 删除</span><br>deleteTime := data.DeletedAt<br><span class="hljs-comment">// 实际上,不会真的删除,只会标记一个删除时间</span><br> DB.Debug().Model(&ArticleModel{}).Select(<span class="hljs-string">"DeletedAt"</span>).Where(<span class="hljs-string">"id = ?"</span>, bookId).Find(&deleteTime)<br> <span class="hljs-comment">// `SELECT `DeletedAt` FROM `ArticleModel` WHERE id = '27' AND `ArticleModel`.`DeletedAt` IS NULL` </span><br><br>arg.JSON(<span class="hljs-number">200</span>, Response{http.StatusOK, gin.H{<span class="hljs-string">"删除时间"</span>: deleteTime}, <span class="hljs-string">"删除成功"</span>})<br>fmt.Println(<span class="hljs-string">"id为"</span>, bookId, <span class="hljs-string">"文章已被修改"</span>)<br>}<br><br>}<br></code></pre></td></tr></table></figure><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p>可以说这次简单的crud主要时间就花在修bug,各种各样的bug。`(<em>>﹏<</em>)′<br>算是大概修完了吧。等以后学了更多东西再迭代一次(写bug,修bug)。</p><p>再补一个图:</p><p><img src="https://s2.loli.net/2023/09/17/Yp8nFgPe6ZjdatC.png" alt="summer pockets"></p><blockquote><p>感谢夏日口袋陪伴我度过了这个夏天,夏日结束了,我的冒险还未结束~</p></blockquote>]]></content>
<tags>
<tag>gin</tag>
<tag>gorm</tag>
</tags>
</entry>
<entry>
<title>Git 基本使用方法</title>
<link href="/2023/08/30/Git-%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/"/>
<url>/2023/08/30/Git-%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/</url>
<content type="html"><![CDATA[<h2 id="1-1-Git-目录介绍"><a href="#1-1-Git-目录介绍" class="headerlink" title="1.1 Git 目录介绍"></a>1.1 Git 目录介绍</h2><span id="more"></span><p><strong>项目初始化</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">mkdir</span> git_study <span class="hljs-comment"># 随便创建一个目录</span><br><span class="hljs-built_in">cd</span> git_study <span class="hljs-comment"># 切换到该目录下</span><br>git init <span class="hljs-comment"># 初始化 之后会得到一个 .git 的目录</span><br><br><span class="hljs-comment"># 环境为 windows 10</span><br><span class="hljs-comment"># 使用 tree 查看 .git 目录结构,失败了:</span><br>tree .git <br>tree .git bash: tree: <span class="hljs-built_in">command</span> not found<br></code></pre></td></tr></table></figure><p>windows下的 <code>git</code> 没有 <code>tree</code> 命令,默认调用的是<code>cmd</code>的<code>tree</code>命令,而<code>cmd</code> 提供的 <code>tree</code> 命令比较特殊,并不是常见的 <code>.exe</code> 结尾文件,而是 <code>.com</code> 结尾的文件。去<a href="https://gnuwin32.sourceforge.net/packages/tree.htm">下载</a><code>tree-1.5.2.2-bin.zip</code>,解压,然后将 <code>tree-1.5.2.2-bin\bin\tree.exe</code> 文件复制到<code>git Bash</code> 的安装目录下 <code>Git\usr\bin</code> 下,然后就能使用<code>tree</code>命令了:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ tree .git<br>.git<br>|-- HEAD <span class="hljs-comment"># 当前指向的分支</span><br>|-- config <span class="hljs-comment"># 配置文件</span><br>|-- description<br>|-- hooks<br>| |-- applypatch-msg.sample<br>| |-- commit-msg.sample<br>| |-- fsmonitor-watchman.sample<br>| |-- post-update.sample<br>| |-- pre-applypatch.sample<br>| |-- pre-commit.sample<br>| |-- pre-merge-commit.sample<br>| |-- pre-push.sample<br>| |-- pre-rebase.sample<br>| |-- pre-receive.sample<br>| |-- prepare-commit-msg.sample<br>| |-- push-to-checkout.sample<br>| `-- update.sample<br>|-- info<br>| `-- exclude<br>|-- objects<br>| |-- info<br>| `-- pack<br>`-- refs<br> |-- heads<br> `-- tags<br></code></pre></td></tr></table></figure><h3 id="1-1-1-Git-Config"><a href="#1-1-1-Git-Config" class="headerlink" title="1.1.1 Git Config"></a>1.1.1 Git Config</h3><p>不同级别的 Git 配置:<code>system > global > local</code> (按照级别高到低的顺序)。</p><p>每个级别的配置可能重复,但是<strong>低级别的配置会覆盖高级别的配置。</strong></p><h3 id="1-1-2-常见-Git-配置"><a href="#1-1-2-常见-Git-配置" class="headerlink" title="1.1.2 常见 Git 配置"></a>1.1.2 常见 Git 配置</h3><ul><li>用户名配置</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">git config --global user.name <span class="hljs-string">"yourname"</span><br>git config --global user.email [email protected]<br><span class="hljs-comment"># 查看用户名 后面不加参数就行</span><br>git config --global user.name <span class="hljs-comment"># 查看邮箱同理</span><br></code></pre></td></tr></table></figure><ul><li>Instead of 配置</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># eg: 将 ssh 协议转换为 http 协议</span><br>git config --global [email protected]:.insteadOf https://github.com/<br></code></pre></td></tr></table></figure><ul><li>Git 命令别名配置<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># eg:</span><br>git config --global alias.cin <span class="hljs-string">"commit --amend --no-edit"</span><br></code></pre></td></tr></table></figure></li></ul><h2 id="1-2-Git-Remote"><a href="#1-2-Git-Remote" class="headerlink" title="1.2 Git Remote"></a>1.2 Git Remote</h2><ul><li><p>查看 Remote</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 查看已添加的远程仓库</span><br>git remote -V<br></code></pre></td></tr></table></figure></li><li><p>添加 & 删除 Remote 仓库</p></li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">git remote add repoName repoAddr <span class="hljs-comment"># 添加 repoName 远程仓库名 repoAddr 远程仓库地址</span><br>git remote remove repoName <span class="hljs-comment"># 删除</span><br><span class="hljs-comment"># eg: </span><br>git remote add origin_ssh [email protected]:git/git.git <span class="hljs-comment"># 添加 [email protected]:git/git.git(该地址为 ssh 协议,下一行的是 http 协议) ,命名为 origin_ssh ,以下同理</span><br>git remote add origin_http https://github.com/git/git.git<br></code></pre></td></tr></table></figure><p>演示如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ git remote add test_origin [email protected]:this/is/a_test.git <span class="hljs-comment"># 添加 该地址是随便写的...</span><br>$ git remote -v <span class="hljs-comment"># 查看</span><br><br>test_origin [email protected]:this/is/a_test.git (fetch)<br>test_origin [email protected]:this/is/a_test.git (push)<br></code></pre></td></tr></table></figure><p><strong>添加后,这个地址将同时用于pull和push操作,除非你明确地配置了不同的URL用于pull和push</strong>,上面的fetch类似于pull,<a href="#anchor1">具体在后面会讲到</a>。</p><p><strong>只能修改push 的 url</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">git remote set-url --push repoName url<br></code></pre></td></tr></table></figure><p>演示如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ git remote set-url --push test_origin https://github.com/another/repos/url.git <span class="hljs-comment"># 设置 test_origin仓库的 push url 为 https://github.com/another/repos/url.git</span><br></code></pre></td></tr></table></figure><p>结果:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ git remote -v<br>test_origin [email protected]:this/is/a_test.git (fetch)<br>test_origin [email protected]:another/repos/url.git (push) <span class="hljs-comment"># 修改后的地址</span><br></code></pre></td></tr></table></figure><p>也可以通过<code>cat .git/config</code> 来查看远程仓库的配置,经过上述操作,然后可以看到以下三个远程仓库信息:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ <span class="hljs-built_in">cat</span> .git/config<br>[core]<br> repositoryformatversion = 0<br> filemode = <span class="hljs-literal">false</span><br> bare = <span class="hljs-literal">false</span><br> logallrefupdates = <span class="hljs-literal">true</span><br> symlinks = <span class="hljs-literal">false</span><br> ignorecase = <span class="hljs-literal">true</span><br><br>[remote <span class="hljs-string">"test_origin"</span>]<br> url = [email protected]:this/is/a_test.git<br> fetch = +refs/heads/*:refs/remotes/test_origin/*<br> pushurl = https://github.com/another/repos/url.git<br></code></pre></td></tr></table></figure><h2 id="1-3-Git-Add"><a href="#1-3-Git-Add" class="headerlink" title="1.3 Git Add"></a>1.3 Git Add</h2><p>通过<code>git add</code>命令将文件添加到缓冲区。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs bash">Ace@MacBook-Air-15 MINGW64 /d/git_study (main)<br>$ <span class="hljs-built_in">touch</span> readme.md<br><br>$ vim readme.md <span class="hljs-comment"># 写入内容: Hello, I am a readme file.</span><br><br><br>Ace@MacBook-Air-15 MINGW64 /d/git_study (main)<br>$ git status<br>On branch main<br><br>No commits yet<br><br>Untracked files: <span class="hljs-comment"># 表示有未加入缓冲区的文件</span><br> (use <span class="hljs-string">"git add <file>..."</span> to include <span class="hljs-keyword">in</span> what will be committed)<br> readme.md<br><br>nothing added to commit but untracked files present (use <span class="hljs-string">"git add"</span> to track)<br><br>Ace@MacBook-Air-15 MINGW64 /d/git_study (main)<br>$ git add . <span class="hljs-comment"># 加入缓冲区</span><br><br>Ace@MacBook-Air-15 MINGW64 /d/git_study (main)<br>$ git status<br>On branch main<br><br>No commits yet<br><br>Changes to be committed:<br> (use <span class="hljs-string">"git rm --cached <file>..."</span> to unstage)<br> new file: readme.md<br></code></pre></td></tr></table></figure><p>查看<code>.git</code>目录结构,发现<code>objects</code>增加了一些内容</p><ul><li><p>前<br><img src="https://s2.loli.net/2023/10/09/7nzsw64rXRjlY3b.png" alt="before git add"></p></li><li><p>后<br><img src="https://s2.loli.net/2023/10/09/D7iIoH56vXWtbZU.png" alt="after git add"><br>(增加的是文件的id)</p></li></ul><p>通过文件的id查看文件内容:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ git cat-file -p 477d2427d8b7d6e7a02f705da6479569ed7eb825 <span class="hljs-comment"># id</span><br>Hello, I am a readme file.<br></code></pre></td></tr></table></figure><h2 id="1-4-Git-Commit"><a href="#1-4-Git-Commit" class="headerlink" title="1.4 Git Commit"></a>1.4 Git Commit</h2><p>通过<code>git commit</code>命令提交。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">git commit -m <span class="hljs-string">"description"</span> <span class="hljs-comment"># -m 用来加注释 </span><br></code></pre></td></tr></table></figure><p>提交上面创建的 readme.md,之后会发现object目录下多了<strong>两个</strong>文件(45和a2开头的id):</p><p><img src="https://s2.loli.net/2023/10/07/lyaXT7pfCLe2hHS.png" alt="after committed readme"></p><blockquote><p>下面会讲到</p></blockquote><h2 id="1-5-object"><a href="#1-5-object" class="headerlink" title="1.5 object"></a>1.5 object</h2><p>object(对象)是Git的基本数据单元,用于存储和管理项目的内容。</p><p>Git中有四种主要类型的对象,它们分别是:</p><ul><li>Blob 存储文件的内容</li><li>Tree 存储同一次提交的所有文件的目录信息,<strong>每次不同的提交都会创建不同的tree对象。</strong></li><li>Commit 存储提交信息,一个 Commit 可以对应唯一版本的代码,即<strong>每次提交都会有一个commit。</strong></li><li>Tag (后面会再次提到)</li></ul><p>关联如下图:</p><p><img src="https://s2.loli.net/2023/10/07/HBsl9dOT1SEjkcU.png" alt="objects"></p><ol><li>通过 Commit 寻找到 Tree 信息,每个 Commit 都会存储对应的 Tree ID.</li><li>通过 Tree 存储的信息,获取到对应的目录树信息。</li><li>从 Tree 中获得 Blob 的 ID, 通过 Blob ID 获取对应的文件内容。</li></ol><p><img src="https://s2.loli.net/2023/10/09/vHbytoDad3c6S5g.png" alt="trace from commit to tree and blob"><br>最后一个是commit,通过commit中的tree的ID可以查看tree的内容,tree中有blob的ID,可以用来查看源文件的内容。</p><h2 id="1-6-refs"><a href="#1-6-refs" class="headerlink" title="1.6 refs"></a>1.6 refs</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">git chechout -b branchName <span class="hljs-comment"># 创建新分支并自动切换到新分支 branchName 表示分支名</span><br></code></pre></td></tr></table></figure><ul><li>refs 文件存储的內容</li></ul><p>创建<code>myTestBranch</code>分支之后,refs目录下多出了一个文件,且它们的内容都是一样的,即<strong>refs 的内容就是对应的 Commit ID</strong>,因此把 refs 当做指针,指向对应的 Commit 来表示<strong>当前 refs 对应的版本。</strong></p><p><img src="https://s2.loli.net/2023/10/09/TJlCBcdym4wrEqI.png" alt="refs"></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs bash">Ace@MacBook-Air-15 MINGW64 /d/git_study (main)<br>$ <span class="hljs-built_in">cat</span> .git/refs/heads/main<br>087260f549a0bb3c0f78544dd8583f52c7c1988f<br><br>Ace@MacBook-Air-15 MINGW64 /d/git_study (main)<br>$ git checkout -b myTestBranch<br>fatal: a branch named <span class="hljs-string">'myTestBranch'</span> already exists<br><br>Ace@MacBook-Air-15 MINGW64 /d/git_study (main)<br>$ git switch myTestBranch <span class="hljs-comment"># 切换分支</span><br>Switched to branch <span class="hljs-string">'myTestBranch'</span><br><br>Ace@MacBook-Air-15 MINGW64 /d/git_study (myTestBranch)<br>$ <span class="hljs-built_in">cat</span> .git/refs/heads/myTestBranch<br>8b5e69c2b7fe66863d9c3e4bbcbd081218ca9b53<br></code></pre></td></tr></table></figure><p><strong>不同种类的 refs</strong></p><ul><li><p>refs/heads前缀表示的是分支,除此之外还有其他种类的 refs, 比如 refs/tags 前缀表示的是标签。</p></li><li><p>head <code>git checkout -b BranchName # 创建一个新分支,其中 -b 表示切换分支</code>,分支一般用于开发阶段,是可以不断添加 Commit 进行迭代的。</p></li><li><p>tag 标签一般表示的是一个稳定版本,指向的 Commit 一般不会变更,可通过 git tag 命令生成 tag.</p></li></ul><p>创建 tag v0.0.1</p><p><img src="https://s2.loli.net/2023/10/09/YPs4juA9c6iHtaB.png" alt="image.png"></p><h2 id="1-7-追溯历史版本"><a href="#1-7-追溯历史版本" class="headerlink" title="1.7 追溯历史版本"></a>1.7 追溯历史版本</h2><ul><li><p>获取当前版本代码:通过 refs 指向的 Commit 可以获取唯一的代码版本。</p></li><li><p>获取历史版本代码:Commit 里面会存有 <strong>parent commit</strong> 字段,通过 commit 的<strong>串联</strong>获取历史版本代码。</p></li></ul><p>先用<code>git log</code>查看当前版本的 commit ID,然后查看commit,找到 parent 字段:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs bash">Ace@MacBook-Air-15 MINGW64 /d/git_study (myTestBranch)<br>$ git <span class="hljs-built_in">log</span><br>commit 8b5e69c2b7fe66863d9c3e4bbcbd081218ca9b53 (HEAD -> myTestBranch)<br>Date: Wed Aug 30 01:24:41 2023 +0800<br><br> now i updated test.txt<br><br>commit a20a750ede4652ba5979fedd3994f9ddf090a9a7<br>Author: Kjasn < ><br>Date: Wed Aug 30 01:02:39 2023 +0800<br><br> i add a readme<br><br>Ace@MacBook-Air-15 MINGW64 /d/git_study (myTestBranch)<br>$ git cat-file -p 8b5e69c2b7fe66863d9c3e4bbcbd081218ca9b53 <span class="hljs-comment"># 通过commit id 查看</span><br>tree b362f2c28c76ee6619c05216c50497547a1d64ae<br>parent a20a750ede4652ba5979fedd3994f9ddf090a9a7<br>author Kjasn < > 1693329881 +0800<br>committer Kjasn < > 1693332399 +0800<br><br>now i updated test.txt<br></code></pre></td></tr></table></figure><h2 id="1-8-修改历史版本"><a href="#1-8-修改历史版本" class="headerlink" title="1.8 修改历史版本"></a>1.8 修改历史版本</h2><ol><li>git commit –amend<br>通过这个命令可以修改最近的一次 commit 信息,<strong>修改之后 commit id 会变</strong>,tree ID 和 parent 字段不变。</li></ol><p>原来的commit对象仍然存在,但是没有 refs 指针指向它,变成了 <strong>悬空的commit</strong></p><p>演示:</p><p><strong>修改最近一个commit,commit ID 更新了:</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs bash">Ace@MacBook-Air-15 MINGW64 /d/git_study (myTestBranch)<br>$ git commit --amend<br>[myTestBranch 191970a7e6] now i updated test.txt this is another change to test.txt~ <span class="hljs-comment"># 对test.txt 修改后的内容</span><br> Date: Wed Aug 30 01:24:41 2023 +0800<br> 2 files changed, 2 insertions(+)<br> create mode 160000 git_test<br> create mode 100644 test1.txt<br><br>Ace@MacBook-Air-15 MINGW64 /d/git_study (myTestBranch)<br>$ git <span class="hljs-built_in">log</span><br>commit 191970a7e6cf9a463ebc6ca32b522ced441bc082 (HEAD -> myTestBranch)<br>Author: Kjasn < ><br>Date: Wed Aug 30 01:24:41 2023 +0800 <span class="hljs-comment"># 时间仍然是第一次提交的时间,修改后不会更新</span><br><br> now i updated test.txt<br> this is another change to test.txt~<br><br>commit a20a750ede4652ba5979fedd3994f9ddf090a9a7<br>Author: Kjasn < ><br>Date: Wed Aug 30 01:02:39 2023 +0800<br><br> i add a readme<br></code></pre></td></tr></table></figure><p><strong>与修改之前的commit对比,tree和parent没变:</strong></p><p>前:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash">Ace@MacBook-Air-15 MINGW64 /d/git_study (myTestBranch)<br>$ git cat-file -p 087260f549a0bb3c0f78544dd8583f52c7c1988f<br>tree b362f2c28c76ee6619c05216c50497547a1d64ae<br>parent a20a750ede4652ba5979fedd3994f9ddf090a9a7<br>author Kjasn < > 1693329881 +0800<br>committer Kjasn < > 1693329881 +0800<br><br><span class="hljs-keyword">then</span> i commit test.txt<br></code></pre></td></tr></table></figure><p>后:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash">Ace@MacBook-Air-15 MINGW64 /d/git_study (myTestBranch)<br>$ git cat-file -p 191970a7e6cf9a463ebc6ca32b522ced441bc082<br>tree 96153ce3c7dea5dc537babc5c17102565b7066dc<br>parent a20a750ede4652ba5979fedd3994f9ddf090a9a7<br>author Kjasn < > 1693329881 +0800<br>committer Kjasn < > 1696726013 +0800<br><br>now i updated test.txt<br>this is another change to test.txt~<br></code></pre></td></tr></table></figure><ol start="2"><li>git rebase<br> 通过 git rebase -i HEAD-3 可以实现对最近三个 commit 的修改:<ol><li>合并 commit</li><li>修改具体的 commit message</li><li>删除某个 commit</li></ol></li><li>git filter –branch<br>该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作</li></ol><h2 id="1-9-完整的-Git-视图"><a href="#1-9-完整的-Git-视图" class="headerlink" title="1.9 完整的 Git 视图"></a>1.9 完整的 Git 视图</h2><p><img src="https://s2.loli.net/2023/10/08/oMNwrlPuSvCIFn7.png" alt="完整的 Git 视图"></p><h2 id="1-10-Git-Clone-Pull-Fetch"><a href="#1-10-Git-Clone-Pull-Fetch" class="headerlink" title="1.10 Git Clone & Pull & Fetch"></a>1.10 Git Clone & Pull & Fetch</h2><p><a name="anchor1"></a></p><p>Clone<br>拉取完整的仓库到本地目录,可以指定分支,深度。<br>Fetch<br>将远端某些分支最新代码拉取到本地,不会执行 merge 操作,<br>会修改 refs/remote 内的分支信息,如果需要和本地代码合并需要手动操作。<br>Pull<br>拉取远端某分支,并和本地代码进行合并,操作等同于 git fetch + git merge,<br>也可以通过 git pull –rebase 完成 git fetch + git rebase 操作。<br>可能存在冲突,需要解决冲突。</p><h2 id="1-11-Git-Push"><a href="#1-11-Git-Push" class="headerlink" title="1.11 Git Push"></a>1.11 Git Push</h2><p>Push 是将本地代码同步至远端的方式。</p><p>常用命令:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">git push repoName branchName <span class="hljs-comment"># 仓库名 分支名</span><br></code></pre></td></tr></table></figure><p>冲突问题:<br> 1.如果本地的 commit 记录和远端的 commit 历史不一致,则会产生冲突,比如 git commit –amend or git<br> rebase 都有可能导致这个问题。<br> 2. 如果该分支就自己一个人使用,或者团队内确认过可以修改历史则可以通过 <code>git push origin master -f</code> 来完成强制推送,一般不推荐主干分支进行该操作,正常都应该解决冲突后再进行推送。</p><p>推送规则限制:<br>可以通过保护分支,来配置一些保护规则,防止误操作,或者一些不合规的操作出现,导致代码丢失。</p><hr><h2 id="2-1-分支管理工作流"><a href="#2-1-分支管理工作流" class="headerlink" title="2.1 分支管理工作流"></a>2.1 分支管理工作流</h2><p>分支管理工作流有:Git Flow ,Github Flow 和 Gitlab Flow (不过多说明)</p><p>以下以Github 工作流作为演示。</p><hr><ul><li>在GitHub新建一个仓库用于学习测试,然后复制仓库地址(http,ssh)都可以。</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ git <span class="hljs-built_in">clone</span> https://github.com/kjasn/git_test.git <span class="hljs-comment"># 我用的是 http 协议的仓库地址</span><br>Cloning into <span class="hljs-string">'git_test'</span>...<br>warning: You appear to have cloned an empty repository. <span class="hljs-comment"># 因为新建的是一个空仓库,什么也没加</span><br></code></pre></td></tr></table></figure><ul><li>克隆的仓库存放在当前目录下的 git_test 目录下,<strong>切换到仓库目录下</strong>,随便创建一个文件用来演示提交。<br>eg:</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">Ace@MacBook-Air-15 MINGW64 /d/git_study/git_test (<span class="hljs-built_in">test</span>)<br>$ vim readme.md <span class="hljs-comment"># 创建并写入内容</span><br>$ <span class="hljs-built_in">cat</span> readme.md<br>Hello, Kjasn! I am rd.<br></code></pre></td></tr></table></figure><ul><li>add,commit并push</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs bash">Ace@MacBook-Air-15 MINGW64 /d/git_study/git_test (<span class="hljs-built_in">test</span>)<br>$ git add .<br>warning: <span class="hljs-keyword">in</span> the working copy of <span class="hljs-string">'readme.md'</span>, LF will be replaced by CRLF the next time Git touches it<br><br>Ace@MacBook-Air-15 MINGW64 /d/git_study/git_test (<span class="hljs-built_in">test</span>)<br>$ git commit -m <span class="hljs-string">"add readmeme~"</span><br>[<span class="hljs-built_in">test</span> 9471dd3] add readmeme~<br> 2 files changed, 1 insertion(+), 8 deletions(-)<br> delete mode 100644 readme <span class="hljs-comment"># 删除了原先的readme...</span><br> create mode 100644 readme.md<br><br>Ace@MacBook-Air-15 MINGW64 /d/git_study/git_test (<span class="hljs-built_in">test</span>)<br>$ git push origin <span class="hljs-built_in">test</span><br>Enumerating objects: 4, <span class="hljs-keyword">done</span>.<br>Counting objects: 100% (4/4), <span class="hljs-keyword">done</span>.<br>Writing objects: 100% (3/3), 261 bytes | 261.00 KiB/s, <span class="hljs-keyword">done</span>.<br>Total 3 (delta 0), reused 0 (delta 0), pack-reused 0<br>To github.com:kjasn/git_test.git<br> 2adb4c4..9471dd3 <span class="hljs-built_in">test</span> -> <span class="hljs-built_in">test</span><br></code></pre></td></tr></table></figure><p>然后在Github仓库页面<strong>刷新后</strong>可以看到新添加的readme文件。</p><p>新建一个Feature分支:</p><p>push之后,自动创建了一个向main分支合并的pull request</p><p><img src="https://s2.loli.net/2023/10/08/I9Nb8hZ3xuafsjC.png" alt="创建feature分支"></p><p>在Feature分支更新readme文件然后push(图中链接)。访问链接可以查看提交的代码变更,是否与main分支有冲突,解决冲突后可以<strong>选择是否与main分支合并</strong>。</p><p><img src="https://s2.loli.net/2023/10/08/mUkCQusNydtj9IZ.png" alt="选择是否合并"></p><p>设置main分支保护,以防错误的提交代码影响到main分支:</p><p><img src="https://s2.loli.net/2023/10/08/r9vhonu6VkKFQwN.png" alt="设置main分支保护"></p><p>演示更新提交,然后直接push,失败:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ git push origin main<br>Enumerating objects: 5, <span class="hljs-keyword">done</span>.<br>Counting objects: 100% (5/5), <span class="hljs-keyword">done</span>.<br>Delta compression using up to 12 threads<br>Compressing objects: 100% (2/2), <span class="hljs-keyword">done</span>.<br>Writing objects: 100% (3/3), 298 bytes | 298.00 KiB/s, <span class="hljs-keyword">done</span>.<br>Total 3 (delta 1), reused 0 (delta 0), pack-reused 0<br>remote: Resolving deltas: 100% (1/1), completed with 1 <span class="hljs-built_in">local</span> object.<br>remote: error: GH006: Protected branch update failed <span class="hljs-keyword">for</span> refs/heads/main.<br>remote: error: Changes must be made through a pull request.<br>To github.com:kjasn/git_test.git<br> ! [remote rejected] main -> main (protected branch hook declined) <span class="hljs-comment"># 不允许直接push</span><br>error: failed to push some refs to <span class="hljs-string">'github.com:kjasn/git_test.git'</span><br></code></pre></td></tr></table></figure><h2 id="2-2-代码合并"><a href="#2-2-代码合并" class="headerlink" title="2.2 代码合并"></a>2.2 代码合并</h2><ul><li>Fast-Forward</li></ul><p>不会产生一个 merge 节点,合并后保持一个线性历史,如果 target 分支有了更新,则需要通过 rebase 操作更新source branch 后才可以合入。图示:</p><p><img src="https://s2.loli.net/2023/10/08/87F1QaXDlTsHdIp.png" alt="Fast-Forward"></p><ul><li>Three-Way Merge</li></ul><p>三方合并,会产生一个新的 merge 节点。图示:</p><p><img src="https://s2.loli.net/2023/10/08/dNznAlLIO498PJS.png" alt="Three-Way Merge"></p><ul><li>演示:</li></ul><p><strong>Fast-Forward</strong></p><ul><li>不会生成merge结点<br><img src="https://s2.loli.net/2023/12/20/Vnt4rLdHgFaPi2T.png" alt="fast forward merge"></li></ul><p><strong>Three-Way Merge</strong></p><ul><li>生成一个merge结点</li></ul><p><img src="https://s2.loli.net/2023/12/20/9oc43YWRJ2ZkuLK.png" alt="three way merge"></p><h2 id="2-3-选择合适的工作流"><a href="#2-3-选择合适的工作流" class="headerlink" title="2.3 选择合适的工作流"></a>2.3 选择合适的工作流</h2><ul><li>选择原则</li></ul><p>没有最好的,只有最合适的</p><ul><li><strong>针对小型团队合作,推荐使用 Github 工作流即可</strong></li></ul><ol><li><strong>尽量保证少量多次</strong>,最好不要一次性提交上千行代码</li><li>提交 Pull Request 后最少需要保证有 CR 后再合入 </li><li>主干分支尽量保持整洁,使用 fast-forward 合入方式,合入前进行 rebase</li></ol><ul><li>大型团队合作,根据自己的需要指定不同的工作流,不需要局限在某种流程中。</li></ul><h1 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h1><p>参考:<br><a href="https://www.cnblogs.com/snowdreams1006/p/10812861.html">git 入门教程之 git bash 竟然不支持 tree 命令 - 雪之梦技术驿站 - 博客园 (cnblogs.com)</a></p>]]></content>
<tags>
<tag>git</tag>
</tags>
</entry>
<entry>
<title>gin学习记录-中间件和路由</title>
<link href="/2023/08/26/gin%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-%E4%B8%AD%E9%97%B4%E4%BB%B6%E5%92%8C%E8%B7%AF%E7%94%B1/"/>
<url>/2023/08/26/gin%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-%E4%B8%AD%E9%97%B4%E4%BB%B6%E5%92%8C%E8%B7%AF%E7%94%B1/</url>
<content type="html"><![CDATA[<p><img src="https://s2.loli.net/2023/08/26/KnkYaivqlSDmMA8.png" alt="明日香"></p><h1 id="6-gin-中间件和路由"><a href="#6-gin-中间件和路由" class="headerlink" title="6. gin 中间件和路由"></a>6. gin 中间件和路由</h1><p>把请求的处理函数叫做中间件,且形参必须是<code>*gin.Context</code> 一个请求可以有多个中间件<br>通过Use()函数来调用中间件 </p><span id="more"></span><h2 id="6-1-单个路由和中间件"><a href="#6-1-单个路由和中间件" class="headerlink" title="6.1 单个路由和中间件"></a>6.1 单个路由和中间件</h2><ul><li><p>Next() 会将当前中间件前后分离,前面的为请求中间件,后面的为响应中间件<br> 执行完前面遇到Next()就执行下一个中间件,<strong>把响应中间件压入栈中(大概效果是这样)。</strong></p></li><li><p>Abort() 会拦截执行后面的中间件,但当前中间件后面的代码仍会执行完</p></li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> { <br> Name <span class="hljs-type">string</span> <br> Age <span class="hljs-type">int</span> <br>} <br> <br><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">set</span><span class="hljs-params">(c *gin.Context)</span></span> { <br> <span class="hljs-comment">// 设置kv </span><br> c.Set(<span class="hljs-string">"note"</span>, <span class="hljs-string">"这是一条kv设置"</span>) <br><br> <span class="hljs-comment">// 设置结构体数据 </span><br> c.Set(<span class="hljs-string">"user"</span>, User{ <br> Name: <span class="hljs-string">"kjasn"</span>, <br> Age: <span class="hljs-number">11</span>, <br> }) <br>} <br> <br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> { <br> router := gin.Default() <br><br> <span class="hljs-comment">// 使用全局中间件 不需要匹配路径,直接用 </span><br> router.Use(_set) <br><br> router.GET(<span class="hljs-string">"/setVal"</span>, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(c *gin.Context)</span></span> { <br> <span class="hljs-comment">// 用Get()接收 形参是key 返回any类型的val和一个bool值表示是否存在key </span><br> <span class="hljs-comment">// 接收单独设置的kv </span><br> note, ok := c.Get(<span class="hljs-string">"note"</span>) <br> <span class="hljs-keyword">if</span> ok { <br> fmt.Println(note) <br> } <br><br> <span class="hljs-comment">////////////////////////////////////////////////////////////</span><br> <span class="hljs-comment">// 接收结构体 kv </span><br> user, ok := c.Get(<span class="hljs-string">"user"</span>) <br> <span class="hljs-keyword">if</span> ok { <br> <span class="hljs-comment">// 直接打印整个user </span><br> fmt.Println(user) <br> c.JSON(http.StatusOK, gin.H{<span class="hljs-string">"data"</span>: user}) <br><br> <span class="hljs-comment">// 单独打印 需要断言为User类型才能访问User类型的属性 </span><br> fmt.Println(<span class="hljs-string">"断言"</span>) <br> _user, ok := user.(User) <span class="hljs-comment">// 断言成功 _user 接收到user的类型,若失败则为空 </span><br> <span class="hljs-keyword">if</span> ok { <br> fmt.Println(<span class="hljs-string">"姓名:"</span>, _user.Name, <span class="hljs-string">"年龄:"</span>, _user.Age) <br> c.JSON(http.StatusOK, gin.H{<span class="hljs-string">"name"</span>: _user.Name, <span class="hljs-string">"age"</span>: _user.Age}) <br> } <span class="hljs-keyword">else</span> { <br> fmt.Println(<span class="hljs-string">"断言失败,不是User类型"</span>) <br> } <br> } <br> }) <br> <br> err := router.Run(<span class="hljs-string">":80"</span>) <br> <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { <br> <span class="hljs-built_in">panic</span>(err) <br> } <br>} <br></code></pre></td></tr></table></figure><ul><li>通过中间件传递数据并接收 key-value</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> { <br> Name <span class="hljs-type">string</span> <br> Age <span class="hljs-type">int</span> <br>} <br> <br><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">set</span><span class="hljs-params">(c *gin.Context)</span></span> { <br> <span class="hljs-comment">// 设置kv </span><br> c.Set(<span class="hljs-string">"note"</span>, <span class="hljs-string">"这是一条kv设置"</span>) <br><br> <span class="hljs-comment">// 设置结构体数据 </span><br> c.Set(<span class="hljs-string">"user"</span>, User{ <br> Name: <span class="hljs-string">"kjasn"</span>, <br> Age: <span class="hljs-number">11</span>, <br> }) <br>} <br> <br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> { <br> router := gin.Default() <br><br> <span class="hljs-comment">// 使用全局中间件 不需要匹配路径,直接用 </span><br> router.Use(_set) <br><br> router.GET(<span class="hljs-string">"/setVal"</span>, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(c *gin.Context)</span></span> { <br> <span class="hljs-comment">// 用Get()接收 形参是key 返回any类型的val和一个bool值表示是否存在key </span><br> <span class="hljs-comment">// 接收单独设置的kv </span><br> note, ok := c.Get(<span class="hljs-string">"note"</span>) <br> <span class="hljs-keyword">if</span> ok { <br> fmt.Println(note) <br> } <br><br> <span class="hljs-comment">////////////////////////////////////////////////////////////</span><br> <span class="hljs-comment">// 接收结构体 kv </span><br> user, ok := c.Get(<span class="hljs-string">"user"</span>) <br> <span class="hljs-keyword">if</span> ok { <br> <span class="hljs-comment">// 直接打印整个user </span><br> fmt.Println(user) <br> c.JSON(http.StatusOK, gin.H{<span class="hljs-string">"data"</span>: user}) <br><br> <span class="hljs-comment">// 单独打印 需要断言为User类型才能访问User类型的属性 </span><br> fmt.Println(<span class="hljs-string">"断言"</span>) <br> _user, ok := user.(User) <span class="hljs-comment">// 断言成功 _user 接收到user的类型,若失败则为空 </span><br> <span class="hljs-keyword">if</span> ok { <br> fmt.Println(<span class="hljs-string">"姓名:"</span>, _user.Name, <span class="hljs-string">"年龄:"</span>, _user.Age) <br> c.JSON(http.StatusOK, gin.H{<span class="hljs-string">"name"</span>: _user.Name, <span class="hljs-string">"age"</span>: _user.Age}) <br> } <span class="hljs-keyword">else</span> { <br> fmt.Println(<span class="hljs-string">"断言失败,不是User类型"</span>) <br> } <br> } <br> }) <br> <br> err := router.Run(<span class="hljs-string">":80"</span>) <br> <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { <br> <span class="hljs-built_in">panic</span>(err) <br> } <br>} <br></code></pre></td></tr></table></figure><h2 id="6-2-路由分组"><a href="#6-2-路由分组" class="headerlink" title="6.2 路由分组"></a>6.2 路由分组</h2><p>将一系列的路由放到一个组下,统一管理,为分组路由定义全局中间件同单个路由定义全局中间件一样,用Use()函数 </p><ul><li>定义一些需要的结构体</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs go"> <br><span class="hljs-comment">// 封装响应格式 </span><br><span class="hljs-keyword">type</span> Response <span class="hljs-keyword">struct</span> { <br> Code <span class="hljs-type">int</span> <span class="hljs-string">`json:"code"`</span> <br> Date any <span class="hljs-string">`json:"date"`</span> <br> Message <span class="hljs-type">string</span> <span class="hljs-string">`json:"msg"`</span> <br>} <br> <br><span class="hljs-keyword">type</span> UserInfo <span class="hljs-keyword">struct</span> { <br> Name <span class="hljs-type">string</span> <span class="hljs-string">`json:"name"`</span> <br> Age <span class="hljs-type">int</span> <span class="hljs-string">`json:"age"`</span> <br>} <br> <br><span class="hljs-keyword">type</span> ArticleInfo <span class="hljs-keyword">struct</span> { <br> Title <span class="hljs-type">string</span> <span class="hljs-string">`json:"title"`</span> <br> Content <span class="hljs-type">string</span> <span class="hljs-string">`json:"content"`</span> <br>} <br></code></pre></td></tr></table></figure><ul><li>定义中间件</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// 此处直接内定一些简单的数据</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">DisplayUserList</span><span class="hljs-params">(c *gin.Context)</span></span> { <br> list := []UserInfo{ <br> {<span class="hljs-string">"张三"</span>, <span class="hljs-number">23</span>}, <br> {<span class="hljs-string">"李四"</span>, <span class="hljs-number">45</span>}, <br> } <br><br> c.JSON(http.StatusOK, Response{Code: <span class="hljs-number">1</span>, Date: list, Message: <span class="hljs-string">"请求成功"</span>}) <br>} <br> <br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">DisplayArticle</span><span class="hljs-params">(c *gin.Context)</span></span> { <br> list := []ArticleInfo { <br> {<span class="hljs-string">"c语言入门到入土"</span>, <span class="hljs-string">"本书是c语言入门教程,面向入土"</span>}, <br> {<span class="hljs-string">"数据库从删库到跑路"</span>, <span class="hljs-string">"本书教你如何从删库到跑路"</span>}, <br> } <br><br> c.JSON(http.StatusOK, Response{Code: <span class="hljs-number">1</span>, Date: list, Message: <span class="hljs-string">"请求成功"</span>}) <br>} <br> <br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">showTest</span><span class="hljs-params">(c *gin.Context)</span></span> { <br> fmt.Println(<span class="hljs-string">"showTest in "</span>) <br> c.JSON(http.StatusOK, gin.H{<span class="hljs-string">"msg"</span>: <span class="hljs-string">"这是一个用来测试的中间件"</span>}) <br>} <br></code></pre></td></tr></table></figure><ul><li>拆分出来,这样也方便单独成包</li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">UserRouterInit</span><span class="hljs-params">(api *gin.RouterGroup)</span></span> { <br> <span class="hljs-comment">// 用户管理分组 将userManagement作为api下的一个组 同一个组内的请求一般放在一个大括号里 </span><br> <span class="hljs-comment">// 发出请求 http://127.0.0.1/api/user-management/user </span><br> userManagement := api.Group(<span class="hljs-string">"user-management"</span>) { <br> <span class="hljs-comment">// 以下是userManagement分组下的一些请求 </span><br> userManagement.GET(<span class="hljs-string">"/user"</span>, DisplayUserList) <br> <span class="hljs-comment">// ......</span><br> } <br>} <br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">ArticleRouterInit</span><span class="hljs-params">(api *gin.RouterGroup)</span></span> { <br> <span class="hljs-comment">// 文章管理分组 将article-management作为api下的一个组 与userManagement并列 </span><br> <span class="hljs-comment">// 发出请求 http://127.0.0.1/api/article-management/article </span><br> article := api.Group(<span class="hljs-string">"article-management"</span>) {<br> <span class="hljs-comment">// 以下是article-management分组下的一些请求,就像之前写的一样 此处简写 </span><br> article.GET(<span class="hljs-string">"/article"</span>, DisplayArticle) <br> <span class="hljs-comment">// ..........</span><br> } <br>} <br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Test</span><span class="hljs-params">(api *gin.RouterGroup)</span></span> { <br> <span class="hljs-comment">// 为test组注册showTest全局中间件,该组下的子组都会用到这个中间件 </span><br> test := api.Group(<span class="hljs-string">"test"</span>).Use(showTest) { <br> test.GET(<span class="hljs-string">"show1"</span>, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(c *gin.Context)</span></span> { <br> fmt.Println(<span class="hljs-string">"in show1"</span>) <br> }) <br> test.GET(<span class="hljs-string">"show2"</span>, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(c *gin.Context)</span></span> { <br> fmt.Println(<span class="hljs-string">"in show2"</span>) <br> }) <br> } <br>} <br></code></pre></td></tr></table></figure><ul><li>在main()中分组然后直接调用拆分出来的包即可<br>分组之后,请求当前组下的其他分组需要加上父组的路径作为前缀 <figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// 分组 </span><br>api := router.Group(<span class="hljs-string">"api"</span>) <span class="hljs-comment">// 返回一个组 </span><br> <br>UserRouterInit(api) <br>ArticleRouterInit(api) <br>Test(api)<br></code></pre></td></tr></table></figure></li></ul><h2 id="6-3-讲讲gin-Default-和gin-New"><a href="#6-3-讲讲gin-Default-和gin-New" class="headerlink" title="6.3 讲讲gin.Default()和gin.New()"></a>6.3 讲讲gin.Default()和gin.New()</h2><ul><li><p>gin.New() 是创建一个新的<strong>空白引擎</strong>,没有添加任何中间件。而**gin.Default()中调用了gin.New()并添加两个中间件 gin.Logger(), gin.Recovery(),这是二者的主要区别。 **</p></li><li><p>gin.Logger() : 记录请求日志:在每次请求到达服务器时,记录请求的信息,包括请求的方法(GET、POST 等)、请求的路径、请求的 IP 地址等。 </p></li><li><p>gin.Recovery() : 恢复从错误中恢复:在处理请求时,捕获潜在的异常,比如代码出现了意外的错误或崩溃。它会确保应用不会因为异常而完全崩溃,而是尽量将异常信息记录下来,并返回一个友好的错误响应给客户端 。</p></li></ul><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// 以下就等同于用gin.Default() </span><br>router := gin.New() <br>router.Use(gin.Logger(), gin.Recovery()) <br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>go</tag>
<tag>gin</tag>
<tag>学习记录</tag>
</tags>
</entry>
<entry>
<title>折腾日记 - openwrt 安装 docker 插件</title>
<link href="/2023/08/20/%E6%8A%98%E8%85%BE%E6%97%A5%E8%AE%B0-openwrt%E5%AE%89%E8%A3%85docker%E6%8F%92%E4%BB%B6/"/>
<url>/2023/08/20/%E6%8A%98%E8%85%BE%E6%97%A5%E8%AE%B0-openwrt%E5%AE%89%E8%A3%85docker%E6%8F%92%E4%BB%B6/</url>
<content type="html"><![CDATA[<h2 id="写在开头"><a href="#写在开头" class="headerlink" title="写在开头"></a>写在开头</h2><blockquote><p>搞了个 <code>openWrt</code> 虚拟机,想在里面跑些东西,已经安装了 <code>Docker</code>,但没有图形化界面,不方便用,所以就开始折腾了…</p></blockquote><span id="more"></span><h2 id="经历"><a href="#经历" class="headerlink" title="经历"></a>经历</h2><p>我跟着<a href="https://www.bilibili.com/video/BV1xm4y1a7ke">B站视频</a>安装了 <code>openWrt</code>,然后安装 <code>Docker</code>图形界面插件,网上各种搜教程,看得头都晕了(我实在不会安装开发软件和配环境这一类的东西),我都全程问chatGPT,还是各种报错,进行不下去。前天晚上洗完澡,刚12点,感觉还挺早,我一想,在找找教程看怎么搞,然后等我注意到的时候就到了两点,最重要的是安装依赖还是报错😭。</p><h2 id="遇到的问题及解决方法"><a href="#遇到的问题及解决方法" class="headerlink" title="遇到的问题及解决方法"></a>遇到的问题及解决方法</h2><ul><li>问题</li></ul><ol><li><code>opkg update</code>报错</li><li>安装<code>Docker</code>插件失败</li><li>还有一些小问题,比如文件传输,<code>winSCP</code>无法连接到虚拟机…</li></ol><ul><li><p>解决<br> 先说说这些小问题吧。其实这些小问题是一个接着一个的,比如我不知道怎么把下好的安装包放到<code>openWrt</code>虚拟机中去,然后我就去找解决方法,用支持 <code>sftp</code> 协议的软件传,我下了<code>winSCP</code>,结果死活连不上<code>openWrt</code>,但能连上<code>ubuntu</code>,把报错内容告诉chatGPT,也没得到什么可行的方法。好多次都是遇到这样的小问题,而且一个接着一个。后来我发现,在图形界面中的系统菜单下有个上传文件的功能,太蠢了……<br> 然后,第一个问题,这个问题不解决,后面一直进行不下去,我也是一直卡在这里,然后我看到说是镜像源的问题,那些源仓库的链接复制到浏览器已经打不开了,所以得换源。然后又在B站找到个<a href="https://www.bilibili.com/video/av970595502">视频</a>,我为什么没有早一点发现啊😭,这个手把手教会了我换源,下载<code>Docker</code>插件,安装插件,最后就解决了所有问题。</p></li><li><p>以下是这些依赖和插件,打包放在这里了:<br><a href="https://wwnf.lanzouw.com/b03epekzc">https://wwnf.lanzouw.com/b03epekzc</a><br>密码:9xv7</p></li></ul><p>大概就这些了,也没别的,吐槽一下自己有多蠢就是了。</p><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><blockquote><p>唉,我只是为了薅微软羊毛所以用 <code>openWrt</code>来刷东西,折腾了这么久,真不容易😵</p></blockquote>]]></content>
<tags>
<tag>折腾</tag>
<tag>openWrt</tag>
<tag>docker</tag>
</tags>
</entry>
<entry>
<title>gin学习记录-bind参数绑定</title>
<link href="/2023/08/16/gin%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-bind%E5%8F%82%E6%95%B0%E7%BB%91%E5%AE%9A/"/>
<url>/2023/08/16/gin%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-bind%E5%8F%82%E6%95%B0%E7%BB%91%E5%AE%9A/</url>
<content type="html"><![CDATA[<h1 id="4-bind-绑定参数"><a href="#4-bind-绑定参数" class="headerlink" title="4. bind 绑定参数"></a>4. bind 绑定参数</h1><p>gin 中的 bind 可以很方便的将前端传递来的数据与结构体进行参数绑定,以及参数校验 。</p><span id="more"></span><h2 id="4-1-参数绑定"><a href="#4-1-参数绑定" class="headerlink" title="4.1 参数绑定"></a>4.1 参数绑定</h2><p>在使用这个功能的时候,需要给结构体加上<code>Tag :json,form,url </code></p><p>两种绑定方式: </p><ul><li>MustBind 实际开发不用,校验失败会改状态码 </li><li>ShouldBind 可以绑定<code>json, query, param, yaml, xml</code>,如果校验不通过会返回错误</li></ul><h3 id="绑定post参数-ShouldBindJSON"><a href="#绑定post参数-ShouldBindJSON" class="headerlink" title="绑定post参数 ShouldBindJSON"></a>绑定post参数 ShouldBindJSON</h3><p>tag 为 : <code>json </code></p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> UserInfo <span class="hljs-keyword">struct</span> { <br> Name <span class="hljs-type">string</span> <span class="hljs-string">`json:"name"`</span> <br> Age <span class="hljs-type">int</span> <span class="hljs-string">`json:"age"`</span> <br> Gender <span class="hljs-type">string</span> <span class="hljs-string">`json:"gender"`</span> <br>} <br> <br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> { <br> router := gin.Default() <br><br> <span class="hljs-comment">// 绑定post参数 </span><br> <span class="hljs-comment">/* 发送到数据: </span><br><span class="hljs-comment"> { </span><br><span class="hljs-comment"> "name": "aaa", </span><br><span class="hljs-comment"> "age": 33, </span><br><span class="hljs-comment"> "gender": "male" </span><br><span class="hljs-comment"> } </span><br><span class="hljs-comment"> */</span> <br> router.POST(<span class="hljs-string">"/bind-post"</span>, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(arg *gin.Context)</span></span> { <br> <span class="hljs-keyword">var</span> userInfo UserInfo <br><br> <span class="hljs-comment">// 将请求中体json数据绑定到userInfo 上 </span><br> err := arg.ShouldBindJSON(&userInfo) <br><br> <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { <br> arg.JSON(<span class="hljs-number">400</span>, gin.H{<span class="hljs-string">"error"</span>: err, <span class="hljs-string">"msg"</span>: <span class="hljs-string">"绑定失败"</span>}) <br> fmt.Println(err) <br> <span class="hljs-keyword">return</span> <br> } <br> arg.JSON(<span class="hljs-number">200</span>, gin.H{<span class="hljs-string">"data"</span>: userInfo, <span class="hljs-string">"msg"</span>: <span class="hljs-string">"绑定成功"</span>}) <br> }) <br> <span class="hljs-comment">/* 返回结果: </span><br><span class="hljs-comment"> { </span><br><span class="hljs-comment"> "data": { </span><br><span class="hljs-comment"> "name": "aaa", </span><br><span class="hljs-comment"> "age": 33, </span><br><span class="hljs-comment"> "gender": "male" </span><br><span class="hljs-comment"> }, </span><br><span class="hljs-comment"> "msg": "绑定成功" </span><br><span class="hljs-comment"> } </span><br><span class="hljs-comment"> */</span> <br><br> err := router.Run(<span class="hljs-string">":80"</span>) <br> <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { <br> <span class="hljs-keyword">return</span> <br> } <br>} <br></code></pre></td></tr></table></figure><h2 id="4-2-绑定query参数-ShouldBindQuery"><a href="#4-2-绑定query参数-ShouldBindQuery" class="headerlink" title="4.2 绑定query参数 ShouldBindQuery"></a>4.2 绑定query参数 ShouldBindQuery</h2><p>tag 为 : <code>form </code></p><p>form是用来绑定 POST 请求体中的查询参数,这里不能用query,query是用来绑定 GET 请求中的查询参数 </p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> UserInfo <span class="hljs-keyword">struct</span> { <br> Name <span class="hljs-type">string</span> <span class="hljs-string">`json:"name" form:"name"`</span> <br> Age <span class="hljs-type">int</span> <span class="hljs-string">`json:"age" form:"age"`</span> <br> Gender <span class="hljs-type">string</span> <span class="hljs-string">`json:"gender" form:"gender"`</span> <br>} <br> <br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> { <br> router := gin.Default() <br><br> <span class="hljs-comment">// 绑定query参数 </span><br> <span class="hljs-comment">// 输入的请求为: http://127.0.0.1/bind-query?name=kjasn&age=54&gender=male </span><br> router.POST(<span class="hljs-string">"/bind-query"</span>, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(arg *gin.Context)</span></span> { <br> <span class="hljs-keyword">var</span> userInfo UserInfo <br><br> <span class="hljs-comment">// 将请求中的json数据绑定到userInfo 上 </span><br> err := arg.ShouldBindQuery(&userInfo) <br><br> <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { <br> arg.JSON(<span class="hljs-number">400</span>, gin.H{<span class="hljs-string">"error"</span>: err, <span class="hljs-string">"msg"</span>: <span class="hljs-string">"绑定失败"</span>}) <br> fmt.Println(err) <br> <span class="hljs-keyword">return</span> <br> } <br> arg.JSON(<span class="hljs-number">200</span>, gin.H{<span class="hljs-string">"type"</span>: <span class="hljs-string">"bind-query"</span>, <span class="hljs-string">"data"</span>: userInfo, <span class="hljs-string">"msg"</span>: <span class="hljs-string">"绑定成功"</span>}) <br> }) <br> <span class="hljs-comment">/* 结果如下: </span><br><span class="hljs-comment"> { </span><br><span class="hljs-comment"> "data": { </span><br><span class="hljs-comment"> "name": "kjasn", </span><br><span class="hljs-comment"> "age": 54, </span><br><span class="hljs-comment"> "gender": "male" </span><br><span class="hljs-comment"> }, </span><br><span class="hljs-comment"> "msg": "绑定成功", </span><br><span class="hljs-comment"> "type": "bind-query" </span><br><span class="hljs-comment"> } */</span><br><br> err := router.Run(<span class="hljs-string">":80"</span>) <br> <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { <br> <span class="hljs-keyword">return</span> <br> } <br>} <br> <br></code></pre></td></tr></table></figure><h2 id="4-3-绑定动态参数-ShouldBindUri"><a href="#4-3-绑定动态参数-ShouldBindUri" class="headerlink" title="4.3 绑定动态参数 ShouldBindUri"></a>4.3 绑定动态参数 ShouldBindUri</h2><p>tag 为 : <code>uri </code></p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> UserInfo <span class="hljs-keyword">struct</span> { <br> <span class="hljs-comment">// 后面加的是tag uri是用来绑定POST 请求中的url的参数 </span><br> Name <span class="hljs-type">string</span> <span class="hljs-string">`json:"name" form:"name" uri:"name" `</span> <br> Age <span class="hljs-type">int</span> <span class="hljs-string">`json:"age" form:"age" uri:"age"`</span> <br> Gender <span class="hljs-type">string</span> <span class="hljs-string">`json:"gender" form:"gender" uri:"gender"`</span> <br>} <br> <br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> { <br>router := gin.Default() <br> <br><span class="hljs-comment">// 绑定动态参数 从url中获取参数 </span><br><span class="hljs-comment">// 输入的请求为:http://127.0.0.1/bind-uri/qqq/12/female </span><br>router.POST(<span class="hljs-string">"/bind-uri/:name/:age/:gender"</span>, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(arg *gin.Context)</span></span> { <br> <span class="hljs-keyword">var</span> userInfo UserInfo <br><br> <span class="hljs-comment">// 将请求中的url的数据绑定到userInfo 上 </span><br> err := arg.ShouldBindUri(&userInfo) <br><br> <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { <br> arg.JSON(<span class="hljs-number">400</span>, gin.H{<span class="hljs-string">"error"</span>: err, <span class="hljs-string">"msg"</span>: <span class="hljs-string">"绑定失败"</span>}) <br> fmt.Println(err) <br> <span class="hljs-keyword">return</span> <br> } <br> arg.JSON(<span class="hljs-number">200</span>, gin.H{<span class="hljs-string">"data"</span>: userInfo, <span class="hljs-string">"msg"</span>: <span class="hljs-string">"绑定成功"</span>}) <br> }) <br> <span class="hljs-comment">/* </span><br><span class="hljs-comment"> { </span><br><span class="hljs-comment"> "data": { </span><br><span class="hljs-comment"> "name": "qqq", </span><br><span class="hljs-comment"> "age": 12, </span><br><span class="hljs-comment"> "gender": "female" </span><br><span class="hljs-comment"> }, </span><br><span class="hljs-comment"> "msg": "绑定成功" </span><br><span class="hljs-comment"> } </span><br><span class="hljs-comment"> */</span> <br><br> err := router.Run(<span class="hljs-string">":80"</span>) <br> <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { <br> <span class="hljs-keyword">return</span> <br> } <br>} <br> <br></code></pre></td></tr></table></figure><h2 id="4-4-ShouldBind"><a href="#4-4-ShouldBind" class="headerlink" title="4.4 ShouldBind"></a>4.4 ShouldBind</h2><p><strong>会根据请求头中的 content-type 去自动绑定</strong><br>默认tag 为 <code>form </code></p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><code class="hljs go">router.POST(<span class="hljs-string">"/bind-form"</span>, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(arg *gin.Context)</span></span> { <br> <span class="hljs-keyword">var</span> userInfo UserInfo <br><br> <span class="hljs-comment">// 请求1: http://127.0.0.1/bind-form?name=lkh&age=77&gender=secret (虽然是post,但也能绑定get请求) </span><br> <span class="hljs-comment">/* 请求2: (json格式) 也可以请求form-data等类型 </span><br><span class="hljs-comment"> { </span><br><span class="hljs-comment"> "name": "aaa", </span><br><span class="hljs-comment"> "age": 33, </span><br><span class="hljs-comment"> "gender": "男" </span><br><span class="hljs-comment"> } </span><br><span class="hljs-comment"> */</span> <br><br> err := arg.ShouldBind(&userInfo) <br><br> <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { <br> arg.JSON(<span class="hljs-number">400</span>, gin.H{<span class="hljs-string">"error"</span>: err, <span class="hljs-string">"msg"</span>: <span class="hljs-string">"绑定失败"</span>}) <br> fmt.Println(err) <br> <span class="hljs-keyword">return</span> <br> } <br> arg.JSON(<span class="hljs-number">200</span>, gin.H{<span class="hljs-string">"data"</span>: userInfo, <span class="hljs-string">"msg"</span>: <span class="hljs-string">"绑定成功"</span>}) <br> <span class="hljs-comment">/* </span><br><span class="hljs-comment"> // 请求1的结果 </span><br><span class="hljs-comment"> { </span><br><span class="hljs-comment"> "data": { </span><br><span class="hljs-comment"> "name": "lkh", </span><br><span class="hljs-comment"> "age": 77, </span><br><span class="hljs-comment"> "gender": "secret" </span><br><span class="hljs-comment"> }, </span><br><span class="hljs-comment"> "msg": "绑定成功", </span><br><span class="hljs-comment"> "type": "" // get请求没有的请求体 Content-Type字段 </span><br><span class="hljs-comment"> } </span><br><span class="hljs-comment"></span><br><span class="hljs-comment"> // 请求2的结果 </span><br><span class="hljs-comment"> { </span><br><span class="hljs-comment"> "data": { </span><br><span class="hljs-comment"> "name": "aaa", </span><br><span class="hljs-comment"> "age": 33, </span><br><span class="hljs-comment"> "gender": "男" </span><br><span class="hljs-comment"> }, </span><br><span class="hljs-comment"> "msg": "绑定成功", </span><br><span class="hljs-comment"> "type": "application/json" // 类型 </span><br><span class="hljs-comment"> } </span><br><span class="hljs-comment"> */</span> <br>}) <br> <br></code></pre></td></tr></table></figure><h2 id="4-5-bind-绑定器"><a href="#4-5-bind-绑定器" class="headerlink" title="4.5 bind 绑定器"></a>4.5 bind 绑定器</h2><p>需要使用参数验证功能,需要加 binding tag </p><h3 id="常用验证器"><a href="#常用验证器" class="headerlink" title="常用验证器"></a>常用验证器</h3><p>验证器和值之间不能有空格!!!,同一个字段多个验证规则用’,’隔开<br><code>eg: binding:"min = 5" // error!!! </code> </p><ul><li><p>不能为空,并且不能没有这个字段<br>required: 必填字段,如: <code>binding:"required"</code> </p></li><li><p>针对字符串的长度<br>min 最小长度,如:<code>binding:"min=5"</code><br>max 最大长度,如:<code>binding:"max=10"</code><br>len 长度,如:<code>binding:"len=6"</code> </p></li><li><p>针对数字的大小<br>eq 等于,如:<code>binding:"eq=3"</code><br>ne 不等于,如:<code>binding:"ne=12"</code><br>gt 大于,如: <code>binding:"gt=10"</code><br>gte 大于等于,如:<code> binding:"gte=10"</code><br>lt 小于,如:<code>binding:"lt=10"</code><br>lte 小于等于,如:<code>binding:"lte=10"</code><br>eqfield 等于其他字段的值,如:<code>binding:"eqfield=ConfirmPassword"</code><br>nefield 不等于其他字段的值<br>忽略字段,如:<code>binding:"-"</code></p></li></ul><h3 id="gin-内置验证器"><a href="#gin-内置验证器" class="headerlink" title="gin 内置验证器"></a>gin 内置验证器</h3><h4 id="枚举验证器-oneof"><a href="#枚举验证器-oneof" class="headerlink" title="枚举验证器 oneof"></a>枚举验证器 oneof</h4><p>要求当前字段的值必须是 oneof 中的一个,oneof的值用空格隔开,常用与性别检验 </p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// 以下是结构体中的一个字段 </span><br>Gender <span class="hljs-type">string</span> <span class="hljs-string">`json:"gender" binding:"oneof=男 女"`</span> <span class="hljs-comment">// 性别 </span><br></code></pre></td></tr></table></figure><h4 id="字符串相关"><a href="#字符串相关" class="headerlink" title="字符串相关"></a>字符串相关</h4><p>contains=arg 包含arg的字符<br>excludes=arg 不包含arg<br>startswith=arg 以arg开头<br>endswith=arg 以arg结尾<br>dive 用来对数组或切片中的每个元素进行单独的验证 </p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// name字段 </span><br>Name <span class="hljs-type">string</span> <span class="hljs-string">`json:"name" binding:"required,endswith=f"`</span> <span class="hljs-comment">// 用户名 </span><br> <br><span class="hljs-comment">// 1. 验证切片中的元素不能为空: </span><br>Data []<span class="hljs-type">string</span> <span class="hljs-string">`binding:"dive,required"`</span> <br> <br><span class="hljs-comment">// 2. 验证切片中的元素的长度不能超过10: </span><br>Data []<span class="hljs-type">string</span> <span class="hljs-string">`binding:"dive,max=10"`</span> <br> <br><span class="hljs-comment">// 3. 验证切片中的元素必须为数字: </span><br>Data []<span class="hljs-type">string</span> <span class="hljs-string">`binding:"dive,number"`</span> <br></code></pre></td></tr></table></figure><h3 id="自定义验证器"><a href="#自定义验证器" class="headerlink" title="自定义验证器"></a>自定义验证器</h3><p>内置的验证器往往不够用,需要自定义验证器,如下自定义一个校验姓名是否重复的验证器 </p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">package</span> main <br> <br><span class="hljs-keyword">import</span> ( <br> <span class="hljs-string">"fmt"</span> <br> <span class="hljs-string">"github.com/gin-gonic/gin"</span> <br> <span class="hljs-string">"github.com/gin-gonic/gin/binding"</span> <br> <span class="hljs-string">"github.com/go-playground/validator/v10"</span> <br> <span class="hljs-string">"net/http"</span> <br> <span class="hljs-string">"reflect"</span> <br>) <br> <br><span class="hljs-keyword">type</span> SignUserInfo <span class="hljs-keyword">struct</span> { <br> <span class="hljs-comment">// 添加验证器 常用的 此处 uniqueName是一个自定义的验证器 </span><br> Name <span class="hljs-type">string</span> <span class="hljs-string">`json:"name" binding:"required,uniqueName" msg:"昵称不能为空也不能重复"`</span> <span class="hljs-comment">// 用户名 </span><br> Age <span class="hljs-type">int</span> <span class="hljs-string">`json:"age" binding:"lt=100,gt=0" msg:"年龄不符合要求"`</span> <span class="hljs-comment">// 年龄 </span><br>} <br> <br><span class="hljs-comment">// 简单写,直接用一个字符串数组 实际开发需要存储用户信息的数据库然后到数据库中查找昵称是否重复 </span><br><span class="hljs-keyword">var</span> nameList = []<span class="hljs-type">string</span>{<span class="hljs-string">"张三"</span>, <span class="hljs-string">"李四"</span>, <span class="hljs-string">"王五"</span>} <br> <br><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">GetValidMsg</span><span class="hljs-params">(err <span class="hljs-type">error</span>, user SignUserInfo)</span></span> <span class="hljs-type">string</span> { <br> <span class="hljs-comment">// 将err接口断言为具体类型 </span><br> <span class="hljs-keyword">if</span> errs, ok := err.(validator.ValidationErrors); ok { <br> getObj := reflect.TypeOf(&user) <br> fmt.Println(<span class="hljs-string">"类型为:"</span>, getObj) <br><br> <span class="hljs-comment">// 断言成功 </span><br> <span class="hljs-keyword">for</span> _, e := <span class="hljs-keyword">range</span> errs { <span class="hljs-comment">// 遍历每一个错误信息 报错信息可能有多个 </span><br> <span class="hljs-comment">// 根据报错字段名,获取结构体的具体字段 </span><br> <span class="hljs-keyword">if</span> f, exits := getObj.Elem().FieldByName(e.Field()); exits { <br> msg := f.Tag.Get(<span class="hljs-string">"msg"</span>) <br> fmt.Println(msg) <br> <span class="hljs-keyword">return</span> msg <br> } <br> } <br> } <br> <span class="hljs-keyword">return</span> <span class="hljs-string">""</span> <span class="hljs-comment">// 没有检查到验证器错误则返回空 </span><br>} <br> <br><span class="hljs-comment">// 函数原型为 func(fl FieldLevel) bool </span><br><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">nameCheck</span><span class="hljs-params">(fl validator.FieldLevel)</span></span> <span class="hljs-type">bool</span> { <br> <span class="hljs-comment">// 遍历用户信息列表 实际应到数据库中查询,这里只是简单模拟 </span><br> <span class="hljs-keyword">for</span> _, nameStr := <span class="hljs-keyword">range</span> nameList { <br> <span class="hljs-comment">// 断言 </span><br> name := fl.Field().Interface().(<span class="hljs-type">string</span>) <br><br> <span class="hljs-keyword">if</span> nameStr == name { <br> <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span> <br> } <br> } <br> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span> <br>} <br> <br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> { <br> router := gin.Default() <br><br> <span class="hljs-keyword">if</span> v, ok := binding.Validator.Engine().(*validator.Validate); ok { <br> <span class="hljs-comment">// 注册uniqueName验证器,其自定义验证功能通过_nameCheck函数来实现 </span><br> err := v.RegisterValidation(<span class="hljs-string">"uniqueName"</span>, _nameCheck) <br> <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { <br> <span class="hljs-keyword">return</span> <br> } <br> } <br> <br> router.POST(<span class="hljs-string">"/custom-check"</span>, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(c *gin.Context)</span></span> { <br> fmt.Println(<span class="hljs-string">"访问..."</span>) <br> <span class="hljs-keyword">var</span> user SignUserInfo <br> err := c.ShouldBindJSON(&user) <span class="hljs-comment">// 返回error信息,不报错则返回空 </span><br> <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { <br> customErr := _GetValidMsg(err, user) <br> c.JSON(http.StatusBadRequest, gin.H{<span class="hljs-string">"msg"</span>: customErr}) <br> <span class="hljs-keyword">return</span> <br> } <br><br> c.JSON(http.StatusOK, gin.H{<span class="hljs-string">"data"</span>: user}) <br> }) <br><br> err := router.Run(<span class="hljs-string">":80"</span>) <br> <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> { <br> <span class="hljs-keyword">return</span> <br> } <br>} <br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>gin</tag>
<tag>学习记录</tag>
</tags>
</entry>
<entry>
<title>cpp-re</title>
<link href="/2023/08/07/cpp-re/"/>
<url>/2023/08/07/cpp-re/</url>
<content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="抱歉, 这个密码看着不太对, 请再试试." data-whm="抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容."> <script id="hbeData" type="hbeData" data-hmacdigest="2f96fb5b2b0127d8a24ff43e26e105aadc9b2eaa22649ff81669abded96b263c">3d0f19459c77e7adc1de9f2499cd45e5ff681bb8549318365763578dacb2a01aaaa320619c65aabc64fc7e796540efcc0166099b7b9dd5866e2eca1ea60d2444b6c6daa987e3d2a66ffb4625935044c2cffa4e761fb9cf455f283e8364c4a0a3e4e7579f9e5d18d64c72a9e0d09d51f99561b5e24df667c68c87784844e62126ad4a3d58813a90b8be1ea347ece607e378a2331178645b35dd513a57ec3b33ab7b03502ff73cc46d9c49f756a9d2057219ffcc7ad6d396a5c9f99c556b6214538ea54bf5481d22ab9aca7b8656cb2c295eaa4b25227f487ba476049868e35e6b1cf5277781fb9b451142a59f69587a3836510d4d23c1f3c7f1650832fd516cb985982cfa5566622a111cc2fc0cc2abb5c182f54bfb90dac97f2cf09251544a487d8ef8e30ee572f655bec16170deaaa92d77a02cf250868b444265b28e3cd6cea0781a4991518a3f9c6b5d9594ccfb0f72b4afa54c920671bdcf8bf8c97a374b56a8f8217d1f9e4dac74fb3310900311b315968e3eeb81deb54c1a4df78ddc42ca7785d78ee92aaaf211b1ea18ab48156465bb822aedbc025cc6cd60e092427fc1b106a6cc00c84abcd4e10b3609212c25e1ea1da43666f6e9ec04572377277aca0d27adaf8dc7b56ce601af577f1f348e5a1f044a33fff14fe4d47ab3ea560a15bdfdf5d3696db3f6ab36170cc10fead6c4035135d4e1675fe89368d68034b322c7a4ba5ea49a2a78c8c588c10efd33b21fe29a0e6a91d031fe6119fea6d0a6f5f763f2b2e9eb6d9e444c51092386d1714bedd30ded99a11716f5229d705baab4610f82393f9783fb626fb4c03c4662cafc2be91ea353c3db954d9784d7255a89078812a9991b1ad1ae460bed9d347e930655c96193d43cceb0e583c669934b06fcf6a5d898d9f051ed541055030879539c47657af1508d285f6ebdfd13af4ea22c331d13c8aecd9f102f3b87344984df2a2587e563dd90d8e31e977f4126889314696f13566f9dd56eafc9605da6573c52818d855ec494e92d35a97e94ea7f0d8afa464d642de25142ad58c2e3017f11aebae7911d00be0202d00650be5f220876f87a7f3a856f7673273810c74b35ff1188d499faac278be3cd103a4cf6af936dc0afac36c11d485bf6dcadb4df0041c9d935efa183abcab327938311595a248c9ee690a27d940895ff24c304171941c7d0fb51a5e3fc3cdd9b2f1b75e3111ea80557cb248e04d2f8190ab23cc398412a8b06d71d66f9fb882540a19fb59c6932bf3fc4e67974272ff7167edbe538cacf9826f21212688886308928211de1cda41e417a46e209f5fadfdafb459caff1cd41b9741075f717f8a870eb9eb4240eace1e67d8a4f72eb36f9aa4ee74e769cf194c7908d9918f0dde5b39653d2488a01dd5c3bd5678df01f3ca07f57d90be7db90fc591e5eec5e939a34b8cb755a68d0b1395bc9c3f5084c7e33ad5ff6d24fc52275c45230fe13a87d9db60c001d39e6db8ac5eb46d1fcc6ef9686613d2d407b0cb0cacc36ed66030fc58216abcb8c6c522b826f52569e340baaa84e269d0a9321fb051107f9d12ff478ca77b823c3f3ab7b64e43eb7aa468b0be2da020dcf388af732e2a4505a0db793a61a05d4c3df37e7d437bbca82402314ea1021f43d07799bbec359f8bae36d9508e933915905f198ded2a9a69c7af5f3d73cc7e3bc329cc400353ed44921f2a2f262239b6e540b0a80dcbae116556dd1e6b2f0b856abe34303f58aaf90f34376e61a82e6959fa92f6c5a97d86eea2f8d0327694ef76e7165737b5ae050332d14fc068d037d9fa48841ab26e9ce6753a034cfcb02d01d9567d0f5ffde13ec855bc1de61a600304bfe65f4b225e3541b3d6801dd889104bdee13635589715a3119609131279660866b2fdb9c7ab319de64f36384ecbb6f00cca3269f9cade4ae08e441572c2f0f86fc9afac44150951964a360e150c025e3c8b63ec76f51de4b470abddab3cd8c3481e7fcec519c72cc3656f05943a3c92d6525a31483b2eeb80720df48c6b23477e705ce646f8e0a31d9a37bcf966142dc9403b14e2736e335b1d966a117c1f643bc206fa820c91b6f4d203d3e65d88cc6b8ab11eddd9261d1b2b68e6d8e8e490e228387a42a8ae4890b3cfb4b12c7d6e2f0539e7436ef81664cfcceb05ddef97e9d4959c798b75d79c9eac2dcf7b205afa1be748f920e6f9e36ba70fd6602c3f8833015c1c6ad270675e3b6cf7617ee13c4bf078d6dfd75b282c1bf37efbba98ff78b0e78222cfcfa00336916c0ced92382331f54b02523322474d68b60355cb6daf3539419eeb93fad2abc9f94a961c0b78f719b8c7f6d423ec8915dafe938d76acbe8b1a7bc6afa8d19ba1392d38257658883f9ea64aa92f3caf8e52101bd2b6ec5735def5271466c002cc00d9ca311e93c1f7bde61d034ece62fc777929e4f134c789e5a36ea48111150eb4568d41f4674292bcdfd59914b937d44c51787e3e3272691a8e1c843d1c5b7f6269c725377b51b4b45ee793db69814b947fdc4ae73c5b303d175f72afde800f4851da24cf5533c37b17c9f129f10085d60a30f47d78f0266d745dcf5ec339d267e6c84aa3a9e81af27ff562c09d01cbc32ad64cb3600372effefc011706a3732226f346f173087ec9bfa931d15e0c9f1ce76230ebf3348280e61359a4914a652aacd6b7ff9bb6a0871365791fd83f99bacb6b07058ce1d55321eae124cc649e7d0d5e62d4d14fa804350a04b015b89379daf64a1c8b232ff5f2c2000c51e93ad3fe1ea4af61971e055d1d3916d24864c308853d4e9bfc4e157cba7010a1b9e5b1edf85821232418ca59a1b32be5795a860235cf0bbabf40d1e50a0d86c09cdd9bc07688515b2342a14bf298be650372899f38f0f5f3a9624b4ac0bcf435b288babdf86c16d4ffc4871877c3d127f21dd38dd7d7d26f2d964f6731935e6b2b2a11ac54bb1ec063a2d38109b6618c8553430c61db103811b67a2ba7bbf65a41de6322b3be56ad71ef411da99709e4e59369d00dfc56ae8eacb0c50601a6503afd3c7854af2744a15be1bee6cae4c9003f0064fe72936ac646a0f8cc31ca5c2095940ff67a95dbf622744f8071e59d1f838697595f8f465b19de0be2bd60819d4f1e3f02ef8ece39be136c7635b07694532b7eb563e4a167da388811323a0b796f32a394c94171c2eea582a14239c30199c95fa7b1f9d01d514c5b53777099f5bb34298e388d145eb1433a75060548477538405bc45b071c7d71baf792955df46c92b7f3929bb74b0ef64859683add043e40d6396cf110a363f19f400aad49ac8694034e8be90d829c8f528c4ab89e8ca13838b1db9a606901b3b1968e0ea917cccd3c4b652eb7318062283624c9c4db946df8ce9d94a984571f469f6b48d035531baf85ed1d54c0cd01c4d93cd782967f7121be34ecc05b30b6bedd7a5adc5b29c288298c2e92c330ad284e189e3a0bb41762d0a60945b43697142084daf4ca7f51cf9378dc09c6f6bcd776028058a6a522851904a15a1b5029f0023724ac4a74d32aa27c22391b802ca5c7e15749ffb1aa0f268ec9787d0f231f9ac5220377672ec1947b6d7d7f44f40e49686b454373742d9a6ebac5494493c44107308b2e2ef1455e47fb0235e12127b8a71f149ba518ddbc4ef34d02e140011983b97c4aa4ba85a42ff486499e897e8f12635dcf62f1cfb40c7445b0aeb528949e83efaf37c75105625a767a8935e8552bc693f475747798c9c81a65cb4e69ec98d00605d74b004d55b6835330f586ab3f0697a371bf5338961fc0e21e7d310fffe7e54cf3773ce9c2a31bdf65a9186ad18da78b0537131a73baea928a0e519307d31b21ec7970e733b73d9e62dd9eaa939bab6761176cda5ad91b40d365c3d8af84aec9df85827e71aa8deea60a72c6c9a58ecfef36e46f2bf8d4fd433e3397688167c40e62dcbc82baacf7d925823f1c7a234f0de8d607e5255b771213ac352c826b59e411651281cdd00fc00ef928a4662038b92172b56142b35012257df25929220d3015182dd04310fb30b496aff15a2385b9e44f8ec557b93beb7e402893bddc2285854a9c9f8c00220d12a2f2d0a94e02ebe43871d5d8ebee0da9a2f85215591f67859e1e9906e05ef1fc87f0388b6837b3f7cd26e4090717e54295d9767878e770250da917da9c891856deafd6d49453909f7c6729cdb9ce581abc8acea68aa960266ab5b3fa19c86abd31a63cd47502feae9ac602c0c23a7f5b9de28e8023e5702fafce489a18426b9935f1d31786aae0b81cff166a8b76b929b3f9a4e3fda546851535d7f930240abc45a3a88551732399a5bf38dc6839b46b4bff2d3b6d97ec3163e941be75ea04f6d5793b947dbf0393cb03368909f3f4779f9d439d4bf945d0cacd9663e01a2eb2e01e65c8bad896fa463dfcef56a96a87dd6565f5649352f62dbf23bcf13fbeeca6d667d8e1ae1c6171282308c44f6c57abb0de72ee4d5c7b7f745292c879fc9224eb5b17eeceec36e41ac867115f6234930a44f5f54e677080e2ee040732a6844a2743c63d8185f2e3ffa4427aa3990c1249d63480a8e20b486d3ff3159df1b4cc3b9c9555fc3e58f7c9f57acb0b355bf0ecf4e299a3a7ddc134a7f0c55b0743d714b7f531ccd88a117352455ad0bf393f892a8c1ca68bc22581eb78767180f948da876a5173aac853463c0ac08a59a59a2f71d2a87da692790f4162ca2381f7b3bc7ab86ee616aac5859383a60000dbc9b0f685c66fa5eb5b363822ae5efb474052e29e8bb4feb4c7fd78504a2ec8a4e8f2a1bd706de5879af85cfb0ae97f899228adfd99f5fc4053b061f957dbfb2f3fc18763d286c232740fe0365aaed1071c3b5ca7a6ad9c8f2c67257ef415de1866f1ded75f4a91b476060971f4957cef55789ba6ce0a98c4055b032ca56f787a54cb0e0b5c04e4e941557bc1ffa6577925d3b751456b23e79e5da2a5da09d356d49f5f9de743ba94803f3a1992ace706980304325bc3cbdf202f26879ec5ade3bed43df1a62c7a74c0a26d28b3cd9e32175bb9acec2b1f1295e200e42887d903fc707ce30e51a024cfe2a7f114e57e7fb4655d6c22a75c7f70e4a9b48849c80de55e9d2328f922be409f20f1433d5919df9770ad9b8e3acd8e33d42c00615ba8110c5aa53ce94a28e3c75a80afc709c4a00c23636dd9fa5cd2f5664d0fae1afa0c5c93f25ba4d17862778d80c29709516d875daa365afe4057e34a7e924e30520686f0bcd495f9b31b9d986bad6d6bfd078657092e69b7bf4b1011829d5b32fce0aaef64a7ee3b1d2d6d67f69b598de2aec6cf80ab536dcdf56ccbed07ae999df45eefc94f91f4eafc3c3ecbb18ae97ff2bf0dd112d7caa904a07b02818f2080d0241ab98d7ec3193e0cff6b82810c3885103fa2f53a2a2b7957066bde3ed749ab51936c6da293bc9a911397a092188da95530ae8531c69b7d1b732df8c1f31d105e6cffdedcbd0cbc9ad5978786fa45aa7ae48bcada05f321ecd221deb70a407e7185967602c7ba3d69c58e72aadee0b83150a04003991fa9635dd982b1cfac65fd1481ef6e6bc635722eb7e474a3829dd7a7b0146173720aece846e4f6535024ac2856359036fc2eb4359c60eb8d7969a62500e759d83e364324592ae3645d8c830e807f473d21c63a88349836de8e9628189a649bdce00054d9faa14726cece551e34af6a09b3776be4a12677f5a746f62370bcab1dee4566157f21bdc8cb73d32455d79720016d3b4ef4249636b2c034adc416e9486ec1a063109e5ff8c0944a5df306d88b6fe8c9081d95434df6ad4bbec7f671b8b75b2b4e257b0429c58efe3754bc39920eb3208f1f9cb884109ad55fb29d989973bae98e84859d0a7d66e48c0d7c8256f6067e86f2f85c183fef65927df68e749e5cd1a7a7976ea363a9930ab5fd92494e6235006284e3bd1c052bb8897b01f44fe760a45caa0d2205055467d98f3e78fe00497249e87c55b694aec21f6a7dea4668e6ccca95fe5f6c556792ed252005b2ee7955086cb61c44b9dac5b49a8a7fc685e4260d1f0e0857e38926182fa53c3ed44d0caa7028850cce3cee7a658f4282fdc7ddd125e869da03285e9673a545bb222f1b29c69eee18167c81dbe439805cd59177aefd65840c9c4b65b7916eb3c7cd1c3819995c2741593fc8a12f5adc232992fed218d7cc3df0c85f1202946bae0da53203d4544c3a59470cc932f201b81935234f0bbc6921efd56134526f40731af636f6d64f866d7428baafae937ab1a88f5151c5b059be39ab230857ab34d1b7e265e19f5ec62aaabf3873f1b45f8b830927025f6484f70dedd3dc6007f8644b6fb4fcfc66a4da3cb7884b07ee2cb51a4ac628171595f5a34988f314a5a1b6e471c2a46bab69abd140cea7e23d763d3dd23aa2ecead1b905cc3074246ce46eb8a36e79035c20e0f145224e3edba29997df5af32c8ad9bd61c26de9099e12e1d2fab6bc80ec6154967b25309c727fe2ca0a8050cf70f9cae0c67e97f4eb13bf7e725b1322288ac4934c36dca45739b3fa56e48f18bf186e86fe7df304d5141575e6ccb19e1541e376b7b2f15fd763cc76acce546ea4ea792108bde121f3580a1905d3dce7f91a24db48fbd1efc62b1209556048b3c8c886fd6f8fd6acb2d759316463849bf4ecfbefdc9479c6326a64c5d43660d0d915e2f5ac0c27f8bbc91c15a629a08fafde5931e0d0d835ccbf10063010a57795bb52f13a530248cf7298f699bd83be3fe5604165a020d6aa311679d27a27d71635ad1038e17ea046adcf034475ea24ccb15ca51f6dfcd13802d462599bec748bf10d82e427d0c02108c158aa5215a0418a5c4f18623bd56d15be92805fb270eba2b5dedc69e040128546fa4c321880cd0919cebedb6185d8381c210ed94090b5fbcfc4c1c0c8e4fb7a3c70c7034363614630b296df114de2498bab97eb8edb269b2613662ca1c1d474445c92f09fff4755d82d70602add19b8da9fd0da05ca22ca07d36e0ef1231dd2a0c25e2883a13b26fa22f463208361b75dff1aa198197375a5075ff528dc2771f47deba3c6bd025a404b46f7d7e6d995af011a697779ba211e14d777e80d0bbc0284652fa6f40ded066c135c5567d1b81d8501cb78704f38888ac579fcb353cb860d6020b0725ac3383d9c5579bb01e3d64f5a42f60501e5d80895025f5de0409087d31902ef8be557aec59657e1f912336cd23d94724493d124f398cff9b067491758eae1c7dd88421e184f22b5b973987fa86190d1da21c7b6c0ec718951304a7ef4ed0c41ada12d692a6e7348fb48bb7007b1a03cc69150bd842e2eecfaa71c884d12f1ec396fe53473017025c7208049f038193f011c147a5413a83d89c0e43031432d3f45090300097219c4ca78312b3ba07c96bad32fb44139ef1eb54e517981e3b1d405095f5c071e553a4ea0f76f1c0f4a0f8d5a2ab42a7c5f1fa8131bb1b56a4cb616894fef206cb3e54f46ab8a1a14a8db133bca981b6610a35ec528adb4eb791fd6fd2bf33dcc7061c33549438283b1842383dfbf5cf7dc64b065528e2ded35005a6351c804f3844b4a1031daa3f77edbc78777b0cfc2c972012e99750b63be75dc91f6a00f9ccdbb4e35a0a2e0ca759ced3690e5335f878e682c60d0df176a6c75b1bc40fe6f55fdac244c3a1c972fdf8ae3e26b5d1a570a4263d1b3cd69b1795c27ef0c604c9d2ab950d20191805fbaa4890e435afc9ccde24e95ca9afbf7964a1b9d6956b5df7ad677ca0bd7f7d7dbcaa37667125be50e484590a8f134092334cc6325d1b38f466074dd7fe96f2ae01582a5680f0e24cf3aed2f029033822e891b35f74e677307b2f2b2f8c9797c57632f1cb0e400d655a8fcbb6de822f68a0fb1ba64e335340fecab63a70732409a534c3c961d9cef4b14cfd6b809c681b7320a358f1bd78730d8abfe22f13d4f2b3bd5960305323cf3e6091c109d8091891ead1e97302561785c9e572f971b5505250e675ed6695351322db60f663def761320cb757e042c37bb25c4074c1de344f46468fab30498674e871cec52d2ead5c91e1aad744eed0b303733ccb970068f606066bcc8023d033bf644a82aaf44d5046be29231f0882af429fe6813a97d775dee456b3307d4e7f1a21702e1a1ddbb975c0057a1e42ad8a7a0b7f64d159f17614d55d998ca266f93bdce69c8e88648618df184a93a141e60fef82bacdfc0ad95911ba13c85b31bac4527352b1207494d55d03250ae8d02d7d0ea242c98ed9700e91df68f1c3b70e810ce03113da3425a2120bd41e96e3217f1af3836179bdf62b09a16261a1229d4b08819c6052f0bb6960297b23bcd7bc3e5a742b5efdb4d190a0260eb972f15118f1725d5412ba4fd8875ccafd51d97c2942a570567040d52682354d9bc2810605aae409d68b7e90c99651448a122c3ccf473f9c31e0c627abb2fa5c5dbd0ad2834501b36b90cc2808286e96c4f153eea0d75d6834a379121b2fd0baaa90ee78d1573d602d2d12fbaa67dd673cfaac2ed3b32d3eaaade176cd1a25c01fb4109966d42cc5e15caf089ec5ae718edf7da4adb311a1ea8ff6e984ef95dc5ab9f5fbcd14d8b2c8106be3ca025c174b750d166ace5a7f74fa2b976f3fa2abc58992765e20de569983e661c626075871d3e00c299eddb655b76a5d804b02157ba4ef17e9de1a962a262b8cc15412c3dafaad51176280ee8cb7637fe3ab405cbd6cf3697570ee4ca44846df5cbadaefa2d75e74e324fa1802f6575cc6b412ee38360f34a58a7238a3555ba477f0d2c0b6b7c9fad83d447a9ded6995a196c833e49b530bdbeddf3a1f26d917ee44f52f0d918289ad9697412f127b4c1488c25602cc63c2352cf50b6f5df292f8d6d03ad4a0aa4064e17ad22347b89db38d8a0a17c347611dcee0ff3af43c295053d83a2bb7b17b794b315dd981fdee89851e93bb371385cb6fd5ee43f8a2a2d0e8095642ff93d4631f77b8a7832dad482633baead6fb45ae8e3140f4973439b24fffcecc7d15b04445c67584f63f95f55893b8f9af5f4923e7787f0fa30e77e755c0897a7af51ab74fa1deab927d01239dd67695e0522fbdad093cff7880867c5a6c856be7acf62b4b1acd1b9a1af520bde8ba3fce2c51841d91988f4e57fbd2846d88187a7a63cebd54795d89c4e0739e7e447bbc5b1d1177e43e7bdbd8f7c0f1ca444e0a80b68d3dfe5ff41501f5adc1ed512b2e8ed947e1be6e3a5c9191f3eeced06c232e8323c0bb45383d03a71247a2a8b02cff8896f2ac3bded8d68a485195a7d902971ed066645fa99f587c4e9a8591ad28fcba498dadeb5a88567a6634d557d1be87595065a5dfd7d753346b8d599756b5c0383d48ac5dd766f2e50fa98c9fee7a29d98e723b29a250a9a24a5b20011dab16de0868ccda8885ba73ace8cbc5297a36540ec1167928c52e847828f3eda23013855eda4e7fd6aad953f27bae29e722f5f8176233e1efb612ba8b2881103bff76e6eb99908930dece4e5cbd7daf1e3a6c47442131aa25b2abede09857f1d5694796e6e40f2cfd16a27e6ba16ecf3423e760572b640094eeadf5053254439c3fbceca2e8bcedc9a1d730ee6a49f6a1169458fd6efa5468f3258bcb3e7be4c01b53ebe1ba9d93ab64c11147570b3e805570fa4f7f4b5d24ecfa0391029be50a8330746c62048bf501bb8639d8ecdce842f863978538777b4302844089b1d566ee1cc917deece24a6679b3e2b4449c8747042276771115dff86df6ac84100ae27b18c66deb9f97a7de1f519c2d26db4b57453734b51015a01e5000fd727351d5d7822c59a2ed2d3c16faefae4baee03a01a5fd0ab9da725f64fd0b17b704feb31b08620c95408c62f11eb95ae86e0736bc2d638d9cc1797de6284ea6986f883de65895cffb4ad4f7d4acceebdacc90110aac5a33e26bdab05c6ee28c09a919fa3ff7a092a8b2f617037531614fc1ea21ccbfa9897ec75ba0d75a894eececb8e1d3e7f1c8d5a70f79d79540c0a00b17cee84ca2ae7ab5d2e20c051f48455c291126eb3805b1ed5e6b690f18cd0767620ca58d794860eb028949e608d9c9fc9a9f76b06730ca19dcf4bef74e9b5740d66ae9d3f69f5fa26fe959f5dfabbf284b828038b049ad92ae7a9cc685f0ebb98b4e9a9bfe4729beef682d9076d938f124c8b58a1c4b5c6c3e19bf2ebe1798635b85613166160523433c025cd8a4226494ad628581bd9c525f92125b649ea8e5020e2d9e94fd3c8d6a3e3d54f108759bc1f37bef73ca8b6573257c6d19a5bfac63d590f3b022cff8b49f658efd8515c6ee941c58c8962a978a4f68a9e203ec3ffc047e827df256fa7a022e04a9778ebdb466b458e3785859a628c65e8b6d6412d65a14107f966c076787612d1f467b4407dad8c01d70e82b4f547a34b96a9967c684c10d5d014605a0fcb903ff4d289771ed3d517735c854536498c13b40fe8235401b56e793ff3a0ae5114980283a20f3a39fe7d6aedd1be2c89dfba8d77368176c4c3fd784660a4895170e4f5c5dec1249f9f0bd6d3890a8db61bad62996304be6b558a1360d51b5b9d167cd517be6920eb7d884c7bf5b809e991df207dfcced8d91ba00e9bef19f34fac429bd2637ecedb91fa5ce29145078ed0c7afc9f9e025fb16b6ec669674c3a48839207dd7825fa1077b83e6b9ba7d1d5d9e464ff95c74764db904efe1582f69fdf4759b409f0665f146e9f3a5a76ed7d1992d0000069ae8023e9435c2532e1a7c5fdf446b88097cb4bbef84e0c977b9707e0ff36580cbc0708585b6c3ed97010deeafa5f8b5ffa2b6b0f4fd6a9a544a7e27ce45b4e60cfd04f4c81962bd57169e35ef3008aa1259d3caa5ff5f7329f8b189b7b6387036294684ee0c485d3497457a5419df3ce9dc42eed4171bce67edafae0ec00b20c5232a8460f2cc9f47bf2bda0f73334a7c7db3b42f061dbcdaff7920a662dc5e7318d7f0fdb102ba52592a4f8a0d7b1a0244fd10c47ea030d9a80767e874349c86e6755d545a152ead20705f694ca37d96be550ff3661908a77af32cfcd120c8431377c2159a7cb23b2c8660c3725b524277042d76ec41feb949097fd0197ef21671dee2c643d5af95d23e6128b7c54b35dafa48be7bfba771f5019e14b8c8b20ead4211b6f2513289a670002a085274cdf968cf846f023f88775e8e61f4b6fcea999f4d06ee4c9aedb33b6897a14f8eee1884c42a58341f570ce59e8939681c580efca0ae374ad6ed6cf7dc9c8d12e63ba1b067bed41a1d90cc652ca936c3698bac85827946a0214c448d4b60636aa0c85e8f04a4a6f4d11012d83b70f94347f5f12242c31c80212a713b838849f7d24a28a1756743afc3d428f8ff585c78b476e3b8c282a84499cee760304b8bf49bad1b947ac1d16f451e3126ddca84050a823ba4fc5c38c496434526ae813e3039b0cd8d7e2635dd2905c0b98690daa7e0b57c2855ba92a440a68f5defd95cd3c67753e2244f986a3602b3a324870a7e49304b415b76a1d02fe602373978a4718bcda932e9966ded9d7f0d17cb92ebaab5f5975da04315b3ddcbdb6bd48024043e0a23ca280d8c36cc72c49cbb20f5938204c9bc10a85e26152131b9bfeb0fc45fea9f060012d77a9956524be95e64d4e92798c19c234983898c94db7fefdaa83e118a7fc3c73446283c77c43fd8999969e169b54019733f32257b5a3dd81c84f1df78a41dbf4e79f68ee1344c61b1fcf929f3518161745228f6400ae63dd2551c431c46524febe05f442bf2ab316f029fc9180c71822b37f156a4f05564afc1157331042f0c3ab5fc3633e24d976f02acce3a016c9016c186e58325635082839a793b6729a4da20609aa6cb1d81146d0ed018adcf82c6f016c2668b515e6fa660db4d466ba31e23faa6fd2e7a1b3fa85c5bb9873bedfe0f78b033f67fd9096b5183682a214431779eec8dc560fb7f8cbee408c87d2fcfa5cb75582effda9fd7f83e6c0e359af1974a03f1730e0e351ebc871bb332cd8fd2c4fb3f3457a98e8dbef9ae1dbc6470afccd1a089153772bdcc888aa52fbaca86ba3edd23b0e048d77028c4dadbb970a679df645d2c9f7922328f41469c226c487c59bbb5063f3a8ca4fea268c49aa478ea20be0ff6d3ac6bc66312b9be5330666a9eb2905fe3e5abc3e7c1c5958882a9053faa88446957925b5a7734923741e4b574b4a645e8508c82fa39cc6cb52e8b3d108ac7dd9dfa0fa9723e11bcf0f07fb0ceda6d72d3962ae60288c5030a7595a970e0c6f2ab16670bf36d9688d14accef8d14b61c91e10d628b771263c351828a6ab27370cb5c7d2f8dafed428d653e951cbdd6cdf4b42184dc21d6701023c545d9bb3a44bba759a706f89246976fbf120644a600fc4eb219218ca4bb246ca54dcd5e62330094233960c86a886bd04a3f07b9afc889afdfeae75438fe2f179b9927c605bac30ecec3f02c188efed0b1f179c9cc9126a108064892f92c308b3d6737aa20a0771f3e692809ae2654412736f7e7dce36c7dab715f6bae14b5fb91bdb3d63b707a2058ee4ab913c187a66613d21c17f0e23b15ef4f57a9378f97c7bc54ae87fbdb1408699bfc084249a62c4003edec7ea3945c9f7fbad28772e4ca53484e1103f862f78ca86b9185f05ad2cb818e3aec04f6a94caba157fd364067a0525117b07db17c2ccc56a796898dd5da5ad302a5524a1ff469075bb90a9f6389326d4916ff96f49a53ac3d633c99e0c1540307209c1259b286266594c477d8e6c2fd1de1f669edcc8ae8ffbe549cab1cc2fae7eb6ca7b9083aaa22d047b6854bd1f671a48965fc950b03c0c29ac4a558b0179057626b544568120ffb3ecf753c3a4fbaf66425d46f6cc91fc0b68c0cedd6f5aae5a9567216e2420567d97057e8062a8939610d2442c90b7ebdecf9030d02007a9a04892f41fc460d31c961650fa23a8413670f36762add47dff3cb7f034632d351288705ba34770748db4e19ade67c8ae14fcef3010f9cb18ac950807d9ba299c0acba93b4b39307d80c92fb50dcc824f601b41b6f3aae464e08310e86d055d347ed57d3b6a841d6d1b93de68ef650b4b4ff40a363fb042b8f8d2bf4c1d62f76d852c5b51780d1d5a04fa269d6b6eeeadef494ad5fe21b4eed0434552c1331d8472600eb70ede4d26106ef4d051646cbf2ec89a413823b3112abff07df3c29f8bd3ff37d89666a5695944c23868133decd6cba228ba246038d17cc134f027a2fd566a8d8938dbaf7f90cb3b08a101f9f532fee55b5628556520e4aff0389b035e8d843d48c95c3a6fa2740fc4c525838951bfb48f4fa6a6449d6fc9957b52eabc3a7e7a33cb92ae259a4cd681fa07cc33a471cf05bbd3c9f0bcf48f52ee367605adbcc23c1505f1d3b7abfe46f03a4b4d587f208c10b103c6ea53a24b3403649290d25a889bae03ddc413b81ad745fce8247acef3393cbd8f698f35e2a6bc64cf55f86b63b7d6f214a80e983503ea0fe03f19234c0e500a43bcccfdd8d88c4e0a340d903eaacc9c836fa4152c8e1934c2cd1dcf0bc950a6e8c1bfc480b2d6c623fd4c9109496aa6c9a7eca697577886e7771ec6da19dd677770ec384b3ed5f22342e0b047ad22dcaa09d153da559bd95951f0b3179f956e9e67cd1d22e77005137413748dba5737fb7eabcf9381ab57914c5fbc1f6a49dfeda69dd1d31052a0a7838fa851430b3d669c33dbd91b734dab1de40573f30aad3df7adecbadf523e7efcdf2772c43600218838b23d5786a739ece2f95a7441d63e939c35370dd4cd5b2e16e6993e59a11401cb51f5d735666ed67009edd7213903fe8d1d81af16e358d97384a08282b7037cb319664e4f85cce8c9c13f3f7926db2903a619a0f807759e7c681f4728b1a2e469f3ff7474b38f368fcabbdb8bbf04ece98fd765d82da1ac5c9810476b05f4c6803b3955a820611ece9daee868ae71fedcece2fe240686ae0069507e300c58a02b5a284d93e328a14a8b17867bd6344b8f1bf1d4b0fc5479a39a072aeb22230c6e9e6b45a006058fdba02cb96be1f55228b16fbf92055604f56fd607aeba35a59241dd062d7cb270421ea8e3ef4a3eecdcefaee48c785daf970f52ed0a0cd18e2defc8cdfcd501ff5bb7717d62f6a4730272061d580070a2d30ae7d8a25366fa71c9e629d8370476118ea6bd3c7808094770b68922d038fb922778be774b07652086db2dca741755d8512948125177c44cc8de34e514d78d36f620a49544f7f33264205c5448b49373fe7bf5a2ad39fdb970d1907c1644ae6379cb0f39c34fadb5ba8979222aa58920dc05ce81cfc6d56a1a7d19713464d03b7709c68502cbc40c4ed2a1b115c1670e8a837d7e630333541ef3994f8137f4def363734396694d6245966f1ce12c674d3f8d5945455b2200242d73bccd3f1d7248a3e1f31fc1598af53e8eda3faa0b61a6f65a5cb349e07200a1d812645c11f65708397ed915029f191e8cf04386108c23b801bcce1409e5694b3b682499ebf1abeb67f44aa7796a60b60203c7428442c2c7ea0218a3413f13f2d5ecc20550432c96a9d176a8df452f4b084966669ec39f01c6f15220f63674a6b15da5de8470d7753a45f75dae01d97e25e99ef1481558567703d9590df048393f6cb316ab25579592e8d6550fe24b2206c630d81d922682f529639a6f2a43178a45b2b8feb66eb6d57932debef010a668a805cae625f8b3291d844fdab36183ba73cdfe6587da3d713c7bc8fc0f18645b803ee3e8c75935240dd74b205644fb2633c70b6b6a593973a6cdb9adc0efe6340e0135f0b997cf0dd136c606b17cef4f5b25e8280ff89d330562643d4c0c7adc013874614c55b878e982fe824afe38d44537b9c09406c4ca143c58bcc13215531b9bce4cc9f1d0b3347f571dcdbd2d23877d13e14aa0a10c1142799d4a4c82372be32f46716f59c1fbe3d1ebb7759d39ff0394dfc4198c38a1b0f7fd23a1d03fe705782274f484719cd0d668259f7051bc277a8e8e817971f1bb50aceb2c97c5d2602ec030817e231412d5763954a481538f07d05fd2e5b7d436a1df29f152bcc2601cdd2fd683df96639e037524d567cd325e2b0c2fd77bea5f8a586a493065addeba789672aacbb66084c9271d7ea76f3bdda03219b043beb7f77a6e7089bb2ff4821ab8a18ec2613ee8ee8e56658cf6618ab7d9ffdef32c230420c2b2af0c06ad343a7f18ef9621a74c9e38cb4831d8832d8f1289a70f3a1d8af558d5729926a5447930b0f9a57cadf2d60993a9ffb8a6b9c30f922a90b2a0786f138a0e070d70d12e1baa569b892cc88882dc6e23491a6414d2bf40649c66c5fb3a304f1679684f0c999495e475b17008330208ecd30adb06c1a05beac831acbf37748b3ff8ace4973c941ac57d27acd4bff3303cc594f8d563f09c8654e711b35842e9c2cfaec60dea36c2332b923afd821b7f992fc494fbf1116b45663ebabc3e950adefa80c36b0e5a376f880783eed8e0e7836c902ab3587ac22b0feb3573858b20b9c0711a9ed9eed37a837a75b2e122675eef94174887111601284b775c5ed12f98d2d4e397cf16e7bbbe444dbde3d93c91d01c5af0ad172e18c527cf51c60cf5c487a866c52e59addfb27ac022da0d5438dee6edb0ed81d63de62070dd03a3b829ea067b4c2d99df531698f40215e75bcb0bc4cdff4eb6ce3c31c6a25a16ec5829f08c35e4652a2babb426fecf0ce5509093c973ad709079c4ffb263a82331f2d484c9057570c3ddac20605c87cff203855b9b8e30b8e192805d1b6a70627a0be2cd03e37613ef70fffc057937abeab6d3943295bfcecf2e0516ddb51526ea4652da88f506e187eab7b6321edd5723b01a90426700f030937518c11335c789ed634cc22aa9aab53419401c384f83a0d929c2f12dec2e4b9f73fc139fd8e37bf88020074d1f9d7102558bd40fd2503b5c2a760bea0c31507af11c47ffe5972e9049faf593ee835b9baefa8c80a0d63c0440570051f2db9124b0248693f76533fd2792d7b5149a7330bb7826f79d08584f01848ad4fe4cedf88999360bf289d602f2c14d2ad63fe749c9f460cc28a6ec12f08bd9ac3cedfb0b1d17c19affdddfa918c12b5b4eac1f6e0cafb2c9b620f3f5f8e8ec20655cd1e6bb23bbecd863ac25c1c0db50c270232560efa4aac3c3ad995cdee0e8d8770485914156cb27bee5677171b80280de450cad51642d4ab17613bd01cf9f8136c1ed48124f7e662c81408caff6326206ec81b8e27108aedeb20f1091d64a148f838f5d02c7100bb59d7e5a5e24a19ce1930b1fec9587ef74017f6c6c1dc3cd48e3bddbc41a6d9beff8771752098a61570ba81b7241154dfda8bf5f2e7078c6edbae38ab23de8010ebc14ab83c3bf4be29ad5c94acaa6433d7ad5106bc5a42f2dc5e0afe96a762fa6ce0fb8bb4409128438337a194e08dddba3ec0d35a0be1cdf0b33c87acf6dab08d9eb74127acd454078b3863b1dcded2133bd9703790ec6c1d4d9647b8b11431d61d4c7a3264d8a2ae6000c3cf2aee986e708d9586541f3232d3de2438da55b21fac77647f4113fe19be66eb354b15ccba7a17c0ea272026c24b4329451a110a5a361f9796468648b10cdaf800683c0eee08e7283a1f796959d2bd51b5a0fa0d36751a9944a0d41b57539e8596b007624f8d601ff9c4ac8957e99e6fda613b2b05bfe1ac9169098fae5e3ab0f231134bfe208dd740724cbb4531b3f00b8802555ad23dcbb59d70dda31dec7a9495ea742b17dc2b5983cf5efdfa7a90111e1382059f89acccebb0a882cec1af33864b73c9927bb36a2a96554c39473d3677c3c904131c31178b7b904ae57bb45eb78e005a4cd02b87117b80c8fe936275c258ddc6a966ee5b61d848c3bf87759a2d758c6de159e7d976013894ce9e660212a00c80278ec7fe45f77e82bcdff5ad82e248d7662090bce167186dd8e1f2ee28ad7788a2700701d5001f207e0c9c2576ac9b5cb7ddd6ff14dcb472f79bfa68ad2256a904e058d16241a2287710577bb1fd8679bf434f2cace708d39011c77adffea6c76f2b794ed519b761d581a5aa7ada64980883996831c3764b5ce51cb9320a77c7467c17958e17c209fa836637652ab88dc44f0c927f82560fdf076a1af3966bd5de1a0258137560a39b0cee0eab0aeb5602b9762a161f7d47271bed12dc6e9a4e46eca5f696e64392ce5361b6b3f13b6063d68886f521fd0d9d485ee570b57530b1e43bb0fb47a9fbc11de4bb8ed11029da9b8dd07fca9dcdcf58779094c6ce73e39074f7c61ee36048fa108b865651f4d8b624c66cf67d08e55cfbd25358d3b30222caf80806d961de0e58ecad9b39451e6c44c1696302946cf8bbf7110589db08d8288e23615e09bc8a7e9d935181d6c9e3e611fbf5d64f4b05b60087e95f2dc2b531347eb4d45d13583df852aa4fac7ee9d6148aaf6f645fb007851e0b336db7b079718c66d339e2cfac4eb4be6f5166cdb0f92d6873394b418bbdc9680279ac0434ba07f36eb1089ece8f617af15cf8fd40f3bee4555364454ff1e47d817e28cdee5f6838618a915f3c404376c83bd863b2cceb9115fb6aaf6e0914a268cbaf84077114abcb0049804912af57ece48c9316715f4629a6e7696e97a054c7f9286c6458d70e714d4f5957a09f6f9ce6de43455e8c173812da5b84e754e86cbcd72ddd2e8715d4fe82ad211d498fa2335cc43f909d378415b4200d7bd51289044aa2da74af1f6181093d806bcf22efae80ae25791cd78e0ebaf63fe34f068d0f7637aecb55ca750c84e42fd8fdfe221de0ba26ee43ff0c3b4b0002366c7c5b43a36384e616134570b8047e1a60e89c3b5f2efc5669cc190d19d5f33d377a3a27db8056924f42c0cfacf7475892550a3f661e3695da2b4d7f2e7fe70ec571b6dd843a0d80858ccaf4abef880e68e43fbb2af91d0a1d9bc90d69aba470deeab1b447015f8f2f0bc4bc3d6351b5672ae0fa8227f63e1372497531d5ee015c6f1918485bcacb510a8148c4775040f2493c0a67a8441370060e94a6df486ce162b352bd1fb33be982387f5abd2c0fbea52363281dc0fb078c5415c966041bbb1b6cf911139066fbc394679c1dfce96ca2b91a8c50ddbd78469f4da7e50a1c249be31cd22d3e5fc0d23805eff4a043a581712769170b7780f97f5722158bedab074b8a612a319209c7b36694c404a266395843db535585343beb7081e16612e7fbee406edeafe4a23f71fe8fa99af7be7387b137a41eaca898af92564784851d89666d3b71612082344ee361ddaaa810266b65869d390faa49992bbef1567c9c15c2d2e906516e15fd1958a14a936271f5040b0dad71c65822455f4425be0e01d8507f04db1f756af3c8f6b80db0dcb9e082cde3a604a76b87aa287d9266045f9f6814ccb18a52d94f5e73c847c32c5d0b7e189f7cc79ac2e8fba7a011df1304eddd9b6a7bec754bd57da72b7f17a20c4aedf17a26e83e714bc9ddd864f186f5e60135cc43f1ed9d2c7100c290be16746df1a2863d53e2df80d5217bbe14cfe3eee07592b9ba3cfe6c676e29c89d49cb3284d8d26222f405121bea909e239a65042f41d3eb0f9376a4aebeb5e18de06b73ad6a28aef784d68a5ad82c0591e61bcfe106f87b570404269633cf4dac1e2753b9cb908acb9170bed74800a305327325f0fc089598807cae92c0692a509def3963bfafc13b42ffeb57754c314d52373336ae5c0e51300bd8ffc09077aef5d4524e390eea4214028991837f77108899f7bae54791ea41506615e13a472a75efa55e1d6d0a9bfd461f7a55e613d48e50a627b370abd0ccff6aa880153e2bb19e7cfe08107af76170de4a250350d4ea2fd249fbc7cc047e2ec38364eb0ae29936e82062f52364a2b46ef4382162f6ce450d6b535ef70a8953aa3afd557592d4f2fc165e96a44d947565a28349b68273424651978cde8ab512dea4ca4a0b520c841d590d999bb61bd77666fe81191de42b67471ffbfb193245520012b983ca8b7ea5b28a6e01ed5f24df3a1845e374f04afc5dfe2714a1f9c1f69cab25ae2e9fd9667e40435207ac1639abd3c09de6489277c3150f549657ff290d50597019d22f9d6dc479d7743b32c9039cd5f98a2d594f1daafe7d4063cbd2540ed04cb7726ae13a9104395b2536f8063ffd5d4cdcba111f8d0da4dc9c74f7a49c5313e19763ebb6926ba100cea70193efcc331f23b8cab459ed5a9540873dfd293b4ef9d1447b7cb3657fa1a86486795787d09c3717a2fe5bbfd2d3f1b4fdad60c864abca2c98baa6fbaf37588ff13c0782101b52becec71f51d8f900c95e80b9a64a4ee8f7819a46884b6df0b84e9dd04e9bbf0c18512992bf0b91e76b8eca53b1bcaecd81bcf19f8f44a87a9428ec6578dbb478b314f7b8c0a31298fd7229afc9bd2e4ff116e56a25825e3bb5fe0fda7764f69f5e8b41806ee59203a6c997c916d81e0591a343e02384c9781227e303df7c8f1fd382725a4d2e08111adb529349ed0813e3a85bc8a7eb943ce493bd6ea26b0f22572f1930d187a58e2544845537bd79c3cf9efde7a897eaeab8222afa8bf0330bb6788dd9ddd4b264cfbc41bdb0101019587337429252d5c6275496ea6bf20c71588c933f173ec880ad4a92978432e2b45c9c693e9cc1af89ba448c82bea59e22e010a4ac4a1f7df718d26868ef0afa807e05c1d009c85f4d1142170baa1c072dab8a9dcc5032b148b462198e96048ccc7b43eb5edfc5504977486ce4450d932053af8e91d20a9613ac9d63dab643bb0be082d8fa8c344fec5516ffba24e399d7cbc09c80faa19dd05669371b8111b46e31155892a32fa663a48c339e1ef5a70719242a4cce8ae3248b4b5217d5fc403d4ef8b2805bdaf9fe7c0d2a31d51cc6ae4dafe991d6135c164b730ba04df9bd4d3b6680c5429001d41a454e7f08d680b53868bae863ca6a0f1cb26dfc3b73d4668bb0cdedd52ca6477dc512665b7c8e661ae798004ceacd4ac622db900377d431d8b827a70f68393306c135c824079fda3921c8b5e8d447b1b2ba1ee06b614f0a57f9f19e086eb09de03f4970875bdc7e44932ecd16394a7594cbf9752ac69a9ea0dee1afbf63dda0d9eb62f0005d274026cfb7022c4c0c1ad8da43902a1c4b664d52138a25bf3ecbe2eba5b9949fee04660d5f6edfea603e68f2435f3f02e422c468dc15d6223a4ce131734cbebdf74335c8e5386cf93ae97aebc31bb92f8d4b4d90f008973f27d28103b95cbeaca1339b1cca67b262b4bee1cb2c004a138bd7616be9605e7e935694f09e0b5552bb2ddd448264a07ed09b7a36e00e0b4b4308a2ab9abe787639471fa377c193ad77231aa5fbcb7615945c853da849afa3076be5221b8f0cc7019e5e34fa5b91c0f532f7055826a3fe9bf3e5e4f811a64620a543c51185298a6e4f31a9f28f419f890a0663e705c74854a4d7a5e0e67dea400a330cad8e9b1cf2f131b3de4a433a0575dfeb309bfd87fc2c13a5ab0280b10e7b7bf8b350e32c598261fa65c231883cfbd20fc61cbe43a461f7d1e43173fd7a5a1dc508f2b65795fae7c0e8c3c0fe1d438238e8d749fce446b5b58c27fef380905ceaa453a8c1864d69f6c978c49236484033bcca5bcd6a1b0536ba69af3354011bbc1eff3c55b3eda0fc5cefd6925b37a5d1922434e4c135aca8bdebad3d80d63076ee0402d2c3aa082ca0491d92b8aacfd67d79d21f1a249c88a17034dcb847174d384bcf8349244e416f80e6b5484634c43cb5814a0b949e595897b4e064ce784c0e747f214253ebe5f16e9c8176d3a9f9a0e4edd5feb1c17d7e011f291467a6bbdce3c71a2d812ce4c022ae729ae76e6c2d4f04aad807ca115bdd2b7fd84971e59b853adf208cb6c1cde2705c43d1a23b028cba4d9dde725381726fbf644e056ca34293b108cc17810d90f5cd3837eb504e977a79ba230bc80459d168060df176791661f7b6f5309c2d2af7ddf9fc8b99709f6911e7e8ba912dcd96f1ac360368d4c0b575d48a6eb053444d2a9d9ac2767cd837469b0e1b438eb9bf5c1ec70e866e542c153bb8e5f3ccd74e8b27754c182478c7fe2bbbd618d89dbcc9244f4587e2e578c12363e999face9e1527a98300931efc5a8c699368a8d663df376d991f88d6c1fba92bbe8d71542f5d0343d44f2906688c8c63358ee2006321e3c3b62695f687b53df2e051af3dd3572c61dc2cd6b0952b28843e4f3d5b3d6be29e96ec5f2498a7bd319a3cefa22d4129f5812b5128825619d115ea62494a306ddd4d5e3b330dde975b3b32f782ba5f648c077f23fbfa67849612154dff250d82f955b48f8e2a3479438c7ffa358515b92935f56ea0a64c6c88918e98d3867557ed94434760ffe2bd2ab01a7eca3fadee031fc96727decbd6b9dfb2cdb081e2f6807626e143b2636b2cc3d5c087b1aed920508adc10cbb262535fdcddf89fd3deb552ee53f978abb4d548c0fbdf6c1795ae676180622d380d420b7998c852b22b8ecbedf2277175477d316bae4e21742a4f0fa1c594814bdbe5eb4099d424d4a61629a5446078907cca29354005afb0091339a2de17bc32c85b0a59e742a09be061a03afea297b9e12e31b2b052e95bf3a96ea321a66c227dded0a5c598bee970f6fd433c8e2025f4651b86544704d1cdd6b0f07502406238e35b0f8d999932dea72ee3ca3ab82da1785db931f3f568ca4ae02056d57a6813bbe9e0d53bd3f980342601f253572b32cd81dcd743dc6ba77342ddec7bdf874eaa2eb77b7ef958e874e9d03751beb6be43550675ff9464baeb46e523ac51ba33a73948707607b71331936c3384ef7c25e7a38ad3ca7b202ea516e80d861809dab3ab32f138c5e160c1318aada4825cf15d99e7c0a3ebd08073287986aaa3dfd3bff73421796dcb5f7d20c122f707b648a58f940b8af5b81365fbad8d03bd082f13381c7cf24a69a0b310856d88323e74c253e615a58d27f87f2727fe30761faa581399d5bbc1171fc8f484b05c5c7e86a97ef25f4b4fd1befbf3dde9f14ead672fd6eaa39633d47eda54f3c752bd0ae3bb85461ec6f68dcf2726f75907c3665d9811ab6a43e26ca03680d0b27538332a3c365a4f0c340a16445635e0c05913187db1faf00044b75fed2d623d58c989f6d64e1d7c2421c62f60533c2a7e4b6eb117e8031abd60c25d755c5141d513c87e175e0754bbc4fc3205dd6f7a5d3198894e27f228deaac043fbfb1f8878c1d50167970cef1f2aa7315e75878ec5263c61bdf403f01180009a80a6072542e63e2c1ea3418fb1005d3943a49268c377f3506ed97c07b8b819b2c295ba8e4282767e9e5f95d4aa8c7f7905ac77c9345b1f3711ea5e44eb609de705e5278c80feb79596d11ca38509c07334257c16cb418b349edbf36f573f609436967988cd52b11d0d65bc72b5825ba42dc40c284c17b86a52137b1952d6a97ba6cf06194c296385883f1e7566bc27613dddd34902f21f19beb66decc57ae6d40cb9d929032b36c791955b401005c2df4522260dee9790515420ee5ae148d4fd1a4e42c9e35d439ab1ad7adfa10f226f25e68a9780573a01fd8465d76bcf8ccb0fd0aca871ce3d327bc2fad19c6f8f401d084262ff79f402e9bb061f38d3dd5dff80dd60e15acdc635124b4ab2a9c41864982193f5e317154d8086529ce405e7a4abf43d0243d6156addb1e0626006113144a5f26303b8e03bc40967126b2a28546afe741581829162cc421e3ffd2603924871eef8078430262b087d8a7072655ea38c8642ad99217e3fe8e1570c4d79c2da0de22d7f37204a683c5838fbd7fcb680c3d8801ea09050c1eb62e5102792f5922b76dce4a624a1fd5d93019e6ae0b32866de6146b911de14cf131d99de0ff22fa6f031bab9804bad794202d8c41b380765d437422dd50575de72ecb8a92930ab21a1cd827d60c8841617e5652fd7df5e72338004e4946710e5dcc5ddd586339d8db85b8de135ccaec1dfbd75fe438991e1375177136068a093c7445012a40f98a2495ecb4c27cf5eb91dd7ad157147a6ac07a9683b14b73fa7210d83862068dabd76ed5c084c7e401d29fdcf9f81d2612cb68884fb37e656207b6622e1e9d7f0dbb42fd3923c0570f32ab18e1942009e1e6ec3cdb46ea4df19215efb4dd33a8a97af4d96592027f9a969959126c11929901b79f63ec18a8afaa4873b62ae91494c396360874b44f34a1d36ca2b2fbaae35dc19fc8f117716aed7ccc53d89c52b24859d4bec0ae1cfd66db149de4b2241c395b788c42ea991646a3e6465c0e1010d4e1de5e32675c19b9e2f3b87c360624f27d1b25b154c9c887c5e49972ac39b3bf0d4771ebba9eb2fc5c9364e64240e3d30e618525cad2d0be62c98901d1c72ad81c204157038894f72af26bc0d752c37622ea8afce5ba415e869f9b8699900f2c246f450ec0627c96b16772fec57833603ea9f3966613c01f8d3792bc6f6af5cd00807ed6d9c0bd3aefb9220cdbfbc4ea68f58d1bbc79db04c5a4e4f434159859a1254d0474d9b3f2dc04f2bd6b930bc96dc805d4f6e67f753e6042747fc4c1c0e56bfad5d3449862dcdd3bce672972b5fa2cd1213a34de228b8803c2f04954a795fce08c029513e655cdaae712e3cd72cdb1d3086ed8f5bf119b177562b3afc1f69ddee9abaaf9768a712a5fd24e4b561fb467501cf243f584e771194be4e391474ff1e6f7f1f72a58a03d12eaf7ce9c7adf415e7f65c5e4542de1cb308c87d16e905536c19e45c69616feea88ba6585cd093eab89cb529ef6a84fc8e05c297b4d8d5d1131d3ebbbeeda1cacefff1c6ae9f8696e65919563d5aa14af62174867ce4e117fc25ee73318b416da236cb294a489fcfdfa88754009dcb464bdeca0e3f99242a6add19eb991afa2d29efa06900dd799c8f927c3dbb1360f0f587d9932c8a0d54e1a13baa4157e72c7bc9df01f0bb2491a474545dd266e4d8f1404c68be8685b2fe3e2e1ac52efc70aa3144dc8e8feb80c28d80f31f2b7c82550b2329656b01d9f27fc7859b75c9dd64ae14f6d65d6f46909bd9f749a306897d564fa4ae324629a8c5936c8940de15e92e999537a4459ca8dacd62c3c5e8aa3b53cda765f623359f0c36cc7e3fdcd25bc6f496a412689b54f398e813ba9c7f35b48879562b897305b36c13376aa83ae9439b042a420ceb159e037bc332726e2c7cdd264109cfba1ec481c7ed055e005d245819acca50dbc354e4d234a3f8171d577290b697f8f5d4c241adaf9078ebd6c9338b4fd9418add6d75c6dcc554860166d75b80eb52470c309b5a79ebb24ad99a0688f896a74bb0525dda357ccb953fac23c3c0f8bf5f20b0ea29a44760ec7a2877ec7315fe9914ea1375341c0de9b992339b741d2076720d731fea3a2fb338a0f2741b9aaaf72fde82cb46ee782febe2de06f298883612339a66d31c5a27f7b1cb2bce7bb2b266fbc66c1cf3ec8df3dbba82bc71bcc94c9132a81fbafbd72e58e9f7a8e493f6d65ca7078f688fd93f8d81368522f10df95316c1e569d53662b6c9719de98cea652ff83b8c912c0159011d779ba88b63a98a6240a40e199e7f064ecbfcff5121d9fc96529c0d6d02e7f81b08bb0af22c13cfdc4cb211ed420e865e6ac7d8fe0164889c3ce2610de98d4f0efeb3f281fa71422b8f053b91f7c49b5ec84402478a0f90fc58f7b4f8d87b5abe23306365f572a432a5a154810647ab2c289853c1868f39c1acbc910819e17a447c69bbe47b991bd40c6d9c9f2d5144bbdd1cd75f0bc18f2091147937dadfde19032a08d0c14338cc0375a19a41bbed1a46099250e02b82994c78f4c23d4d4c6f50abe4565df26360a14d5222cfcb7da44aca75127ae63ace795d541b107ee5d0f4f3b09b9e7f517fcaede25338b6db0ccb2cc579b2aea83b7ece4cb3ee379f40af5fe2f247e9a9facd1297eef012a23b7456b33fae6ec86715b8f2d9dbd47d11bfd1451e5d4d743d31e25ea0042f67c40425d477a92f38981e1e44ca72d3f3f0dcb46b5366dc11277b29afca3418aeb456639dec17a54a1a2255498fc3923d4660a135f640631ace715bf4c2bf75d640880fd276558171e417ab55691ecf49e24c68a22c91943e6323f8d5ef591211a04758b0a92afc5f336393c17c613779d76915a150c8169ba92ac858f2433aa5e253c2441d23f29e181cfc82245d24d211a257d5b25e2c5a88573ec4da60b10b0e7e43e64abd636735e24b24b4c649086182524ac6dc2e7646fac74b93b0f5cc6b4f7331b6061bc4890ef7ebb554bbe3275413d590191c41865da4eaf5cef2639f3f3ecb21f9f04233499dd34a4fe3d700532d89029579c204c273176946b02394455cc4e31de328eb2d4f64a9603d22b65c15d9b5085802fdc83b637d81ddd67d57210264fb586d4bff2afea8a4528b52a995418d898161c1d376c2fcad4eca3a011ab8a1a2810aa304d414a7011950dca2eb5476c0074bde3ffb405e98cd0391099bf6b8ff0466f1d81f02ca1c95e78fb60a0a22dda0acc26f50582a02933de34bb52cb4fa2abefd1f52c38829d0fef1759d95cded69335911efd11182339475f48242439e68ec416d13119380f6f9277381a059488932a4471abc7da066b7c51ed6248bdee10bedd466976ab02783f48aed166786c8c5efdfacd6ab338b8d4a199b632795be069248a477fb564a24cefe04a682be5734e2a5fd429fd9e77a9ee97bde3360e934472383146370f6f6c8e6f583013db2f09b3ef64c005f19aa7cf9b25faad3ce6cc0402d68f336557cfbaf0383f32a28e244dfaeef8513f0db66d7975394da2c090b1b837996d93bcae60c0afd24055159beaf4e1df44986be1843aae2b9a5bf62c4ebbb224f5c62e06959698ff5145e7e2bcc900c88bc1daf8a353eb20f4a6dd127757174d9e5d1780a06aa2510f552a583f1259d8a413618a41196eb0e5b70164cddc863dedb369b8bab6281200eb21a1213dc5457b9c7590b4c6a7323ad672a4ea71db1d0db9c7fca6ee7cf9bdb5aa7530d8b18225df9104c955251e8bf2d56dac61f54ed66951ee106af7ee830d48097d7d3296e6571617cd40e760eeee76c77a4a5c8e3b7c62f8e622eae77b930a0642e2826ab79d2627f0154d8d87ed9c424e24bfcb0bc78419ba0530a0b25d0aff2e0b83e4de8228ec0d2ea253530c7a84be8034c9036e7ec7c52c3ede77de29b2607499e45b620822c2497b381a88568c2652ea245a5cfbf20825058602f27a5d3d0806559ad5b5150a68bf07c4f77623e6f13de6c7644dc4d0fea7884b0bcf2ae2173af943e9da7e6f6c3c1cd3a3bf3b2484e5ab614eaae7c1fac4efae9ec37c1bcd46a124da1ce5afd9ab785a1cb05feebfda188d6042ff84c470e2da672bcdb67d223c8b363da44f3d8c4b4d11683f9f54bcf1d5920eba129b0b6052af6d3c623fb408db1a2fb98dbf94b9bae76207004dc640a44ee9c6d2c1018cbff65e61f4c746aab21d1702b757ef5de3deccd14ed9ca0390905b738eb1b3a3469d3ac06e144c528e8b0cfbceb894ee366b91ddda40d397c531162ee0531880762a02fd0ebcd2e62602eb7f39d53dd0b7e86b3df6eea2bc4d39105245656e6eea9e1365f7d29c7344f1a2e2451e462a14729ffbb0b194a0c5b3eb8134eb945407889d118bf8a40ab2892a81df4fa6440f449b331a4b632a6ba4cf8b845d5260d1e08a22c61691e44f01fbf2ca0d8774e60dcf984ea5f0c97bc154058991ea15f9c882a90777df7baeb7e9501a12451e644fadcb9414809afb20754d4b436d6c77259b80fb4acf0732ad9d31a72cf176fcda3822e00c7dc0de58a25df4c2120db234d0557e9c437444be833e6e5608b5458bc6826f522ea2766ddbb12d1fe54c6b6e48f9f67783c5bd13ee4e69a69bae1a9211270112a8fab98d2945693ab6bea372e2532e4c0bfa8fa2f3538d16cc807db4a870eb5bd76556db258c9fc1ccba668660d0babc4d900fb3b8a75801f59983456519d85d81be2d93ed30344a97113c265879a6df8c260c2501f9de83fca08905c23e717641fdb4fa8c45dac2b0bf83e3e8d84dd85d072a5c45925d94ec49cf13563d3932b8691fc63fcd97229b8786ea00d1989a92f682b143b238340461b12899cb824c0b675c1d427709aa28a5e9bc4bfd5339c63ed858d4274185b54eac1e52d8ccced4ae49a262913614de3e3abcae05420ba6d68356893300e035ac1d6f0df44cbeb9908e01cb22f59fbcfd6f645b6759ba29bd79a9d899ac35c05e841c5ed3086dda9dd13fc4131dc8c7b26b7bbb506f7b721d38341e1595f1a3f4446de7bc66668889a96c65406cc80980e9ebf02363e49a5ddf4ac77e3c236307cf27a98914158f5c3de9c3489ea2b1943e488b2da58dbaf4bd863e93427acdebba458ed31a1f2ff5e967791c8fca47043aa9480793afcd90f5830590ab8a2f4bd49c974dc0fb1ac7161a3abc55b3e12eb8f4ff078a6624335fd42f3456831c8996678b59d6349e7fc2db5255707c72c02bdd90c986293517bc8d40be066ff6985676335a0a39005ab2b67a0cbaae16871ad06d407040c31e00552e33ad29e3735fda37ac3a9ccbfc8dd61557f839a888ae476f9a59402fd0874120f1533baa378426b21e303c47bcf7d296144cf80948bb1627260c526b6e47de4cf7734d5f89bfbaa2a2718f4e3c53c0b6a72ca2b1c875ce961f69c638bb03de170b39c81ba703fa0a0382d637ea501a9dd48fc8034177973fc826a4cc8be5b17e100f28fd57cc0f84845b4eefd577944ecf559a81d51e27c69d99d01dde3faea26abdd19e9b8cb349d75cc21f30d2439587c7ac4e4358466f42766e38c996e15e7c885d09680c5ea69a6c37a117a7a54d2aebd48128f5f6067cd2758078b853a914daa93bf4b32a29a394233e6a89e7ec5819d4d795d2b9d88b1bad8f935acf89ba82982d78b55a5b7bedaa2e00dc293ec0c58bc878001fb90a90700412a58c2ffb1e323efb016d513dcc1a233429bba2466a9fddd9a2e8aa1ac44d1d8ecabe3ee1b468d669b0403f32b814e0da962354edfafb6af1437f97d57ef8c97d2a30397da3b46469dba91bef27d947f7ce9728189d6eaa4f4831f56d199f8a886cfc0a82194b57d0cecfc412e4d9dba354353d1487a48fd258a6f073bcb304add15f1b28e33ed34ff30a54d8252fcc90157549fa635a1b010c0ad2835d3e15ca2c650ddd86bedfbe79a026826023b4f8c82d6972ac51b32927c221f84d9a73fab363f8d99f64ae9dba017cb8a360e79c49b9543a0aa7216bf0bbd59f19629ec2ce3e16446da84b4e783a8d3053efbd30ed62e11c43e4dd62cc152d2194597b08dc90f65d1747ae9332b6caa199300ae20c2b6c18b9e7d81af6866b09e7016e9da391bcb5a7b31a5b37032425c08765518a18645d358aab103a511c8517beb4ea02dee4f17ef17e591f1242bfc1f1aaa54a9910a900ca48cd6bc2c1ebdc0c1e8b2cb510d34e274e63addd18ac464c70c39027ca6d0c3e547f560968613e337ca568e07f8fe7215700989a460efdb9cf38e2fa00b3da149e8e0cf4a6a0c35bed3a47554d81daf9ec9ce8cae02d32c12e72045cb3f4795dd19f10cf023fd3bbddfd555ccc3875237d2ca045f2c70d9ab33bad034a0b80dce8ad3a51fa95aeca10e3ec90b80908d7386c12059ec6ad958b28b393db673d6ef1885595f360881a50b2fac0ab418b3b913da5861ae059e2ea20f86afa428881b90dabf2ae1d25d685db7e3d5099dbf906b5a2020ac85d85b3b5103ca5fbd6ca644bf023438c6a037dac5cac3c597081564bbd32b88aba285d2317707347d21ade83559bb7a4dbb52641c9d1830196bc0263904cb1dca5ed3422845256ad745b546dfc1123c5ca6a8f07ee05c051d19282c42339d82699ed839c08da113f79d74beecacab5da000f415835a3a5a112b8090912e0fd9fd388aa73d889ac73373331778935ee9ee4336a70890ce8f5a491e1e2fc6da4007916ec163bc4b02f851551c8ad0e21c01187a45a1baebfa1eee2a33b86e916d16144d3a1a86870b39cdef10711c2ff172f122038d4692bbd8cad3bcfe9dd4edca2ec56cd7e3628f49929dc8553ad461189225b97ef49e19b99abde599063c6c247bd3f6b09a6ba03e19cfdfe701e907bcf00b2b1cdff107d26d3e80e057eb615ee8eacb7d520a2587c6fa5bdea3674ef49cf3c22677ed5fbe666643394f1f6c09c94bf42dd7aae6b6ef25fa1a4f48efc28274e23558a1f999efa49590e49a15520b999686980a3c3daae79b5a728c8684c40d5fecd5bbccb6381f43f07c3f42e87932d8b7f7387877fdd45a730993a4cdd06fd8e4fbccf1c8eb88ae71cace0e43a1c8a6543a6299962ef5792a4e27ad2b1a2209193acdd62e06281124176d2c2ff3ea78b6965481d28ea4e285f8a62738e2f133287901b94bd447d2a43cba62b0e2270247aa6a001762c4dba32905933483b305f68e3b17d72aa06b6fb983153c6c98264a6d4a692dadffd6e74710ccaab36f31ef33d042c50dfd587f92e3a4e48dbdd815fd129cd7fd78e6d38b9b57bca1e295588e707dcd624a9ece14440a2c6846c6318def3d7b6d23ae3b208f49aab0015136ea044dbb400364bda1f69be79e0121e8429d65931a4263ddf00a159309cbe10a817ea03d7c9c46466b091a29d9af5dd7a9fd2c7e3464070a0a7b21325adc8da29a1c56aa711d9906ec1a8abf6021db5461ebf43935db2dc6998d3d5b5e0cf572712aeb9369ffa934db14361a5d33d207a6801bdc6e7eae78b9d5946e8d51dcbbaa1998e3ea759a48122c93cc6e53c016269d0cabc669b58be45aefa7a096d86d7e14b1fb7d451661e5048830f35faaf40d4426e450121d21ed72e32a74574ddf84b376d39f7dd7b2f83a15e4027f3627c386dd4f6341d8ab71fed915caf079a361dc7fa31de45f594118b3a7916a6b5d49b22c9e3a2d45c2a0f68c9db3442aa79d5c5cb0b4ecc9a62957f4de21941beede5adfc99eb313da32b243f14d721ebbf98a1821966515837f0b9c07edcb4b6ff39b3227e988eb2aeb947e1cd8aeaa94d5f14019ef960d169b27ac8d465c6bf3a96e929de7c86bd569c55ef85b050aa8912629915b01c33f805304bb085ae25b1ebb48b00d59679028431ba8394e03eced3ab462556fe906720d816aae3fc31e9ecba16d6e6ae8ec2d9c42ec863ef798e726c0096641beb451e3773b9f69477a64fa6448b226fd534f3150ceabb06c3d074c240a8638c9b97f2f6caab180978ab42cf4e9a1c7f74a28ad4b9a7c3bd24c55cf4cc0bf8490ff86c5a2143b24cb1e43fc55df7c880c2fcc1576a697e34c1ecd07fb27b3d114cd496d572a33b88d377490f667af8cadb7f8acec4e144c05a22f160362a72938a9e80337514630208d7d61efd3b1b4cba05467ff7bfb407a21b2f3280f680ba23590583dffea7cb17117ba4148f10f928ec0eee83e617615ed0e4b020113d3c0db797a9d5abe46e428d85b1eda2c7b882b2a43358ee587b09eb72e96feee910dbd40202a385679701a4c460b20a67b0a27e22974c7ca053cf99b039d10b55d7f8488ed6622c8298041ade86d2ec55ec72de0a56e76356b118dde56a20a968f8a8bc5390e997c98200d90939b2fe69380dae8c969c203342fb16e9441ec8435988d527070e2230fadc8a62f49d432bce4c8cedd46700cac89a090002104ed82ec251111d6e7b5e43e677e632c8ab5bad874d897aeab1f6125c2cde0c64a2a14e896c545c046a9df9df6d8a37b735affb965a8fe966d5e9e153c79fbabc81d435b109c515f8a42cbb8d9808f7252f53caa5d322f8f43a7f923092baba745924dd2fbbc97df32eb9d18939ecbc7eacdf74e30a03f46503a792ee9eba6ee7ddc543a4adca8ddf03e8c496e39df2969f6219ed123cc75711ba5d3d440ce08e131e4a9f4cdcff3039be899db029057a23ffd337ed36698ada6b684f7f53285da1a1e88d1bbf1243c5ec7d4cc6c8737215e6985cd33823de562dba45a845597e56b08b4c8bc924a5e4bbca6f99c845189be4b049a55a95b48b8bcffe0d79718e663803f845be18b84bae91544f8cdb2c911ecb6df107379e08adf5aa97313b9d5f48189d7bfa0f36f06d4620b33f01113d2bac4c848356a58aca8980d6c25cc34b6b2934e33c7a8095a74d84c8dc290e363aea15ce1334f2a417d8d05bf1f9dee9ab149def4c0f99ed1f1e6b8579304a43f9f19ca367cd876f12e0456aa77c4ae6f20357f033aba53c44ed13d5139a0834cac52591c8826887ce6fc6a0c74e81cadb5bd184bf4d9826a70a9c56d18b7c166d474d8d4b8550deac61929f2c0856e8af3dcc68624c0a4cb68281b1a87f5c2db04085bfbd2f5f8050ee92fa8b8aafe916607cae5c07b40945ff8e7ffd752e78856cce1b8cfbfd42b35e2a27183e4be84075a744c0b038e73baabc6880181b9dbe7e4af0a06e512b247a99cccd7f7e61d68ae777350d743dafaa963071e8e60819273cffe57cb648a5573d340870f45850b14bd735942bdc0396c74792492171089b1e814923660422e770e9a1c59b2ab094b1b7591cd90b881e1388ab8bf20b69868874cfd60b55ec6eb6e845784a5b3c273b4e3805d818562486d17495e8ec6825a8677ead0bb2d289de843bd32e251801a935496a9674fc3667916b53241ddbda0a6ebcb95d38e8f3a1d4957ef45654475fd270260cc481523a8e01521b39805679fd607c83a5b644397b565dbc66a9b1d42b0ceefc2fd6f1782fc7719c5dc5d844174f7c0e5c29f00779a1eb3e5df8bfe8789bd1ea3cfd0103c25a5d9240d87436b1e31d2e9b02a374e422928ca684810d317b6de21c5fa57ea0ef1c032e4ab4c89259a2a223486fa8231b8e67aff88f4cf597edb9dde3a3eda62efa68e7b3848e2c25243e513f8367da9b92514a7af27c934a32c963c7630f214cc900e7779eeb7623cd72eebb5bd99868cc70075ffadc8a5333d01fe82230348be651c1a46bd4c4bba96d1f558da016363545481214a39dc59d44c99ccc71180787a0d24bcbc5fbf7f836f1adfbc67808b585fc3554d6400080d1f8fab56f78c3fad8492071240380f43ed3f682a5c8f0d0301c32cd5794840875b6ba6adbb9038e3f9d72c2c39fb9cd37607df1182e8837c004ab937bbdaca1bf612702a1a7b3f9615f9a3914f7802c935fd5a9d71d26eb7e9492a40e40207ddc7313bb55b01e2cace655254910cd326e4e46e5d1fccbfdcb5d2d1ecd2bd4fae1416c3c42598fc85e592827bd22adf4be5550e90af24aa2994053a09f48b9fb8bff659c5c3d342d04cc830b9d4347d2a90069512b91f462ce5731480f139bced031b314c06440308184c4468b95403d1f0109ddee4eeef3d8fe8d45eb0e4eb1a16c211cfe3368cb4c404ca5436c66b0eed5dd3aa1f5065f62f8199089b7e0b3f28dbb54c7eb8c62f3eb72e29a7e89bb4733601993d34fb880d996800a487a4503fd1762e9e4eb5c41defe8a77a3bb78f93077277671a3bd468c1e0fc98d6fd95aaf93e588a53ff2197585311ca7ff420b442917c5243e95c916befc61b12ed7160992c186715ada3b25584b2075b1f4c1fdf9574346cf69f0800c482414f3eeabd5dae0d7a9a38ada09c648552fad38f70ef8b258cd0158e2f4a4040306d947e3e93a5b312e2d80b8e0dfb31bd3955d4b0a2ca870a8e05c33c3a7d6e1cc132881885df214c8def10b057390eb19f5fd7f913db9baf11b7801639b2171a11f91b12324b2c4f08d5881dfcc781095b8f004b1d1faa3df54d132d08518ecf44eb6889f85188abede00ca219a3b1fd7105889484e06ab9c15b3b86bdca1c0b67085afbc2c962d7c89901c877587c239f0e232c012635e9f38671d7f281942696f9b3f0ccd93ca02cf3ec770229a552338f8a1feb4b336492f54b2e43d72b598fe629f27994124c2bacfe6cc4d6859da90e2335399c7e698bfe907fd9fc122b393691b965914aa240349fc524424d51642e5e09556528e183e54ae8166ebf22b97bcb6bd8e27f8001587ce95821a484a5f17335c539514fe4ee0444b72168fab76cd0c21d1de4019f474e045c9bdc22fe7eb79e85d6aab80a9323ae51850699dc732a4d60da1c71251f4490373ce19b4146ba4d80e686feb2ee1ae9e1086c92b91e670a2b45c684f3c94b9299d54c4ea1218c7c5c22701cabe0a6f5ddfbc83d37a13cd5d497adc3a34313edf23daa53cbc9e798172ce9c7fe2ae352973b54fbe99cbd335b1db50aa149d267d5537eb15cc5274149a523902054297dd910894d8e2d94268224ad30dc0936e265e4ed51c94b32b9c699b45324c21fbd971cfe80aabfcbf92ef79a6267992d944283a807ce2c4243c25874a74c2f892c5a4b1b6ac12bf96367113b0127173e9461b4f05057d9c01749bc6374cf8452503be42fa3d10731f1b56db9a2448a2a21c24ed5cb4f20f40010708cf41159b00b954ceefbb1d9622a969558f42a767ddb33187ddb100478fe67db5d5be8be0caa5deea023748dee4a1fa5d3e274a502deb0c7d04d8d674250fcd8af6434de38bd762ad71798e2501835c1c264ebde6be6a38ea5037c53990b7eca07ff9072de7e6d8219fa43eb3542478dfdbe22aa724a99b47f13b27ea7d076db3520cc7025bfe521cf0bb7be7114149612440a539dce61e1373598d852cf3594802fa282247be320ca1eeef904abdeffd27e9da73cedc477208034ef27962d5f71e4c121994a3ea36da33a869f60c671a8e942f17892adab7dd3ba7708912cad50bbd89f2faca666da3f774ff21f82a6c1a9e64a03bb072915e517d4cc8be63e37b8a1783939410e794da172da0ccbd2758fe3bd97d46dea274651bc7df000bde1176798403430697a7a33c76845776fa498aec57d535e5106c95d9d5f2338d3912d0644a9aca782a2a147f4d5df5a47f1241b3f719c78c18cd80b39088ca1547bb1dad2596d720c6da69d4b83778be2a74b327a11b87aaca40923a99b333963d7aa4a5fe5d2517fa627558813efd28ad3be6a59800976a5e17d28d1fbd8283c3866a51f1f7f785027709e671ebf99a374925a3d4e791464e01d07a9bcc2f5849d0b8fa0131c0f633ed0c5cd71ffac17f53ddec4e487b64257e89fe68346d160f7d8dcbda6d8da8584be7b3210e44395b02575edd54778b168739e8a30c47c8c1b4453ca5a4b7d4a6527cc700d92c4224158d5aeec4c17ddd5083bc2641edb2dd9bdc6570c5dc664486403d56bb634371d5c33543eebb56d532917d0b4f33ef3379420641c2004232a419d987be6622a2d10f62757441b2cacac9bef6112c597da78dc106d804f1eefc59cff751fc3b4593b8be3df83e5310c9789ca0cb47c895f73eef9f2431feae4dfda45a6d6756c414296c1f97bb927db46db31532992ac1bfe08d277faaa060ba69cf4f9625553a361e8009ab78ff03eb7f08cd99445570ee2f4de939d802115528222bf7c6e729a50d4e0774519d2ea4133e449cce88b1b042cfd731cd8b0b615d6fb82c307e7441914f89d9704df391cb77b06cb980238e5c76f2b1d1f5b960b73108a4fcd8edc816c21aff994a8ce3a394fb6119af38892fd7e2a2509a9feee4405ae49ee35158f9d1620dde7116ac38f85bc786090596cc947c7d3374045a5710e54cf90417ae7e1402f2a336e39f4d503e33d11cd1f1c0298018d0a9de96b658c96592bbbc10da57ef49c919bbef110d0f5d5a11d9ff95a3009344f409435684a093c9667b5256fb161731eee3c199eddd242bcf22352b7c5f9f4350368216ef57e99e7f58a21330625246904aa4f891e46fefb30e59bd0d23a056e8f21d4882c6f58500634a44517fc3a856494926dbce41c2f6ecd66ecaa18cf57bc401c9c743358faa8e1991e1e09ba4a60556fcef02c59cd5253e2e888963055ef6c3178c77198edae5e90ee5b917712a1190e5c7945fc2b62c1c95a09e485115aeaa9d4be7025fe972e5469cce03f2fa1ee637798c84db7430e2f7509cd17f09c6f5d1c1f681decfc59adc50c9376fe1a023f8444376b6f61eb28658635bb087b6dba5e41163202fb0d11cb01002e83e3aa76a6e3a7b11b5c91c296d047a86e0545c43cae174404cfaa93611a615f43dff208aef156e05e33a541926341e9e5513ed259b6eb9618636d807e9177fe60156b4743a62b8c65f067b0f4bd5967771205f48f81eb3e453ea4c33ba51b83b99d2fc8f301beab351e626a1fc827a564996347c4a9dd7928320cf04bfe21a40bafe32bc3632fb18e43421248de9a7a1679fc4ae675f11ae704708b441a7e1b79d490a0c686d3f0a6d66458130f944d12587e0a7efd41751712769471ebfd73188d529a4ffa92681c8ac58f3a1aa23fb930cbb5e65033775ea8e026655925fc630764f1981eda8a62497d1a2b0beb5b4c3a00351f6c79286cfc3e1e3f2a67317b7712de03d626b877adccfbd9ea8d535964397951fb49c378d344af321d91fb782b0688f934e9ebe2d8a03addf517da6e4fcc964f537e1e2668411691bbf1686b9ca2345bce586400db50c890fcfabfacaca29e97186e88eef30610ef78eaae9f6bb4a18a414e54d24b4bb76be5c8216419e104084ee31fcd1b0bcc2607ed5e1af2c3e019cb0fd6897f9e1ea5bf3cf9bc9e90c962bd6d66bd62d7bc1fecba17408b2f219d00513795802f026768c006e080515ccfa8e116e8b0bc56063747639d5ed46b924bf723a0396b37ae869cddcad624e98d3e1fb82858665345d37a911e62179a0ffff9f23c5902a36dff3595984122e29f490c40161375e2114a1103db0d4a49a5ec8bbceefe97f70caa468ca84a5afd0600fdabbb5a5c5d1d5f7f6857673a11228d8d28801826e95389ee7be40d93d49fa1186ad2155a14812527bfb756a05e284f1286984362416c256a1fa0437b1ef4f99b3210a3472f5e3522f33d0a1486199a271870bcb84c09e6e22afc20a57197c05c8d26ce7e4397e3674b5c15af27cc4f776d974735c0b9cf4735b2eb2db1f2cc5cf72c98c21b03d3c8defdd9e63d5d701286b5d4827a4c08de7f9da996942d80c8f365fa57817c3d784022de5bf379722786b1a4826391767352cf76962a7b3305e37e8b9dab0029d8f62614b279e4c5c8a748782b2cbfc3c630f1cb8cbe9896d5d4031509d2eafde3c9e386a78b612ba5ea31bde6eea6bc72ee2283836e00708416213d4e67d783421e8057e4314511fe39143be59a758d0bade7f890a2f1eb61ae39636237c3b0b264b410bc86f9b46489840323cc1b479be659d86f610e492c508ab785edf374f8319b31ed72766fb9a98e5f3ab64954b0f67ec5d488b4cd809f6cf71e7fffad53062bf312fbef22a6e2add637317376906aa6e72643635f03d6302066d65b397826dbd8f86f51b7ee64633ffde760f2bcaf912beaf2ff1ea3b520c6ae42d798471e42698865edb41d4479a33d75f214f6900eea843bea4544c77779f14b8ce0a6ad7149912e95c06af686d6e7e503255e60dacd18b3b5b1b96384538e7df2c58b08d2f124a1359aca9079b15e471eb3afa7c984caccc2f3d4d757350b8834c3af4536a8cb5993a2d28c66cba7a6765f59411cdc1c12af9e9bc892d54f04b9db6573d488287390c5c8daf292e892e56dc6afb13e86354a6403e955668c7272782ad9365294dc68c606f30465629208a04716f7a86b8c91ab5b9386d2bf8c35df360e6d94ceb5828db8a088d22339cdc12f36fe8ae76bbd773de0ed385381c8a808c9491bbdf25dfc5bb6ab4438f879249d8ec2bc404bc7392a19a9646395d8310c22f3ef4a05863f37c1e16458e659ef178246480ed72ea3425582060c312a570e8294b2fe68d8af5bf7fba9bf051ab5bcf15c2dc09785054a8a6146a0d940e7cedbf008580620d9cfd719d8d95bcf61324c298c40c077f1d6322e48b9917ff24b1b130ade5d362952d6cc28764a7ffc72a04e5ef0dd22eca1ceb276ea334c8adb3da1bcc3486a7fe6062fe04587ad855f26b4c88646ecd472d9f550c3d79adfe106d4de946122f438f9995dd063e60d1fbfa2fe9e321e793203c29660f4b23cf37db062aa7e65ae40190f9d69fba0bcbcc9e0563fd5f0991e7ce05833893ffa42f1d188027b502fb4ee9dc29c94a933f4a349a7c8e27b8e4982b5b3a9bed83d8ef2d909cf3aad8fbaa6f59dbd4ecaa17690be6eb77c164590fcd633b5579114dda1d91d86496afa088cdc778658644d7171bbeb79e28d419d0493e0adc2818c103f2071713c1fba135e450499ef6f471dfa49f319176adb79068025259276bc984c2f2f3cb90056deb0a4d70fe91a59de78c7a25cc159d6e3c9b7c2a0e330e1a4336b7c0c9b6e4572a080ef9504f2ab28c2c4b86a2411d9c4a110345a2dd0a24f0007e2f67334d887dd8723713afa91f435e72c69925496525c6a6c635bfd9d5f711e372704c39aebdbc7c906fa8ef4a94bce9e2333d1baee4dce570f8021d3bb2644abd3ce1d0b4f1673e168f6220b006e1ee8a388f29ed3258899f0c1d538e98f7473367156072700e32d159485d8e99340f81aa16146699d1b2b23e3458879f0c7f4a8d683162904eea7d4ad78349d4c4aad4ad089aa959a26c6348e9c25e046827fd83422d440f04a981538173625a28a208a022ad71a162cb42d6a8a8470250f8aba279b7a1bfb95600216da6175d720ae6441c068069c74ae295009fb1fb1f666ee98cc9c061521510a2da805f700d89428db547655d593ba9c032543f27d336adac7bb68390efdb9f5a8ee87f897fc7616e2dc76b881d8d378ab00c3fdddf8f54e44bfe79522726299786529304a5adb42e9778554f0098f5f27e766ea298d401d55029e61bdda9b2b97162495bee36826c76f9e0233b5ab011947eda7909c8847ff236681ad69e6e92fab7f5415af88f89365ce1f371f2ddf487a61ae1f70951448721ba9d945ac1468abc53abc17d973875f363214573e62fcc3cef51a0e8c99e6eb7f8507ec41d70ef2b2feb858ef5fed223c2592b9c94a461dd97d16fa07c7e2a68175244e4c691adfa2fa0f42fecdbfdceeff325fc2a0d17a018cd25509974d27477203f783c7519e0a60b367385e02f447d221c257f92fd898b2194dc806c9c579dfdd19ce0b3bd502763c51c3013722314c761735f1ecd9edc372d993723396fb5226c7a950a47f62f827c71205f01563bf76d0be154621aafe922dc1dc9e4789b2b5ef289c7a9d1f111dd22a47ba82973b296797929f10a72a9f2ac887fb3b58e67546a959f2e2778b1f0e4d885bd19ca97256d8f4c115f3bff83d5dce59a165e6bb4dea6cd96afd62f9851cd7dda9c2b0e243bafd77617a19a88295560518a91bef2be17b440829e9e7d0d990ede69445042265dfb05d5f83fcf209353b92e7fa5fbe839a7307a572c9eaf0e39a583cd0e6646ebe7e7d7f11ce1a4ac9def66a8abd0f3d0ee37e73a519a0f7ac37bb12cc48a9d23465ebc41aab4b68f4a1de2ddc55faba3c18e3043aef27153bb51d53e467ffe0ceab6ab34a0cca86b3490ecc0a6fdc1d7d012ff87de965cf622a1fefeb46c103d947daad541f7138155a28a5d87eda3a6111c2c29eb0649a3a02de0d64afc7a3afbe25419d33d48612b2c3fc1bab6f58a98589d863f9766f8672b3c054eb6bae3a2cb62da3cae60cc22b362e8da3f776362575c8b758cf8bb852f3e38acda4e4bad674ff4d07d474bfc46deca6d22146c79dcf3959ba610e7c4afd67dd83581ab008b6ee94e414697ee34e32be1518e8106023fd59371628cbed47193c13ae0bcbb499120c72fc6113631b49fb4a6e83ce81ecdd506d31fcbc6d757633ff4be754d26bb0878ea121beaec3d7c35999dc9183a45e22ef9c787d27333197914290b67f1802c3d6f2868be420d100ab55fc50407cc1230598e28129a486b277c872f86154dd503b81a23458f658114584f2dafeee6ba9ae16df0bbd705efdb5408a9c63d19d6799763fa7d1537fcd881634ac5873ba01aa9fc245cfb620032395c41a49de9847161c558bbd4767b8a686741171755e6e373be1e95ba8d16a764a6fc378ba6294ba365d20dfda11618dd4b93f8fbd95b63372ea501423cab7a37902a385fa9a4fd4eae91046ae63a18ed414f863361bac03aa2866fe567f32654a19b73de9ad920ec5dbd0dcd1bc6af321bc0d9dc484c707587b025a0c0fcf9f5855d4d2fe991c079a95416e73d54751ca20d1465bb7745cf7144fc6972e2236d2de072ffa6798efbafdfce50a4297f62b4db91af4344c58042bef084de8da3c2f31a20476d9aea90ad0aae4b6421f2359506fec2b1483a996edc37a09cd9b49ed7efd0be8403017da59ff2cff2b0d43d55a0a5b104e27a6bcb819c4b68101a564296e4f1d7fd2b2634e534ff0d12ccaa465be6c229440ff66efce6afe75cda1c3c4893a894b0e095cce67fbf9a872a0062ebcc5376e0bbb5c8316afe7cf80c3c2f0fec509c4aa3336656a9aaa42d8b0738d7ad8c9cd31b16b8427b4ce6a55c2a43cf5a7f7582b72f6fbb1b8ced3e5fe2dd395e4b5564f5a8e9aa5fa8239eb0b13d36da56f5a73cf7b2c8d560dd681b37a22dc40513c5ac02a3d9e87597766dc07b58cbfbb952039c2544a94451a81598d571ae6e0102456de61b3f7884d913ddcf4222f3cca30ba43e2c47cfd91d6626bf620177413ac461ce2d47b9481c1a6f1afd284bb59faceadcf519fabda0840377f58c402d83f7e799b6a210178903d2abd7090216775c157638d60cbf5ae690cc44d3ead9a6c9b7113450801a159796a9dbaa5194603b7a3fa392e0e5feee790a1b3a484f2699b869c927be9896eea390dab6a3848cce73d51573e72769862731e48aee98bc5e8815462bd8bf1b9aa03bed72a4d650488d1bb83a913e1a7e0fe7916bf6911be26c6a1f7fc0bfcc1ee73349064ec1a1c20054479725e0ed56be738b0e8cd2ad2d081dea90d60fc320c17e534968ae801113a2fd09e248b2db5c6ee281f3c5fe82cbc504cb4cbff4b87404f39f297f8ee72bbc64c27121afdf4c83d7154ddcd4b59012a395474b50733ed4b2296dca946441e6f9ed96ad8fdd8016cb30b95bb945a0d3cf007b8547a8c17becd9f2eed9358100f0e55c775b91868e5cae650e8e02363a27038cee4602912fffbe57c04ee48e265cb3820e551649f0b58bbadea0890fd322d62318510098a6ffa3dc96ce36e1bc935ea52bb3fbbc8a834fb96726ef2a27de2166d43f1c1d24c13b04eb3d76e60df72c79ada70e560ef35973f59ba9d5e200cfc0962edae8b476f1bdb7fd478e8d05cd3e5834205d36e4ed28c6ec367113de348cfb26dafc1bf159c34d8a5199565e005c80f5945eebbd59a1ec78c539e00958bbe0663f9be4e8bd8b067be7f451d723a324625b374bf9cb34d89c999417036556bbb39d7a0983cb8138d6ba2e1d0ae74f6889f4d105d12fe77eb1724c05dc3005a58a81576bab2494ec930e738e98f985258c74574c475fddfb5d19dbe3c9de74b0e3a1a810b91c0f500d5b28e68c83b06ce7145f1a444056a04f112dc8bcf46710ad21c25ed91eecef1eb7fe5ca772b6c09c0d1d0b32466285f31a9796baec80cd12721fef9d7623231a77cdf9790228a054e016c6394e3b472f318c3cde6d7c382b4f43229845993ad3bab6a2f1bca51f2769fecf5e9017e604ced01a940abc74c4a66cc96706b10bcdb43b0f38e85f1bcd19dbd39e60152586778ffc843ed7432cd465ae354d085bf95f5b06b339c2837f070b50fed9d7a282bb7ebb5b42618e1981c56a66fdd54a5bbe6f81d58ed130ca14d914904adec447e07da49b2ece54579a28a8db14f5c21a323ef263ba6756cc865b05d9c406287cd3a861fa539b2e601801ffe03bb7b47f9c8cefb8024f969429bb26cc7db4b2f7d2a9c1b11545af201fbbd9938aa5b84885190d09ae9e4eedfc29fc26ba9542d0eec9a54bc05bd604c0627931921dee7fb7efc1c492e9ecd25c0e2739363dc6502cdc41023b5341f4b34d05f3b40530aaf5bdc5c11241d804acb167d97f73aeeca7a67f61b35e419ef7ce943ff65d8a646f5b23eaaf3c35ebda7b14ee31ed58ca85c09033da83f7c5a9ada982c4da5eb699c5d6fc8e4321daf7080bcf59b91108764582cffcb09fc6be57c4a559728c4b0da02326168617d6c056fe1d8ce4c24cade0dc7c86ac212ebbf4c857ca27daaed110ead33671b095550c4b86f10a2104dace54fc636c87e23caa5cdabfce3e492190e4a3d61bf47aa3d6772b502a73341287e597bc13ded74aa6df7c2258fdd4fce7e3f666bdb7b92e5e746d154a5f77025cfae084c6a7f5bccd93a8cbb8e68062931cc417d24035cd887efce1de0558dfda8bbc888637d6a78ab8fabda75b56ca2b8fc993f0d329518e9c531646902ac3c33a59733ef4994a9b27c73b97b3b50abfe6f25764937cb6a820c11b03638d2f328330bf5023d4279c8b4bdbcafcb46c5fe8c1499b2ef1c9351f88febed1b0856fbc494e67f9665ec88d71d82e23334da4f5e418f229df4d098e554aa62c823aa25ad69de75eeb9e21fb0327957038dce46a63d139940232df8618e80ccd04bef98b7dba69901883c575786148fd183b5970ed2a3d394c70665c1e8e9f08ffb5bedb261e272759afbc7512011d6abeb80092160c4cc88ef5d40c5f7a04340214b8dd56ceaba3339a0d3f9d42265c80114aecf0c0c24d3710c33bdd64666c7f59539090cdeecb86098f7b6b599a1d9c4451074deacfa6c9f32fdcd66d198ba089857f15ff5e24da8a342b005ff8685638ce76bfca33d1be2167c2f8b42775d91e69788ba31f6039fc0fa7c5d3a127c68b6d460f191404a97fb03e70bc42be346d801f999ff83d760c3e0f3889c2d73370acfd8213d1292b236aa55809e75f61785436295f8201edad1a7f49d26cedf857762920e7c9fdd70a40eea601bfdf7bce23386ad52a3a3959da8b446684ed5e45ce0f249504f66e4063b868b439d7ed2d5b8c2636f0e2c8ac9486d3701ff73c8e7f88465e74c1d788a53b66653e5010eb340c06406104dfd1c11f5f6d8f425eecf782905a22594646fb91cd0aa93479f7117b5b6cc22710778e515a0fbd272d697918d1e6da1cd5d899ec0a1285c40efcc7c7800023fd3cfe2d806009c9736f1f658c185a740a1eb244483aa3217557eb2f7f5625a49a5f3fd64c96ed9e0e140522550fd4fd0f51338bce541418d302157cd50e0c485e9b20c296bd397d28d22ed65263a9e1a288d481e69daf79c1dfc962c067bd2082ad42e00296ae7747623b571ed6a24a17c5614ed6ea428a26c326ad713f87512987bb704107701cc87a6e8dffe965281c5eab341b43789405f22c0fb62752e56649e9aca34f83a2721718c8486f03c596b3c3f4a18e35f3b378f235b88386fe2997a7514b3532454d4572145bef8e4068e1b7dbc82bb24647792fe3cc8b1a3dc1ff0d7fbc71e1d57a623f03496bc1a3ef9d0cbc59fffb890337ebcb7d5f37923debeb951d40804e864ae53e9ab96c26e9917064df57b9988db48f752047c87755e526f48ad8083abd41fed12e858611c4a1f43747a98ac2476cebed959c2e778af88a51f506a2c16f39f161d08daffbd6e827885c8d6be8c5045559a90e4cfa946a91c5b9ae0905f3cbbd4e27b6423f2f93de49a8c4b91046937d85fd266a2edca2fb2193fb855a9cf1f8e48be6bbe3c3d5f5e2d8f181ce107c9c43d6170179d56adf48a76aa5a5c3593cdd500e1c0ae4bf5aa46a54f713c80dbbc0079ce01ffc64c2e34985ae63a410681b125b8b08c3a0d2fd201d9f985797626e78c606b092ea1fecf6e1644a5f37a3b4613c085c8d9b0316f77fbb5487ce647110f5a66bb9342b7d27bba077f93dc7c8b8fe625793602506a0c688daf010b2ff5c0559bea965f2a07ee5f9457d4c6a1fb5114041954462737f685488dff3ec9bff4da502a10bf67b1f833452bd1035ea0c0decdba0f7bab00c4d0b167c03a859695fa6fd243dd13bbbeb2e7636ea55f363815ad5befbf5ffdfed36523569ad7504ab6c66269c8f3faf25bd7511be8743ce62a7ae590e1d3839c166ab7913c2a25e16c6a7b8ea3631363bee8ad489b07a1f230abdfe95a5b237d0a23e8bc7652e7c1296b4a790fcb65fb070ea2d34610cb4bba1188120d6090fc0de8dd05350e0549f3a93867b3c9ca7401498f5526d88e7be055c3f4e014d5856458e8136eee97cdb11ef3bdab950c30ce833e9b0005ed82ff5662845744f79c9a5dfb52a6016d09570aba91f4b4745bbed923cf9e0ba6426446fd8c91a6e39d8c60c8ce0c73fb1e31e1a65870f266fc2f4f59fa15fe06cfe32fb4ee17790ffb3e8d1a00b61cec35a5223dd63a4179787548b43a000458ceb6df70a7e8721bf32465666a91f21072e28efa4f0a654aff82024ac45e38d0da408db3f71109ba36e2d5c2fe19e7bd4cb3e2a46705d19e6f1b09edccb074c3ddf24d7c65d81fab11ba0f8237ec3cbeca4a49a4790a7ee3febc4e136c3bca6e54158b04e51e720f86bbea89ffada5ae80238f6e6699ab3fd1d3d633050ec3a9e3b0171262fbcaa0772ba8d6cb83d31e21b36e9207e0050520beade1f31eeea085fef7dc51ba97286ad42bd51f986aeff055904e2a1aae31f0211d47e46919d56840b6ee15b9f4ad548bb281f8e9e46b1de3480e32a489775fbf8446bdf9b1ad5662d33d73b830597f6285d3f1dcbbdf0c257be6eda078557886521f13f00deda0731fa770eb71c153e6b8129617da8f311db73a0832b4125b21c7c7ae2e8c701f7ace3e9878cfdab3bb6c8d0fb3101a9d45792f503c23248f11c0dfd45cc49be87dabc9c952c85ef57886be4c82bea002e8ab866ec7393528577fb485d11c65092d8161e22eafb2e0f9d3380f68b17c003f1117cb681edb6423708cac35c0a5b6e847890d0e706af9d71d1ee31894c31fba658b82f7ec431e2a2046fd8bb46748fbd40666732b3ed746f100d934810bfe7b2854a833bf4bc4959b40fcbbca67fc9503628df9bc212d43917f28c3dc1a21d76373ef9338c9ed0e81c0f920741e15ebf4c34de0e8ccbb3499f230d72a42bc2c926b768292ac85370edeee51730d13757963c3c1e60c54c958a356d8524122ce6049d7ff68b55f6a96743a7a732d13e20f5712b3cde378d560107b8a560ea040fe47bb28e682a06ca324d0237cf25158fa9f4527341b3877bc84c88372f6fcee49bade277b4b7a40efc10cbe7a46984b36f3b7065c5c47cbb84873155c70ec9f3b68d4902d76967870475e478dd279860a07c3a1b18546fd5caeb5f3d11620287346fee3acf8246841fbb42080831547ee88b095472c7c146388a6abf8be332bf43b586b1e73c64945bf15d2d8006277d3d23563030b3ce98c2aee5019d7e455327fd67f8924e540debb8d5cad52fc5236d89aed07c56406e2808089cd46ba7738074f669531af3caf21f7b90ec28edc84ef45f3831f613161a0368369e9c7ff1001b85aa13739ed4981dcd3a4fcf4c0af9daddfec1fe96aa349c798abcadeb750261a62913b5203345785ac3d4adb5b1c4b8e3a60d7bba435934ea476e733726d9f3a442f005ad30740d39532fe5ac370b3fd2747475eedca58222bb54cb300da81374788b21bccec11f6b24b06f7ab3155e3a69cc9d1f35e19a26c4eab2772935d0527ceb7e06cb5ea407868a3af342b9f2bb2730c2fa8e04e7d2121dd8096a349df48b9612c6c9de62221f1dab62451da7f45eb9b5c437da31ef3adf31af16126c7c2080eada464094b10681d909564735aa1f1519739e5e7aa065248918e0b969234a2751c79bdfd7c0086e1a15328fdb1ef8689903dac7cf07019e8df5e50340cc9137204a8d5c1a9d3fe914e9da0751e35a661aa6134a1fea2b877a985833b56998a4261e80c90e00acb9ce1c023e9e48b615e88677abd89aeaf9cc858375ee1099c088ca00bc0adec76792e650b423b696a48caf182d7c02beb7b53f23076211be6ef5b498a69b0df65e168e08dfccfc11fdabf67c0aad9e8ad6297ee3556dc40cf2038cea76db7732992b88f73c917873e11656b561eb20a8eb5501cc8a59469c6b947a20f3e7fc4cb5c43b12060384219ca4222e6cfa73c46d1eb86585133693708c46d85a2a27ab9f7e31590e582cb6715da9d5c01fea99ecfedfe293e667242912cf38292abf68abc82e4bcf249c3d15b7487d537e779e5f90e3aaf5ebb314007f256078c5b94e8ef6cdcddc79d2cea5732205bc8a1ea5463937d38eaabddad497678e82b8cc0605d22aace20d64d6a6143169af7a03df7b923fd95892abe158189e230459c4d54e6f20739b27cdb7ba10c9dc2c14ed04d789937023d5f3008fbaefa3d9ba6d1561ef7e6ce982834a4c97d6d4d4c87a83f83133395b9f03f31de8d351028b077f017abdc0b0a36512da595be5990fead0ffe4b2abbcb6ef242b47f794d1cd46a26913f00fb3f7e1b78e8e7975a9eb550c22383750026813d43af01704531d0a4c8411808ac4191377305010639dc2a9c056d6218ea7b51b2240d162fc0a803dc4700134d8e7014e00a496be2188da0fb152eb0133230818a2bad270e000af21e05899687ec6b03e07caa4c200eeddc1c6f4e77875c0098503035bc251ff71d5160546b42e4d21ce6df1ba4d12e916d94ce9d99ea53a865bda2228e5ebe5c40e74408373b1c79e86265de32f1fc1aefaf747b9ff63eeb4b551b3e21489d1c60aa6bf18352fc1dc0327f7da835d08fe7ddd8228c4944b3243616142c0f972bd70ea168c754ccdabaddb425dbbe50deb282fd4b854b88514b802d24e4d224379fc63dfc7d899e0f290ba38d38b082b1ede430fdf58dc2fa771579766c65dd581a94940284570439f2324ea381a8b000a8f7b374a534a3a1fec62ab4d9b5f1064fb19ccc6426a97339921dc3c8fdebba073decca53f506ec9f9e3c4fe19026ef94728f00d093884a3beb02153d538ac1ed27e80816dfa2f9dc5e9693666c4b6b83a9ddf6b80684aacd6d60c26be7dcac75005c49c939a0d4b8a3dc9e441ee53ed4e18550deff2cf3fe884743f1baec313936bfffc77aa9ae5bcbe056e682b0484164f3dd30efa84316f2baaa5bf748bce52b35c6e457bbe664cc01d4a26c9f0f7a78c144b4d4a18786195902877acd12e240a744412cf00b6ee2292468d88667d602cd7a72bf3065daa1feab1e0bc6567b23823c041b6edc857d81848cdf398095f38d9832ead3d450405d3def7c7b35953e8f3b40aff1fa16b7ed006a4a9cf0c7fc8029668c0d843f60439b94683b559628342d1a22d6f0e4944175072bbc179ee50d7c0f96662387743231888964e799ace34998f48e307bfcd3ffdb8e8898b6dd614f4f600a1ed6d3e06167913b97bbfdc1794a0990af02c5ffe81669201950daecf155d4234182034ce0a7dc2b8e93728a4a4a703d2414083c3e2faf4a49537a19ceebcd3a45a781dda391dc900619ab752e8dcda7ceec1d1a9fc8a2a93180458b21893c431a2c6339ab8da9ff736eaf26d8ddef39c4c9f6ca0b5b878cba46c7a7edaec044280f8bbfef97a6e2402918eaee80a9b484660b0521b99f8dcb7cc371c1e1c88e3fc685b77426e297a4ba7e91551c4f8f1cc16cfba0916266a5889ecfca8852cc073a4c11e1c799574882e8d10422e5bb2f0de3a796c330085f95cb3f2fbf12150ee92de443f81dbff335927ad7e13c7dad44bbe12661aab9ffa659b85ee5757889d6394e407359f650a91ea6c5d5185fbad90d7a5a568ce03710671bf0f2cf292442df06b6d5c0ee3ad1d3fa44957d91d408e2496fda5b67657042cb04e1a5c07bb803dfb6763ccd40fdbc6643b4e90da572c365296ed4c71ec1816365e11294401ecc74d4caf7bc573e2b3268cca46389f5d1af71dbdd7defeca8238aacfceb31f6c92dca79b7298e8194390e81bd8d973392ea3bf8d73610e71b884b3e8dd72feb19bc1d0171f4def9de9c214f096aea2629187212d748849fa4cafd17ea0cb5359bb3e3d1509192f1ee8c382de5e8e5121480884f6682430ba22c7cdc18705d9af3eb087cbde8a1af8b83b462627d4872af0bbf6505ebce7630a2a2220cabda5d76682e9a7991d7465423ef094f33e39d9f183cc40ab049d73bcfe8b46ceec41fc0066aac454d8d4455308e95de4daf7e9aa3f4923037b1ba51351293e47c38612bd5bf8f280401e44a8b662ca03a202e2dc2bc6600f3f2588ffad8df437a10b4e3d56ddbc764d99b75f49d9e682ec0feb6f13398dfdf034d15b532b7a7161d842294ef0a7c0790653a6ec783ecee727201bca6ef97639b3429dcd9030bfa0f8a54100e1fd221a560837dec2aa23e4646c5ceb86739e60e9c01259855e55112b59bf764a01f4a5bb06d9d60f7dd0128201ed6db848307c5d23102ee08ff117c3ae1174af626a74273d6815ef8d4b611d4d7957f9da1f2f5c3434e14c96fbe184d4ac69a7d8ef3107658b91ea8076cb9d40524ea973d74c12f74aeab2620b1e45b22a735d623f70cd784180d9d692c4b60a9be681b731394c27f8b8a7e692f8e9a903f45cfcc49008c2cb2f85cab3803a94e6d52959789b7c8dd8158d96a4bd68a2fb08858e99c2d7326bd645acc8c5b26f08fffafca036433b3cb058bccc0e6041b47d575b69b52ac1158f906f6b66a74283c3c2081006374a0d834d20834eab6a9e140bdc192a0df8e23122781694e63e982bd47d111b31d9b23be4eded1bbe84b4d33555127662f59361d8d5a6415e546925853543b9d9b6a8a9ca15758ae7341d458f0778755d4ba1ccdbf22a52f0080b7e7c5553c3326da2fd6b15642ed914c48749dbbb8d62e3fd2c8a0218cce6db719ccc528fc0c4a622198a2325cda43522c7f12ea2d62befd33f18ef13114f3cabd61f11fa2e57a0942b33c4af367dcf7c8177dc1641d1d55515bd5cb65beaa97a698c4d69b76c3a677d4d130d1fe437815cba011b4588f64ace2eb640c4c520049ceedb49f6998373762066ea9775e6bb5dda501e9c964a171505116cb2e686675df5d195b035b81f63382e69a5b666a3f3e96327c6d2394c55a6a2fffd543093030bb16a4eb8c7957f65453ce640cd086cb4409685483e15b8cc5673e6434f9aee859405f118d6658b3756736da7795cb5460a76b47334b378c09e46afb96be8aa2de6dab3e7f7e129f29044c84e3e65ed477422100488b9a18e875a79ae1cd01531f17f0011f957443823cca709478da459bd67d010de5d843e0ed88c86cd7aaca82bbf7080bb3bf1e61df5664ee572c561fbba8a0819d390a3d5303fced1bc1f6e688ed21376019816827a27a3baa365af0a5d098ebbb5ce1bfaf80ad620b66944225124cea3a152d58e7f080777995e3dac863335c84c7bf62213e70ae15ea4852a50aef035482f5a534b1ff77b6cb249ad2cbd0113303059d7bcbe42728249ccf937df8892b4df7280b3182313cea81999c9c234835bf9c9b3b55f6214bd5a6ae9d70342f84694bcbe88ff01d0ed6b9b4cf40b559ba323639bd3ef63bcdc6b6d09bc1e16beb147a8ce7e777932728d1363b561e3729b464228f342407304232f044ff5ab51b35cb6109cc1e9ab527756004dcd5ac05107a59ccfbfeaa5e801d768a328d1afa6adb30c8ac1ef5d5452f5682819093fe452bbcdb440f130e0a5156e1cad1a39af86e2332af05174264bd84c9a596273d8fc47a691dc29201a307ad37b7f36cd51a939c80440fb93d9bb6cc24894d617aeb0c71495be19da6684b6435742a580f08caf35cb47e5e10884128e9ba5cb747b90711d203c64f0f08b5eddf3d21aacfd838102c5e1d4683200d0a2a14c5f1b981b1859eabde3467fd7fd386020c10dc22cee8c33c7d580aca8c8c7fdb38a324321c8c7bf96580722a1da796c95b93f54762fc55bbbf20cc64b9746b12d3c4af7a45edf6265fe3251f87a2503bad4bb1a1fac5d81f11fe0235be5b462950b0ff721be8d43425198a0cff8573bb407ace917af6862467c53aaf667239e15812f7f883f1e21258f11ded86c15f9f7fc7e918f0d8d69b83f47294aa87951852805aa80bd51069bfbc2452d71bf5c1433400e928eb7a27636e2fd57caf8c167c93538300cf090783d21792bbc97a6cfab8d7eca41df7889f022f183a448d749428aed1af6af7d98d153c12a7e62c738fda59a21df4b66421a88eebda222df802c2fe6c4dfec3ca05305143baa209b15a82c40abd1042c518150a54d8aa4363e2a9a46389ae541f2ef7ae418404bbf11aa21a42c568ecdd06eef8483fafacd3c84e4199eb3736fe863c2fc0cf8c14bddd7f506964e22147024e962abc037e6f650ce333432eb6031f921bc52b52675131497f2aa85d84fa68a67b587b1b24f95d8f8fa1704b22e8e92bfc35cf85b6cbb501c78273454e84c7c49b9e1e2ce6088db90b34a1f5dce354f5060bffb35122a2c47e21fcf50e89dbc41e645547b1f972b82a0fbc69a3bc05c71dc969a23aa780dd62922c8ebf8a95d3f16911af7cc8a718c394fd318a430ccbbb2ad2951f63e3eac5ed4ec02ff41ba60778b58ecf5ecc33b2b356127f3b91ef79f82cc216a15da1776ffe891fc2d405fef450507b775150b5a65ffeac1a410f622c18dddae5dad64e5f7d10e1986f72dbcf21ef155241f04e3c42a3f855882fed8a2d4f2b846049f665fa56416abeb4cbd20806fac621cd689374e8588bbcee21acc7eb2ff8e354948a73dd95c39fb0e9442b6140a1ca2113f6186cd0e1c974adee7846b0da75cf489837f46340682c21120735f94b86acd29127849193fdabcdd0f9f1404c108506123589fe823f710f7fe44bbc8fb519b9fb6b924b5234f5f7b4f5650637e215e3625b8ec87d13bb610fe3907cfd952fde08ae063f2800d6c591cd0127d48608ef29bfd83f55773cd3568e8d710dd3d7690d11aca6728656762d6d1840592785407bccc045e09825db4661377dac6a6a99bbc36843f229b47514ea17e415881e94c36158940a48cc7b545ead48b7b2c7081c57030b4c6b4ce2885cb1135da3e1b1d5d6d8c36b7d3832f66bf9c47cccbc1c88c455fc390027dd474492654e63d28d4885aca27c0fd02186414ff50eb4009825e11c8edae67a3897a16b5e3e4352fd73fe08a71d9746ef1f1183f4c5f9bc9e166675aad10d9a462792523088dbac54a09b8841ce903386ae5d874cb6d1d130a7c17242936e2a696252a7e299e55eb7511eaaab805d67c8154d636242468703c2c59b446cb271f815c70844891ecf3d6866a7904c5b4b4cc7edba01ddb205e33c17e38a0d585eebbe911e180f53ffd11fe75b1aad52cff56f68d7daf98d2302bd20cbeb322178c6e26bbf132d3883f0e933452e9ac978397f07cd631d833a6240ea72af8b4dfc666ff4510153a94a1c267c0ba18dc057ac3d9ba5862329cc496cc7a7758fe915dfe1540874d6de1a2e84d418efeca640ff7bff64402d13f7d6e846f93cc6fda601feaf18719ba3922e4e8768077b5186cc00aa1c6623d8c02c3834fc365cf9e0f4e9b45930dc1f53ce0034af6900f7d78335f04070276e4bbcc09f6198beca80ed1c1083e2a008017ef7d3bc08e96a3dd2d8152f9915210a1e63b9a5880bb2a892f732972513e32e0d708340fb8130e2cf98175ea2a35aece716dd0e1492665cacf84ff79284c0816616f1481f3e1ca1fe8ff4100bb2042f0578d4d0095c7bfcc95b94a48f9b7d6acb56064bab50827e74f5f8b266c371e62500f65487154d93fa5c6ff87b524a7fa35a7b6b97b548ce3a4ece78513d394c3c1161d593497a0dfde349175e9d7b1146d866161a3b03f137428286d73af5c95f198ac0fa7ca83e2106e1fe9c41e8bfa83d0500f6bdbfe425a4bf1d1af375a4889889c34f5cfa4bdb7035bfea0eaccdb03561f9dc559acaca4484893eb0cda9f05207f79f3ff9af280a4567b1ffc61269ec1d7eb2cae39b1546aa43b7111807d8390b2aaf028a7a4bf64f3948737ddb40c0726020133c4b77344cb9d9a8bd6b0d6913fddbed1df1011d26f8a82680af92cd28e3579d5920b0368d3a6a97d171b706afc1314279bb52ab0deb8737805589ca3849bb5491fa7a7b831cb7ce5bce07471c122173181d3b1ca6f5f92b64f65b403ee16fc76cbd819b1c95fe906aec0708fcb19b10b90b353877a5ff10af59852c84dbeb60ce2386a026ccbf31fedb4c9bf4bd9f2242bd4e977e21d4237b2167fda1b7c46c7b98349188d49294b99fb7ca6b4674588c862252a157954cee5c9137a1b05a5747904b66da6fbc698f9a46796a1a05f84b1fb29afe49c9c8fe6348247c1e9cfaebac5820f0e3adf230b9740bcba6e48e00ec89f8e6de42d62503485d3413d2e20675194e32ed6285d0c3b5eaf6640359ff9cf8c20f5c8f5869aeb8be276f1eeea2676c93a3645f5a6608fed4135d4776d56841d2f49de1b7344d235b60d05dca6229f94e3c56032b7c5ed01243a50041580f2398342e14576b74b182af1611cdff568eff2a6c3c0db4672870b583253b8b4799aed016a613870e40bbc4019b854069de608806a08a4930abf175e9630e9bc190f3912ea3fc431fe32cf048979e36da8df7386e78fe22b3828881de7bbf855b19397e0d977448cde99d49ad659cef0f7badbfadd04f1f3d29c1358662618b87a7a67e9fba15e9fde4fa58ad6c99a4e8e2a240b26c39dcc709b40445eeec01252c99595fe075df5affbbf0efd0aa31866e31ad2ade95f1cb51060540a78ce1b195e20cbeaa8565e461e8903f73819cc0dea923c3e646d0ad7c7e1ecb9c4d4db91700ae942f5706f469fb63d6ee8b4fd2911448257c6597673ae4ffe3ef23cbc5b7de7a6dd8f467d2545ec78409de0f29a4d0d1088e777f609b5cce5c75d8027012c445599a5be95cd9bbbf5dcb682fa3fdc962de848caa6f36a053e2ac7335b78f50bcd2d2ee1810479939a4900b71517c9040753995d7a8b1e9e3c4db8e372e4190cc68fca80366ac5fc6066dd607f3f7119f906e0e91eec09c4b043276a31a3ee642b368966219083590b04aa611a9c051298f9c3fb43b41d70ed39aacbbeee0be87a08ffb0390bd2f6c9ce4e0970c589768247f54b65ed262a790bd272a4eb785b99d657ace85ce8131c3812eed90b06adc5fb52e1f8b157a95c86fdd61f0a5306d9f863f4222e84430e5d24fb2faac2d8a342d94454e4c36881d1227eb650ea011b27d1fdfb6f8eae6831d2e2cc13d4ffc290335e110c22e1f4fc67c1ef632ab72af01433661a722245b0329517d01b4e596a6bbb6e8903d5f18a71df220510e063929bed78ce1b19e342a9cabe236be398974b2bd74e166402cbdfe999d3827d89a7eda0c36ea080a6984ce9cde548cce74152e6d90bac98cf3c21d4cc461dc822e8dc40a83541edb738de7e7d8f4c362b1c8eee1d90dad1b5f56c37ecc972c89bd0d03949209ddf39f648a6f26ac9b4a94e1fe23ae5d991a8fd56d3f48df66bee1f21c87b5459ee22f4486b7d00836ca9b5dea346251b30a82471e6664287d80ab728301ee108198aeb17d1a151c492467aede4419351c6857ba79c2381d749a69c12e6689217131042a10d34f545cd91e1ef32b5daf576cdbe7b4c59816f9da687bebe11c0ef36eee7f2bbffd9b4b51a7f6e676a1195a9de9ad103285683feecd9564447a56065a94cad63082f1512d67010b0c615bbc8ec153f985a016aa9bce7742f14a253d66efbd0ee8462dd4fcc44a9d20c92dae1a67d6e602a5cdabdaa0f7621f69cbcc9161e5a318f6938f49daa7172b4a6440938ecfd6f2ae0c702a016f7831ac326321760b3db0082a7f1b3990866047abfb03d89ce5675579b789bfceb80542714b8ce54bd24f579fd35c26dab42be22bc7810fb733d5bd37c8f2da494f24fb94251d9670144602cc0afbb98e0b6e0fc988a984c77bac80bfdcabe0a9df8d42756dada9ca269f34be2d8f5da999058d50f04010d356adafd39e33bd0548f9ed22811f7967ec916c48ac1af66f0753f68953b51a7d221bc3251620a30bcfb3eeb0ee2d7d77c01ff24ecb13679f730b84eebe434093a13ca50e8fa06e0d582010a1a1c9d485085687a266bfbd7d2f9ff0e5e6a1e7d72fdc2eed13eaf25ba516f260cd437b688772180aecc360e239d73a92175896bdc31aa8f077e40efaf2119d68d1303f163573b76d45cc3ea51498c6e098b613ae83c70fe8974035228073fe92affd203c498be5a4b3258bdf04b8138fc6490420a6d9da5b314f488f40300a02451de404f467c8263e4d6b693f40accf260939109edf7c059e07bf629799db568ba576d2d16b66aa94c1cd6a3ccb094bca6b1f87d9a82e7265b2e54fdb290b1f6ec739b21d49ee566af8c5b5a728a119ece37bd07792196c7eff77278202f99fa71501e2c805fe7a923b86bb41b5bf0aa583d03c39f2d2353486c91dac41fbc22e236af9c084d5752f8476240032af6111b8bee25c42db7f6c3e27d09c9dc48447d0a97f7836ee83278674e181e310c64276edf1ff4f49503f211c1179152a9380778d018508a1ad2a779473243d4a9dd5b5979de5b33acc96e31a8be2903e4ab5a5fd58d1b1d0d7f3b166e8626760c97ec35a6959a7b289e2f3b06ff7d1ff365d4ff7c4595239473d7a8ab67890612b951d79d85f25ea8f50512fa99704305035a0292ac8ab12f15862bf2941ff811121e92bd812cf8e2219665cb9ccc46b52a08e7216b940b609101b8b0c15455a76a5b64feb91f452edc12f7fed2faabecb401c1c3acacd5e5130ce01f76d98385ddec8d3dcb1da3b1016809f92c75c77c1f551fb3fe9e79a4ba0298b6820604a245daf57a6cbcfdc31050fa2fb70961a682c3b5417aca6f69c9b1e73a74f362d8a121e1ea64dc0c6f87733748aea978ef1a679f843a842f773f9a3cfb8af100d5c801b2bdc67a24322e02e75e704febe06227801e6e12002d8d7210ae5c0c6bc077413716d63130505b0141ec9f60b2d79e79375c14e51b758679894bb06afaa8a7320cb83ab4e357e66288f9529eb12a9cfc6b2e2b4614af031d6de552b8839229e299058ce2cd15fe51d2cab63aa83597289a976b1484aa1a0dbd53344ecc6837ed0f45e3685fb3ce8ab04e9eef85a5d583260dc64b426ad963724988476a73a3937bd7ff91bd14440fd56195d4e51c1a0efa438767ad6d039a5838e463ac4fb2ae53d39a2999984c93a61b3f517941f78886cca1888e7059e4537d4e21a7abda26d91a32be6e4cf5dd490657f4b9c8642bd7bee14dc85e51b7ec8503277a2cc2fe9124996aa63834007d260eca7462aa987b470d28efa724f01f8da271c1248fa80ec3f33ec8686d403acf91fef3d3a5b7a72e60defa7c686d92dcfa1111548704fe48260bc0d157ed2ad909bf05186b77a659cc70395746570c8718eebe171cf55a447e29480af036470066d7cdef08ecf3fa1e466656ed00a1b822039e8062ba87efd00af33f9055e47c63692aeaee1dd4141710fd9dddb6569c5195392e9b42ba9651b7e8f99e69989c88400d087d023cf1d68ca207b4d8881fd0e778649d4576ec1b7b26ba4ebdde3584a7fff203c1f81edeefcb8743318da327058f0d4bc02dfd96aad98601c193ec2f59a3a2313bf0eecfe84b424f37a79e490e3adec848bcf973e26b1b8ea31089c7f0e720b932213091ad89fe827c18ad5a53e56fd444f8337d32a1ac94b8c0ff3ac51ad7eb9c8999d54c2ed1a021f65cd9f57f3fed5b57b1c7ab5898f253eecaea59e340c79dc7df7b07caa53989b5864483925cd1aa3336260f5c11c617352e86ec454012be39ec9c3a7116e802d40a16f9a80f84fa970755ecd6b417630ccdbd9867a1bebea7c616f6b7da40ab6548f8c8399dcd9f8c8fa00142052adcc403bf22e091802ccc155f8c49345a2859c114ada2cc97cf457d2adeb8222cd1771c9138102411a38443c7976d19b20374997f78e75cf53ba1006aac9d469ccb4954bf303667ee96fa917e6270cb84e9698c5b8f239d37fa9f11488c42d303532ee1ee275cd80d51721fe1f55fd2d1eabbf1ad49cd3fa0962c80b67955a40f0ceae90dd8f1e3e5a120cd4384fdcce34cf8b2127364c43bffa87e50fc20c50d84b672f56b122c312d03c2a89ddc980ea55abe1ef602bbe676b30d1fcc9deb78be7f7d6dfb34eb39c3a6c06e783c7b190b86c3bd131134a137ae091a1504afddca7127086514eaaee6577dfd04483f4d29a06ee45a4c38d20d46fa9cffa7e5d4f37cb43095d9d866d5a3c088a433a60df63d0bdf499c36442ca7a0f2fc1c2d0b4228fba6810c7817a53107c7c0bbfc57db50dee36765327dde5ac1b64952d5ea48745a7079011791f89d5601c08f440460d6e9932679f5144674e7ba641731a4060abe7b45c50a270fb1b71158584d03f8623a333c18a0a02a289c60f837d00095c7facc86de8d28951fbb132099b0c3946b73a92398001fc1903135103e2f57f2a69a757f9e8fb79386964268b337ec63ce5b70a7e44567e7e825f62b3a0ded29847a32a60b720b1f174a97c05e51c6c12574c397cf70948cc604c80a896dfbc83ee994424ffe404cf671bf7007a1cea6f7abddfb2f48d0e459c12a08ef6814f12bbd5c747bfa3b44464c2c1bc1c92d8d882126e2009964aa8b159d818749d46a707678299d89a5b3175e544870a147bf6de20cd565e9d4183465af6c154bb4263877b85bf5840426c7b370007478551ca4dd8eeb641774e73314ea7a931156e13f65ca9dee532df5d9eb24fca38221b3a4c626a1d4069d6bc8950e801695e38868c3bf2a485d81468bcaf639593d2abebdebeb512c90b63171b9c11938177ea45ba6903c456a5800cf05273ebe8916d21c06ce613f7dd924134f9fa57bae132266bdd3c8a4a22c32e3a99552ca6fa77715f602d83a24a2f286fbaa31bb37c39dc9cafa130d9cf2c1718050190c7f8b53d964a212c72b0a3412b63c277b58a8ca21fd3a1a12f20f7d3545cf5b770564b718380dce90665d694eb5f8ea164a8bbeeea511fef58794629b0ab42cb68e6db7f94d7d62b37586f80285fe9ca61ef114fc63b1f1223c82d502d46a8696782ed2e6bf334ecbb6af2e771e40a8227881fcd5d7b06793de548b8d8e36857a9eb152ed7dd3af30db95ecfdb30a80e01cf2a9ad707bc2bd939870e13613e2662a85ec25a3d2b9b1a5a9d1a69e27ca0bdcdac11ac8af70a6d1004d0099519a4a9c0030447167166d60fcbb5b154929583996514054c9218d24f5f098b984e661fe33b8fcb12f40a4477410b56b29e40e67114a6fd7e6424513f44f8af89e2bfdcf0ee71f3b01ba248f48b0d5ed55f328b4ae6b828f3817088ead29b115bc8e798f18487b556a5147d7fe50024806089e22c3c30fa8e564a5f0c4e4be7da50530ada02bb61d88ab15d7465938ec01007f6ff9604a93374b60612d2a78fdba38adf058316ab8da951955fe124e4a102b27ef5535ee287e7979869143ba5c6e9c615cba3979fe1affbbe170b8176ab14b8402b5cd9f41326f30bde93aa649542ebb7a6ee00efa69ad398bc8f181465c64ccfc79926c2cc402e38a527f9dc2d9ca2dc9102aa30db75aed84142e31cc3914d3afb6248cb16336832474fa3717f288a01852bc7c38899edff608b78ac4916822e0fdba4d3c3541742b82474e30ab8f4f9f6f73926f870231855e8223accc21e963a94bfa837de17f4a2b0fcdf599c5b0b05f85dbe4e8cfdba90949adebccbba0cfd68547a5ccb4168a79f889ece9a9e9b93c4ab40f5ce354e8e58cc74806d9ffbe107eb14fa3757b5b98baf6da8089af530da22925a633d8e08d3656fda027ac4b370d41470454076cf449ec8855dadad39da3602d06e56e75816a77c2d1b80f3d8d3967812959b386b79dfb1628d3632f2135e14bfd519531a6d04ee293fe3a782154937019518a84049ec8bf5e25bb2328dac941102d36445b84de83766ba26c969d56444b17b65b53f07ea1ef82f171d8f197ac2a4f77d374438974a516b2db402ef53abd9a103e4994d53e2a05b6e2b23b006bf3582f2e2b2ea4a9800e709b4dd275c80480ce7f63d8dabf2301d5752f513dff6104c2fad95fe6a41566511a8a35fc04f92d8c2bd7d13e95c1fec1b2693a672623e8526e2d810cbc555d697c427e33096a6d87e39af0da3628c26b99c56aafe65eef50445b93f4c058fe84b8f1703c357bd0ec93f1564aa1a47314dbfe19b211fddf7ea0dde3d98c4035a66638101acbf29fca3750285590bde51ef06e0d24c46cc2c3042d2b26fd45349172bf21c29966fae54417cd24720e12aab59f8ac5a31b5c3ba0b7d52ec16e55c807edd8aba339b74b3cfbb0a4f1c2c1d112b3d06e8e5c0ff4fca9f8e8abedf3d87dd87e8ae803db156dcc06262bd31a071b09bf92d5b3a454e2fc23f46d1642d1464db5a2a4a0b9c9321f4bf334523a5fb071a47e8b986a266b902ff519d529f612d75762d546755443d38005e94d38f0379d13300feab78a8751b1df7bc4a9b9dda66ae277f5de3cc00ff3f6d39f231353197cbff3c46366ff7849a7ef59435b97f3f43e5b65a6e1c33b6fc9babf891e23287aa5531bcf7b889a3d6a4257521a73d430c905f8de613b3a0bd62bc93a476e5d313e00a472170bb6829363575eca4db38abf32f5b7ddf13f0fc4b9263656873274831067e7d7f7c331acad4c972b14429b4c747fa4bf3bfac72625649666a9262ba6befe4f63dca1377944af61bbd52449a5dee8c042535252e2d1aff0103848b61554bf88be954b804607ee99e33cb97988c9a244353897b951f68e6019c2727064c11a8d668bde4a71733f481e8c7f5ae673331c9ae77ccf46292b03e0e07fde87681282d45c4cd28a478e6ee1f5e138005d535f448420801066508e49f473080616e77f3dda97e89a0c625e97e71fe19fab32e3b5faf6514147033f9489bfcc63a26fc3c01cf60f924c889330dad6a89829abcabdd79b8d2c4b11ac6f2502eef6383f30e5b704fb9b45a2aa09827d8e619c11f5c63c508ffc7c3cb3f44872dc9df8c933b39990faf378a88f6f4bc38754d81f12fff2b0f67094a19abb43581e365828c518362f122c49e456457a1fb4975db8639a38fb5a58d060a028aed819c33a6cc3d91b5cb01eef0b6a57bfa52262e3406af55038e8e6fd26c978821de792570ebd021215f73200e5cbd812ca6dbd8aa139284a3ca662004f158e47b1ce27423e502effa9e1fe0afc752f5f999fc8046dbe6654930d2c739256e9ba7d5e7f2dcbdc1ebe63728e0de6c55c0a1aa9f97078afe8ad726d232d087abfb9de73c694547d82aa61124b6f1d07dd5ff494455d0b38f01c0528af1e1de0ca665fd9f75083ecc6a910881cf28969aed0221696d809c96b7ad59e4fb3897f39e8e3f31f4b2f08e05af7b6b3b6222af18374ba366cdf80609a0f42f9c449b24c6f2b0aab2b53bf4a2fae3e13fdbb5d46612b7bdadb701f9776ba2a92bf8bd6e6a65ed456cd4a1127c707b885f3e23d722c6f5d21b7ae81a82c534ac7b80bd4f1e40ee43b13bfdcc2a50398dc59e5ec4a3e7d3d6666be00d6b53482ea5f0f2075cd7ff74326b136729d7a54c0ae61f9fd6ccc3101f7cf8a4c9d831e223de4e528d31e2145c0f7b9b819a4ed97cdc7fd9301943832b36daf6070dfd745b2cf23afcc2cb42bfb3f259b42d3909967d370a6e9f1be2cf58887453d5d1e24067eaf0d441e95a519f33ce7ec0b3050cb8ca0ae2434b9a725b4d9aa91498981bca9e89409744e257e9f58380892a4f8891550b2b3473a36c25d777c71b7d91e3bd2eb1779f08097eda86e9446065e5cab3988b89ad5671f2acdc03cdec52f0965a707aa660f6cb67c0591979618e586344214c9dc5f18af06bda31c07a5501ae2094a83851db1a71ba3edddb6de2b0f4546fc361e71a007b600a1a78ba8996902207d21d286f1424023c7f71e836b1c7d5a34e59e64e1fd91c84b6eab05bf7c07b68a4bab2db77d0071da34ae38ae8dfbd8d54bb047009f5d13f2f0dfc446ed084a3aa045fb94fa243ae6ff64ec4a200f29c4bdc7dbc7a69a195b95c607262e68f9e239f7e3077ce16adce1999086cc5b295d56341e333557cd80bfd0f48b7c2a4e4fe8d75b570e530ec944dce26c9c57d02c8e5c9b4a919775ed4d8e9351a7688a06dec84667e732faa700345d351387915871b113957720f9236556fbf571041e6f0ba793e71def8f4ef8234904f07f5bd706fb733f9d4016596eaa23b8cbf3911f6322360d84e1395658e34e3d4f5bf4159cde368836ac133815eb44839073f0edbb204cbf748adaeb7d88e4aacd9772f3e631c2ce7cb446389791d4578261c4a7b833fd81bde65e605cb9b622b9140b617d663ea6ba227c4631ee873a871c20b6a169e10868b7b43ef9e73ee31e78bb6886f6343c28eb9ebc3234739875d27becdf1ad73e237d55b4c77986d6236b6703e0355fa34b33007a93cc6ad95f2e624f59df74576c3c85e440b226e058a76e510f2678aad4fbdc651bf713cd6598e70812988a79e024fc6305b2ac33a1613b6c98c30753279128e2fc8ad8367fe6febb437d41ec69bcc4951d9b7af26c5a30ee013096472227ca31588e0e02f23d0351ae7ce759191cdc95467ce81895fa416dea4a12694a0696e49568e46b0b1bcacfc5a64bde73da7959fa050bf29242819132f3739f987665731eb8d4a1e9881e1c52cc21e8de9485418b2bc0d47e7c4c5a6ea7caee3b2ba4250d8a9aa1843f9019219334d3c9133370eabb4ee55ecab8d2ad21f00c1be6d66dd55524c21b612a085df616d7f86a96432cc940843296f07f67853b83549c04ad9457f8c70f42b4de119270bcebb4bf56028d8d484222954220128c0b42faed7d844e9297937b7a9ba5bbe219a63688b3a91eea2285a47edf9b6e96ff097750244ff9cc19502aeb5cf6286bbcf156944a7090c232fd8292c0633e8dc3000e1b224810faf0e6fb36b68a58c630cdff3a18bdde6ca0d13a883d25282f963092d9b5f313edd6f63b446fb7e0a122bff00eb9e740a81c4578d616218f8058c78b089ef7a820a68f9151cf66823d03c9ce87203672c3dad755d6298ef5ad76e3f8d023cfd26a718ac86c3e2d93aed2c082e6abe10c93ac999db9d5267ecb326a1dc3b576b57701c3f1354fed41d0d52dcb15864c1d4da2f2b40df65a3c964a697cf2480001ae5802c500a686aaaf434119b2b2deeac2587ee397235c81624c6ca9edf8ea41585c0835bd2bc9309531ecfbb70c31a5d6f221f366fd526b694b2b7379fff24dcd1f719daa433dbb87c30564bb05690ec58bdb8aadfe06070dcbbb7a55b58ecaa82483bfe27ee7ef47521fa670ae87fc1e7650ec7ce82e22a9de6c8359731ce3e2527649b6cc08a68765d5fc4eee62efbc0aef459fc96987108b25a22adea45820cfa3b5d43be949d10d73e2b99be4746da460e56ea6d5c846b25c0e994515313f9ec11eadeb642c89a2fd4af5a5a5ca775e988aae357b907f04b4de3f9ee788976e7d1b7986c2ff0611b2b25bd5cb1ea4357274d1c91e9be47ced538c9cd39f74fc325371e263dc730df827751a13166b54804d8545f5aeb85d6ca88de0b533d77ed7bdab79aaf205d5ab3da986587b0b1befa46fdaf5f4ce688c35ddfc408613e6cd84ff3a77581259e4ddfd560f5601bae420d53d16c20aa3c51892f0d5cf2e39d7501eda588447c589fc60e4e337387566df2c075ff1a12edd86227abb5f10a92e99f31a4e314f5dc735b683f70de3a92ace513712b4f28d17a439307ff91bb6fa989abe935e929951d8a8e20605c07809b564091851e1d880db107ff19d25b6bff62d90837d1e5464649549fb732d34a79666c1dd04c3696cb6926ebb97bedbeeb990be83f5522980f8c9f9a09835b5bc45ed5422bf808eb95e6d06e3af1189407025539f415355fde8f4826ecb29d4201c9531122f1f405a1d8f70d203e5cf6db5f431399d5886eac8c91ca3f1d4a3b26f7f09e4161030534f99c07b873ed9c215c5fb019eb682ec46ffc25920a498357ff0417a8fb6fb5fad9704315e3c4b03bdb6c922e68e959ff51366c4471789dbb9444a8f428033549e9dc00868a75fac5dc0b0f8e5fa1ed85b62584a9397efdaf5f4c35305e1e022bda8ccd38aea99d1e1e6b35446e23178d1add93f84fbe2114eb0bb3c3e228c246b246b967448fc6cbd3aa322a5587cf8142a46ace446461cd5c87f84df3d8ad03a802967aa2306022cfa9187078386f9f19fc60d5461085542368e8bb96f024ea895f20f6c5e5b8a640461070b3b32c6ba3aa8d03f140a59f7b314f16dd723c3326b82101a57f0d3afefcbe725404e0bfe687df232ef9f6eaff8cb4cfd66fb4994951900ec51bcd2e08557c892ec3c1f6f0d98879bfb66d78b69802db5a00d0b385dc3c04eecb68ba371ab4b12183c69782f5c906afd5cb9eb644d18c642e8dc9b33d339c3e765fcea66d618146ae7d14fb6eefda734a8e2d241680d4c27ea814677eab7430283b98a4ab04003db0a806802a4c29fa460e390559b4a428b5b9d832384322ef78ceb575e76ccf631753e2f880eae531b30320fe7c8294833ab7ec8baf0ed8e2d8861247e1d32a33b2f2b22d2bb6ad51a6517906f69fda6c0bd4d4f2da619b07a314bf0045f983119b5bc7f3fa10319bd0d791857d7887a09f36f18190742516b97813f0e3bf21e48da6a22d4b5ca5441a6f8ba9d2af89de8cb01dc613ad96a2a8211c1c6f33ae6bb36c98dbaad5adc7b3d36a15ccac7c4d00832ed3922269e8501443e2efcf853f500762847a86e0547b8aa4260161cb54824b4fba2c6d372cb903d2c3ffe4c4c5281ecac2407e8f18c2aaa3bd0c4e2f7441090529ecee0761ce451daac1e887d4ca2ba7398ee1d10d58544574d92f548597e65a43073d5af96d9e60557b881a1e263db5f22793c9e6c7ba0805c3c7e84380b63c57d31001906cb6eaa65475d1a2f4b05d509fe7100f9b81299b47f590c04f6acd3b762398cac8d537e6dcef14662c4fa9235efa9cead5626ad26d79bdf71df4fdfff3ccae9a438250e0db3e5ffc8888d83af18a9140e758d6884c9ea84899222e60a260d1b8b053bcf671d71052957c4777d705c1c30b91f7c01fc6e6830988b7b2c5a24034db3fc620ef07d3fa7d85531c978c033ef96ca3c91713573eb21e1e952930b5b7acafdd3afa6620a66f3deeabf9e02b35bfa5da75b1ac7095b7b96868779d48aeb76cab8b92c3e337d7a1091eb2db7c2bda2bef93581e2b53a116d9b8d3b7e4305743a3c2acc166806c23c679ef7c101b1b8774b15fd7c282386f22b112a7d73d56e05b13f1513b49be04129338adaa1f935dbb679455c3da38811039fa7026b0bc48f90e8dcb9af893052e1f823736fce97ae712aac583704452ea3383a8d8b3039d4f08100b90d837de7c7268873dfaac4f6ef4b7101b14fcd8cf67f3221ec84b616bb11ac1ecd4ca74b5564379dad77fc293c1b24e7c6f03cff4296f0c59a9bbe85c52afa114173ac394d9f8c08f7e97ea4f4de37acb364fe29c690c43d0521cdb3c5ec152d162f1ca23c8f4a87ca8bd5c63de6ab52ff2ef7d8f7b92e6dbe1e230b42f5caeaecb5059841dc8c683f099a96327279e334fbceecc2aeaf85b837763e90a871c6bcf2a6933e9d762e22a9ad371a15c6b3448bbe10d55ca55401d2f8aff162734ea285136f72b6389feb011adfa0aa5041999bfb014e9dd341ebf321fad7494a90f87563eea82c8766ef349006579e4c0e77d6d9fda458229cf8b9ca15ea8ba3201697669a1e533cfbb4703dedc8465a4009ef78862c503f98b47b09fa4b514df22b660fb0d9c70149d6cfe04c5c5e428f3168b4ff011161225ed0b6d9d447aa6f9a4d4e8419072535f49c6e4afa4155e94ff06444c324daea5ed7e340a14f984a1d9e7f305c8d66157ea8399b11401d21568123be414abe2041cae94a3c267f7b61f1c69f3d5420e2881823c9e36086d8ac81c803c78cdfcc77068b60c5be935f8b00c397c981a22460a28f6fc23aa094e98b241d5eac8de67b9ade3df86a1fee2f659aaee9077e45962394367497c9dead908c648cc8770194bf2ce03fe0bd0ef33f204353c8f77650126934229969c24aae4bb584c803c1e819e6e12605d0f4327398ff7ddd11a477d995f68d7e376eee88a38e06225a3d81aa938a77b7082acbbd947ccd5ce249d9d7984cddfe815b076c799704957f62ff0f48277d2f4e0acf0007f8ee09f008aa9fb558efe0f78fe44740d7c193e3f1309f08b412249e0adab207b832ab1a75c777a656fbafa9117f881598498800dadb679107ff68dd95cc4101cc29b812f37dc9331e387a9bc33486ed4df868fcbbb3b56220a571a248e10ffe519faea476e2803732b7ba7d1cc1e40670223ba0b6d12d0c015cb09042c9f13f091ee391684dc143ca0b4269d040ba0e21afea909da0c1c39c2dd3c70c701f45069cee2868a72ff59890a04e342c1b3139ebde39af9cf18858b5f37d3bf181ebbf80015a563cc6563e54c4323fc82cc377d6a524e9a0287f8297bc6aed5ca336cc9e6ca20c13fec7f3b45ce8cbd01031bc4e48c9bc015696f7a77941a9719917bb080601b86d67b2fe499298e9c16b67da512c8985650854e2582b74abc2e4d92ff40b981cbb0dbdf18dabd2936bccabf069f16a75370549e0efb9c883cacaa06e937d54aab039ff376e10919eb1f84d77d9979d35aa2dcee6683ed6543d1bbb10721a8766942fe8ad704e0ef7da1cfdd5e0a1007bedb57b8015e4e5b3cb4d0e605a71bac25109a2923d05c6b485d2519a38433ba4c31cae688b3f949d526f206b458c42ead1885eea2796180ef93d716403d3149725caabb093b4ae3cb4219c4ddd635bf7f9782999f7216ab0877554b006a7eac54b6dfa5e71dc83d64f070cce73c0786689e4784c5bdb3cbbbdef798d6e0e9256fd28812a4eab21319f7303e1eb32b1349318afcaccb965cf735ccf1dd58389bdeaf00cf38c1de386d08dd56a28bb66adf36cf61971da67c6d2ed01222f1d1219c0731faf9c0b1ec9e5e37dde418dcb2122b1fa53cc6485cfdfebb18515aead4b35c6530b324dd11853f8bef7f93fbfe4a43658695a860f6f49f2bf7501a66a0d269d3195f337823b0491fcb1d9f6ba4468f994941cb7d13eecdaacc9458871606bae540dd505500d0a3d2ef1b7bd3be9caab979fddefd4477a4af1c45df2f223d103ba9ca3f2f42ad22eda316c233c348ee6002610e5d23945aef1fe3b0c8da144689162d3a3213c04f9f69656ffc9ca71bf6839bc6b7cd782aed63d0635ded2ce3f0b68d15c29e2d3d7f7fbde1c2f688efd4f34783c7c4c0d53aab6e6e82b312ee5ff346ff5d616df8d169a845fbe2eaed03b542cd00dfa7e55c207804373b4cff80608949f66fdf34e9c30615d6420f80c97a1ce75874f87b6ccbe775623579b21291cdae0e6f59fbaa15f8929fd16b220de2de33e7c1cadab3b3665964e49c9335d2e73c34a65382e73581bbc67d95e712bceb8e0d0d95404d62eddc28b1b55c7edf01ce206f2e8cb534449d4e86042f0fa8988fa07e5c06276270780aece3428ab0d613e3fb7c3b16e1eb4f24a96818bea07bef50dfa9e9fba879bff708c793ffe712faba7060790eaee6035edcc7f9d52c527c5128da2faba6f6a78bf1cc002d5a482014ab30dab8c0aac9557dc1e2c11748368228b40472730aad54c0b2049b8a084bb827cf09c00ad3dd1b367bfb6e2ec4c29e5d920441a6d9759050d343567b91eaa3a9b915e35e1abfa3fd951b4baf9a889952ded00729ef664337fbfdd92fcf1bb48c612e7370f1f2bb80de9e59e850dfa81df8e7d5659b2544d9c1d66a958405db95647f2750ebed4fac194bca5f28fbe6e0c0af2c7e97791ccca2e0287042b0f9b472c86ad958021429e55ba73f869e4e55cb0743a867f2ee4557a1bc062a22b14ee55b81769a4dc2a3687b9b2b69392497d120f230f86803a96d9685322600824aa27c9e796d56e9c83393f7246e1c3a8c186bad911c671c6f7a33d3685afc6fafe8add7bf2a82c55c0293371f8c5f8c60e577a7e15f18f3ccfc016e8aee0d93dd88d82cf6620ccf7142565cbe899b36bc989d4527b128135e1fd9f39e4bf6b0eaf8e14ec753d07b345219c834281c2f506c39a6839ab9beaa6e56eb8f6d9bc1eae63597284bd61f9983cfdb1a4c49c3f8a6c1851b7f2212784c6847e81ee158f6f933ff9091ea1a3d9ea4205cd2a895780351c925f55b2365ba0f4af80b9baee2a5302b4244bec444cef803e86f16cc5d86c6c86c0ae85490d6dac4802448f82a66a0e6e6cfb455666e0b7abd7fcfc5686b5b525d087c43f1f3148b98d914442dac6498d4dcaf054e095de1cd89fd36725ea7aba1e97ea73862465955561cd5582c282fb9b8273ff12f658f6f38d221ab11e8bda72b3f2a9182197c3a27780a890a029b767c58a81ffdb4a8af91e08eb9e73398d0ae89579bcbffd12b6ac18e6a6219b2cd3ea2a3aeabf88274eec73deb776434c64cfa15b9fae7d80d0e639d8141a25721746a0370db333964cd0398c7543a0c6fee47077b301b1d924c6e58bd135a054448e748977d1daab3d037dcd54f2fc239405dfbe749afc215c0376f294e70c8f9b22dcbb97f055cd7e40516a4c33519ab48485c3af8439da438e3f9bb998704a8c6955124468439bc0c3733c1d1aac8cd4baa36561b2b6c4db2625b36c578275154a253e2b14a12d98f8444c6e2e32020cbc2de8e85875a2f2c39dea99046c0bf81dbfd050b7af1523476cf8a1bf3c051ff5deaffbe727a0db1841ebe7de1e2c9d15a93d134c317601e3cc0e72de47fec9fec7a0d0354d793f51eacf0b7abd312b19def5187736f12fc78ce0ff87b71e8c57141e49a3044404cba868d295f796bfa4bb36b41d369e9ef216b2b40d983d4ea1d8a89eafb0222ae98271f867e7cafc2f26ab6d642d8fd7cde2fe5526f48a071cb843248b3ba25b9fb748dee5af6ff0d2761246fb233dd2454dbe68ec9d18f046368c6de71f00bfef4ea782cb042d26c5a3d4eeb1184248cb8e1a7bdbbaabec16c578c541b2d2d52631a4092e845f93bd701cb2cf2ce5a9760908a999d9cad3ede89cdeab2c3fc99148c81f4d718c7708af85c0144a9afbc91317e008260e55f791cbfb3114d48183e344b0907d96837ef2e4f795e2726dd201d47d2131efce556c3d716ddd6578286e8c58ff6447895dd02b726b20fb9071733e3d1ff0f82777a426f7112ea9c6e01d8216dfcd1d71bced00885e7141aad75e6b1bd953df53bf4e6a49a880078d8ce800331626be365bdc6d1f0690c7596269b415a87d6fd317a17a1b7f8e0667e62c00e813b8da967678dec120021d3d77bbe4e5fd26faa573ac8bb660733d052a34b9e1aa28ec897fd88a94e993c6a18f432426f3ab019e73a8388b113812803d6cdb6df0cbf987d15e82c5dffcc7e78a922ddb4be2eb9c1ec66223efa6070e17bee63ca5ee57e7f409d20c773613dbde9730c9016a023f1f8ed49d0af3c001dae8dc23ba72db9e4a7855d5679ec67f8be5484a55177d7b2f7f999706e5be9228811554571a4da933edb210b685152b7dd33ca4548edd7a93dc8d573bd1f2061515f9eb628cd4b937584952a933590a9987d972fe0c6180400822b6fd9a94bf451a253dbd5be71369cde4ae9d758c78abb3efa59e9cda382e8cd4a3713efbcae0a6ccb1c352316fb90d2d0fbe1b0379ec167bd34d5ebbd839557c1cbca94fea7f583e61ed6814ed5f0bc0e899f5fcbca1e765d23ec74e207affb9a78cd5e0ae0f4331b7f7b8d80929da0a7972da9f744dfd36e939d61e869af22b4032b0a069202049cba8e318d548b8f459b2aa3334e119ce63cdf8d32ca8e37661fe11e38d55fa45b3848066665ec1a29af27ab2e366c519a0f69498b07ffdaca3f7c5ebbc46096447d8446bed39e4fd2d75a0a911fa190c654512031311830d4c51b796a12e996332d76b160f13e7c884d6c6b46a2c20420f37d74b94f42ab77e1ff067df4021dcdb07ccfd05da544dd201326825aae205c4caf24fd46fdd2d7f0b282892202e8c8ef3e8f2da147b02074747eaedba12f1ad0c69ffc0264b975c9b9364ec13c65c328eda4854c90f68e027a458cbe69697f918eebd239b427793a93de4e978f575974da0fb3c3010eba9ca14e78e595fd97f0d6edbead3bd334dd1bc03c2ed0ea2d3bce66ad371b8391bba8f5c08e8f1a3adee97857536e36aa83e17d6141e73913ff4a5d78ec75066ede04a9e5627cb9d258a7acddb02281c8cb47b8d67237e9d3cca880829c226e329325f47e53654552fc23b7e98c8cae29213761ebe0c89b0806e3402ad184d9d9fc2245c9a5ba1acf11979aaacb23bcc8bfa20540f95cbbcbc73e1636e71182df408cf45677c3beb5134bdeb3754af571c74057cc83e28e384ea40a855e999681b1040029c98ed1f9ecf7f78cba6a1c5753b568c5c3eb4a868fc4146bee2a51365ef393599f3f03ab8cfe18620da2dfd80365190fdb8d8e0615b73826d1ec026e56f3f804c35de105d08234891c6f113414d5c1c5ba8fac60fc6717a7609d61630734cc59b4e92f94669a5acff9dcd509ae64d74e17c47b7d150b9f2ee515e22f34f0e9c5539a8418fecd4f08260bcba983a8f52735a8fde7bba18c2e9f833d341cabfa92ea190f04dd85546960655ed973e0328593403ab6e464c41096071b2a510c522f18f9d2201565df42e9a5353de1e1379e357b8fbf26f4258fdbf4dabac0c19aebf321fdcb3f315dbf08c3426e1232a91c78f783c8bc39bd197608c783da227aed6798cc7254cb3479e0b5c394ae562fae210a33915b4c3c7eb7da3d9e7935ad71a620848974de16242831da9fb3ce258c1f5a059c64503a16f27d900ec247735facc0d897e50b21d0950655e1de3cf69c1c3bcd6de0e3a416ad8016b7df54e144206c9acd2de8ed77119fc6ec902aae4f7bed827344edfcbaa4b9b0335e83b83f5662ba0f086bc0290eb9c5e8884adcd8550eadb7576506de78a57b7cc525b83fa5084997e52c40d425768af77630904e6a6767a0aef8e19a1f189f4d7bd90e68658e71ceef80793fc039431959bd9b758bfe261d305e083d2915f85d114ccad2ddd376f86625e3e0ad7110b77a7d73a8c135ab9d79e55a765c4e01d946bc1f53c37555f3127cd5f23f59e4fc240ed443f1f64324e45860ab9f905f18db82fd867ce0da501ef52663d41119922414fdfabbb418338dc009bfefa03fa792b1230fa73c1d544793b727d92c517af97d94948b93b559602c63e4082939db0e407900324637b0bbcc025b9d72bf7772e977de7ec2373c2a8019be0bd237c17193e4591c99ae65166aded3be5a689219c3f9ec1d693b72ab3d3dac3db7b07c0e12fef982cb2d3b8699fd6504b4268849794d4ab658ff34308631bcab8f67fa385a2e45bdc0a0a163995a0b1565a2fb06683c72be2dd9bf7cbf63586c859011c009fd1d5853ccb0abca32b59cce2ead0d00fbdb42c1f3ca23f217a8ac7fc1c045586aa84ec0dc7b8ed40cbadcebab18a5908d39a97b7d52ff2f12daad58957faa1b8fe6cc247d517c7af2876e0e1baf56e9207882c9bbac6e8214774fbfec5e111dc211de5456f3337d584a88ccbcb23bf1bb3054af2280ce024e0558aba4bc88f347bea83b9ea4aab0420542a208e904fd6be3bb442c03e05d513bb5e3afd6824dc6b757bafa6d8c50713380e7a2afc21e84c4fd7370f3fbc9b4147cd9ff2e6b2e3e26df9bfb98edbdf65008d591ce66385978ff580019ed64e2ace97603ad48cb0baa44c3a5dbf92bcf25741503c4ad9666e123d24a8a16e9e490cf26f0c5e9893b5402c7a3ead43f18af7a7c1f0a23e81d5247ae95d3578b51dc182756dc2474a6498ac315f218437c9be99b984792d7da7548baf39c23f7fb1dec9ca97b5212460986d300d8b332ef31c4ab871c37e9087bdc1a9bc9862389ba9453313613600f4103d788caa36b42148c9e106c9b7f566cabb1c06923ab3a3353aa86515d99775a1d0e3f16baea27357f4aae7b37579dce1c97ce249847825281db8230a04fc47a473aa46d67b22add3b1c194252dbd1940b1fb060658c4d1a646d3b88c82c59ff3d7946dc75ddd1980e46b6b23e792fbd5e82c486c2cf3a8f1521c44cfc67ad5584ae5378026f84d659aa6b8bb5a34e1f8af8166526184bee6b4bbb00d4f81bb40f103c6c6cfb21da9dca216835f61d1cc330aec2788b328a4f70035b507566db05913b2d5b4ec19a58ce6f2c607ba411a382f995728e0fe9a51e8624dea77d3f86fabc9691e42eeb843021156fe56d0fcab73474b36dceb3421f2dd2d96e494d14dd2c46dadf640f7b9ab88fadf7ee7779a0f51ca6d166c6bfd7e002f15b8b3a775876a77a820a260403a25b70930c036f3fd864511f355139a9d30b7e8d7632b501bd0e8c4ab741fb44e875efa420e441d523ec59327f183b5bbcdbe15288297d579d51d1e813943d6a402b439607b21d770259e4f22064abff1fe37b31b5b4ee6e0b76b9e4126f05b54f1280acd4ee269bd098fba31a89939abbba1843a7ec2e12cb6c4eb36542247f067a8b087dbb6d14389580e07e3cbd0e5be135b68b87d396311dfff89adaf7c9557473c96929c4e665f98d603bcad57e905f3f33752062f46a0a55e6690e1f404163445599a3dc86f4b603e7beea16a75845211577b5b1452c8257087447a45cd43dc30a748e3dc4d951ab32549cf50c9f8c31c5ec72b97dd9b78c05bfe0aea9e1af93f282160837d3b573e9d6d9fcff782b6f511799557d70963c2e094c6f3dcc6e1d769cb702b5589f40802ceb2ab94e4de9153e6275b0db221abd48be939a78c3d1f2cc3e9416ccc45a4f65a3cfdf7d83b4379645c51955f3d71fe4230de0bb980157db38f5ceca74d6e1d5f54aaac3f5e8e1ff03bd0faf0b33b159cb9ecf6ab8460c9e3b6dd805de70e731b03805a98975df70cb908aae6fa4eb732a176283eee50ed6c22d9cc14de64754cf079d0e5278abf949f2d56e8365e7f8117c7f8d126a51bdf2742e2e1a477a326d9f6de7b85cd89e4a34db6f7941287034291ce729543e628f5264c6b4aeaa583d337436a26661ea91a77fe74e1ab9be02e2afb35b27c9fac23769a0f70c3e4645543552d7b3453c0598c1da0af1af003eea5103acbf89e3c1726bef6320decd170487d67623f354af05dc5651aff01f8239bf110caf295afef4b0db7ef139773401122b2d088296a0f0e0dd8f889f46e2fd1a3164eb09ce9e510686309bc6d9d32b132a2d78eb6dea2f5b2e6d97732ff818a1c91375a3d1f9e35ad8efb59663271f458afd04cc2631af62607ba7ff6f10a373e5b6ce52c537305a0fcca304efcd30d297de83769e7963d4f5d813b63186c9c7617cc940ef11a13369e9763102c8f5f51ec335835a2899141ab0e2ba8524071a42c437236f7e72064073d00e3a33bbeb31d484bb81106782bdeacc69d34dd6ea5ed63a9f432fec61b36c7d313d180d7305b026bd97ff2c38fe335c7176a93e43b34ac3cf03a2dc79a4ed5a924facf77c6e602ed6e208567fbf21ee3906b006b5bfd185f14fc45b87a5da0d17923c4ababf701438e815ab74c14bdcd21680270f31e04dcf0373a7fa6058b85adaa96337457d8e04283ea5ead73378a969c36759562d315ca9962539e5f4fb01e6ef551b37ce2cfeaf6956d14699cef6ff0a0f0fa5ad815d3a3298656b63532558aab8b11dbffd89d7030cd8111b525f6665cc890c68be9045b51bc8b90c9621f6bdfbfe00b86bf30c9b56f90e461692a025275eaf649c3c6143197f0e8f696d42f735589cb493829c3eac3d53f08e7f439fa678f258bf4fac0abe8d73c4eee996a396524dcf4617cd8713b6bf688a59457ff617b451ac09cbbaf82bb1a5c3c6ed633fe3a13845e0825b8911b41d8a24a5ad3df72ecd8b1c45261b89cbd8a4d82ed8626b9d8b62280103058a1cd15a9c0eb13efb487bd7d134648df56c0ff9f047b60b4d4420908be463719bc78739fa861640006f5f31d7c995968017974c8ea4d8f16ba4fce5ada6332cef09ed51580dcf65c71d30664a475a90ba855116c7fb295a5b322e817e88f556931e6fba01e7fc3a23065e27cfd7bb4a364a2fc90086c317e980a8e0f4b30f411aee252609cfd0b3366f26a7adff14700187f3f8034cfdb7d137c69767a3605f69cf8bf10d48205a1ccb99e732df2e2630a7e8b8287d01581ae452261d2b87ec75d07c544c73dcfc56981e1026810eb9fa89c6ca38ae355b2458b259fcfab9084795a7beb5dcadcfb439e7284f355c9a33be00d31131862c42c2113b59a527b2b5287399e99978b073c8a695e256b4586078f092a70e6c2481d34602182bee83b416490ac5b7a1ec08e3821fa7d543b1917de03ad13f21484fc1367a6b94e7e16dd210ac4668ed7d4a4f05cfcfcd2e6cfe479b3a21849dc2e633ba68628921809666dc7de833ade54b1fe8ca97ab74b630c54983b310d0662aa113a296802c4b653219c9916fbcb04ff03cdefef99b2dccbdff8a88a9d3084bcdb5574a6da58d4d1aec6dcb302eb26fea3d9ab1ef712068859312b914a819b98ae185dab504f47fe0947c46d864f34aa5c8c4e0e69443fc90b4b82e6c578f38bc1d5cde620dddf3c17f56d5401a2c490a5fb45ee828adcc3cf752bb52a8e6ad887907aee1dd8cc532ce232025cc26e1461b3aebac91201fe91d546fa5683a49a331cd35fb0a86317695a9c04a1f749b3e84b37172b4433275ec0c6c29d63cb8e4e4d14a062c42a6204a9ccedd652c673f34e113d2d1ad0f03ae8bb729fe0a35bc0c004ad789d2b01505342751b270325b41c836547b32635ce70334e42c51ca7ebf44f447d59e9d7bc297c1b5848695b7c3910e9f4f38d8a2ff4b03570a37243ee6d92f642e2d0f6369bc3a97b9c36e93f3961666e036a8677214ad1de6b644cfdc4abe12ac104da41b88aa878985faa6a423d73207ba7e14705185a7c576e94eadb743cf727fe77997a90dbe5d3ab79ceafa2fb3eb6148d0fe1a6a9837f2144c63585bc07d9022e1f1c6e391e5cab99e03124cb3d16c383b2ac8e987c70e4364e50f6f611e15988f19719815615f31f5833dc8bd833c94d01cfac47c3a5a6883b694eaf69b32d2a30d025fcf07848dcb2050d6ebd6a5a291cdd695ceffbadaab769c34be970554c39c52f11c81648419f99f591be01d5ba178db71a19527472800c5dcce416281773227ae75eaf1c185e4f646d4265daae27f00c08bb0645b7fc19b458e1958cb4da12bb9248dbb97c4818bcaf23e7a4a197a8d5a073a15818774f49678be513b5cf564d50a0346ee24cc930137fc8220e32670149022e68806abca860138a8c9bd5c06bc2e891e21f73d9e86e4653a17c75f1479e421e20f3156e7fa66af7be5d9e30510bae3ce740f0663cd26d0d8ad799f1131860ce1edd25d82a48c6523ce3bf38ec662928eff6c3fddf076b1b061ebb8d081e39a915560bce26dfc298442c875ca7a37da478cc67105fef4cec68470d23ecb54f4ccfd8cfbced274110ab42436c27f461ab990fa58a07e38c74335e68c80b785af168320e93843c79fecc2b95a357806de6aa2741d1791fe05883845d9dc8d5182513e3e31ebce7546a981ad0ebdeecb14ccc76023ac279b17613400c449d35130ce7da2c076406d5850ea9ed5bfd30b4ca8cdc3dc715f364bc98916379f1d263667a2510dda10a5eb3da2c43384b11a131a921ed82e293d4c08eb03fffa191928b1f33a05ddae6ff5d3caaf79a34c81b7a98985db332110306393eec58bcd46a6963555ae48a51d842f5054c678ca47cbbfc4f006d168c9135f172e1569a447feeb424b7f7d4a981e001708dad17f74685b28e4ffd5288f98f45ad0b8aebf27b4224b465e4530759a632cafdded5d7830f50725f8505c3a92149821f25f3628a46200d8efb0702d642e40c32559adaa02cd174732f2a15f66fa7a7bdd2e95eff9dbeedd2cd1fbe438587587d1f07842deba012943700999c923f20b6bbdc3fc2092537821c1a8e2596f0450fda0e933e8443e9565e7cda972c5a9e554306ecb91439fc1765705880bc7ae424fe9cd8e223cc4ee8cc002ed25b8bfdd47d201f794d35cca5a91ffb8d2ff15a016f8756ad88d4322ff14336b154ebea59755a450b8af596185bbf5666f30edc8dccf899fad592c88ec0255e438f1b56b87e95fb103f841b9c1a5fb367e6318b30fe9b8b12719b5a07376545cfcc520a3d0b1ece2910451f92a49fd9b6706ee7c63e2637e9bfa1043ef3575617cac439bedc3c77145e3b055ee403bb95b460c40f3317c37eac7e1c20da7a89efe3cc051ad5bde4f88ab49fd4525e8792c7d919bfd46aa83c33f70d9df696d9fa599950258f9f40282329fa99697a6794c39358cf4a9e8cdd75db5ba0b95378bb73c21c23c1e53869bb493e2086aa8d7d649557866477519024845dbb35c3c1d574b9f442cce9e2ed4dec00f62b058aea237487ccdf3fba217a94e5c10a7627c759289ed33c616dc45dae6a5911c9358c627c4f011561171ae77a92c36b431a5fb150bb9e064fdb7ac4dc3fcac794a13b1e07dacf497edc7496aa0927a7c247e802a028062d9a5fa0bf1eb6ec30ffe697da77d9619ff70bb0b5946a859b7f7dece64bcbacfd14b353a8d8280eb388ebc91897bfa4620110edf255f2b7dfe4756a32acce3131eb687350f0d193f275028ae94d0a8b4d3a3e1ca245eb6f36139ec10b4422a51fe80669a0456f2bc42b8328efe65c6d2d89654725a5104c8b6ddf9914dee54755330a587bd6c3c61727beaa825e2dbaf9fd2adaec3aa285501d2a50d5e4a58a374fea522402eba4bd7a7967f3c0c7d95fcbb79408dd9afb067deae9c791de12fc5b927b688d9063acd9258e4055fd3102914894801ea72c4632b8b0d9b8fc81151e62ae9109b466767f238e3c6ff09eea428f47af24d8ed7d426705c72c7f166a9c11b0398a8697f401a02c1c90900cffa08dc3a16ae31a35eefee207e7a6c4aaf4235381197b18202ef2b39ef0368c16ea129d09393ed510ab94c7fb3db2fb155a052e74ae0376841cd75ddc78aa12646ec1f30ba10be972fa5fa94a3cde9be03b4564d584a6333347db1e8ade20e8413a0d725b4e8fab81b617d5c70916f255506240e93d71b4004f5f05f18c16effaada40197cd80da941df8e7d7291c3dea515ffef01c32f8192e9063a1b0dca01702df5b1f9a9c6da5cb4e4529b453abcb0a9526be5afddea805b1a76dc8f40cdf752a7429492829f0adff3bc25cef410f67ef61c8aaf4a3679a76dbf34e2261e7431f2e964530c2870dad8f7fa0666f18222f63512cc476d4eba9eaa391f5ca4f1ab0201da56574f5638ebb44e27f15c393b854a9c7270a64704ac7a7caf42dab906edcad034b172634c87442d208dd97fdff698620525d3bd8c105acb6b0c338a92d1407ff97a58eeff840b5c62475493babf1562d8f3cdd9a0673d27e80df4b33dfae20d17f517ca82a48846997385b5332e7d1426b8b7adb6842237c95263bb43984aa65961a5246968d03428cdbfbf5311086c4c3939f78f9c1773f946e0903ec3173cb18a427154e145e840038275759d98b7fc611a7bceb700a32ea5839db6bd3b88fc3b130a9f0d2afc42dd6b196b0f9d2c1c4a1d23734890741b09ced45a2a519631952534b53e039c55dc8670bdb923b99154c01da997336fcc3aad921977f834be3bcb114ab7f5df6143ef82a3358bb53ac57e620d297a095201f66ed01d8b832c907a5d53381a80f09f9e8212773908f85b07ed32500b0c99e4e6b11a67daa09300342fcb43e96fb33ff4962c090e85c8a0268be270c20e5435c6e349e7db3a659d43f10ae5e4b8fe284dd49813b93b62c6df0300f74094eae40fe2c6a802afff2bb6af21b9b6070f2e1311b67e85ec80846cd795d251dfc07142c503b7dd3e83759a29a57f7b7c798b585fd87c82582cb2f0082b3aded3c9f19f1de2ac13010706445ccf696aba138d2083d0d9081a6128f4e2fc85e4becc1bd4e1722c82328d324e7dc26611a3855c2fc25e3c4da38ce3dac7bc66324ea8cbe9d5b91f2e7e4b37eba8163468537a7019cb34dcc8665e07fe5ac8b0b6ef6b35dacc43c8fa13619c077d3f29b0b1244f8e4c8b1c47cad31334f9b4daa85ab5f2d85896d51640a3b77500fc0d7fee38b7741d0513bfd68bcd028b9039844459ba59b42eec25043121d337e939043a22b31a2f1abdff6730dc9c764b83b0258abd090bec6a5aa4590c9450128f30f74527b3f47bb5c648eb139aacb3d116343dce197ec745e778cce6054b4bac83dc643b06861d736a62b765d9b4a40b06926dfbc74158e119b392214b74c291b11ee4c573235104e965a404b2dbe46e31620619a9c9915e495d10615810c2eb52f8e62dd27721317b32b4c89e9dfd65fddf621f99e7e1d3b4b317a5cda3453ade65b9e6b988e8ad8c1fc3b2065d1159a58e527a137b9eafc7e8295b419a1bb8ee81c9a0f752aa73b134d988be4d22e200fd35d04d20d07bb62e55d41cf931fce4603ec1a0dd3ee08225e0e2aa76f7b5a5700b5a96e78684b7d7c658829538adfc3aa6b167c4dc5df8a531381ecd46fac739ec7f2a30aad70bda43b8e0a520662799acda52c7eee4439077c3b8313f894fcecf97572b18e84165b23aaedf28fa3d8dd9e483d46a7a893d41f931c8381d8e19fb534f53ad85879c8ed504ee56e985bd262c45df97820c7041e3dac6046f26ad04ab17d7dcb35cc5bfc847235aaa566a666921d94584bde5d1c58083e3712f1836106c1ed018cb616f878e74651f6d35a73785eb47833cec397b72ea7eba7de5257a72f801a696ba67bf979fa317f1818b3ebcaca9284903e43655dc54937c3448ae41a662553750ed8cce453c287a2900eff3917debbcbe0a52fb456e2f6939c3940657c8e9477f2a23e5f480c2e9ad6d35666f3b930a94fe04676ab4d07e67b086674d58e59f53ef579a2987a32cb21e4e90aae6e592b39fd58e6d74aa43a9cbbfb7e8de75b5b331e72160f97e73a7571618d56338fc4706037f84a44bb3172a91070cc8b200755fd89e711cc60f17b00f77002761856f810b20afdbbab07627014ac7a2d0b050f88068f12ec77af9f51fa1007f62a10bec25b36c5384c758c5581617e8d04bcf3c67f2752e932c49344567ee8e63521555e07df6212406c2f8c69234907f4d2e407f1d48ce28e91afb07509681ad680f8404992146364e102a7cc689c8dd1bd7f08011eb83d9b9b6f43c9bc2bf44054db9f1fc11de8f9b45cad871e97f71c086f274f1f88cf1461ae920712009f7985f11d864042f48af318c7a88e7e8d43fcd16c1940b815f28bc89505e9e3d216be691cc35c020761fb72c441430ff051e0485889093992a46e4448f9ecaec1f22c0f1544fe27f2f2c4454e4e5f3b63108e7eb9799592acc88de6698e30151776c52c01c55d2079d46b511956903dd02fc9b791d2bb228a563794d674c19010304156d03dc5db1fc3bbd1e6c7a820cdbe49837d581f9ce1f3d0f58e24fc459d4bcafdc94dd9329d5a6e1408141437f2ead61a5e72030b818ad3f2af63e009f40b2e6e72075b7afa0c5e112102f4e0ae08182719664f8d87ea91ce6d136649213f98c0f3d43c5975c42e3f274d6d753afc8a78178636dcaf2086b377ffc3d0538cd70b914b79b5aad0fd5393694cab5d144ad3285d449096c74ebffe3f6deee3755a55da400e8f9da5c0a809f2e03acf649656cbbddb285a7546dd3e734dfaaf1e02baa025539489690437357ddacb6e8b23ff741568b75ef5d6d3db97c00eff87cff9c44aff557f8cff927aa041fc6801cc1f30525f26c15c9dd93deee588afabe5e3509eb313333c742387d60386d3d60247d5f0c7e85dc20a91f459dfcb9ada786edb6aec23a9cbd45f581a578fa421428b905317a744ad989ad7c5d2b1b870b4db040abe0fedcb0fba275e907bd151fc0eb679a8f9493aa4a769ab2b843ec8668264a362f25af6e3039ed51e8a7776e77005f0a814c81a6583fcf33aa20045c5dda8ea694cc7cea5d2742a9d9ad70725ccfcb85ab14107e46567432293ba5c9e767aa28ee0c2340b0ae2bac016de3d6052b3d895541c6c7b4ddb0c1bf38555e2430eb79f96d7d5f6fbe2ba60470731424cc7b100268352267a020528aedc98eaaaa6e70da7c8c62120026cb13d3a5583244758caab15cd02a52aa573e1ce61a279546dd257b1ad7d2b150c484b56f17b3421237d2ff6ff24dbf9857ea82733e4051f61b3e013bd9f43da92b8b79ed7209b054778d158d44fa9ae1ccbe80bacbbfb79ec97b559d00ecccb924b6879c764f589ec8614ff5ff127fa868cc6e8c760b8cac8042f84873f6342e0dae343c3a7a781649eac4c0a1cce3094347f3803c615709535ef17ee0b5167b18f5a2cec1025c656ff315ac059a6788199a87fd3e604dfd60c9f7737a2e385969163e08f9c985709db83ed2bcef890176e732af6fb3e9f7406f9fe0a062a32772428c4a854b06696f7c428a43f867ecbbdd78239bbd223e796fb9abd8c47e0ebbb7264990c9c4863c2f40ab6e1a5ccc0c99b460c0a57739b140b8fc5876d502c7157c63360ac0a10ca5cf19d3826992d0a64fe010ef4de688acdbe4c9afef1d8d5b75c9eb384b9952bb1a8e5a7cd74d983569621400de24e1714e8b8b4eb47e29efa88d29215b830be856fbe604ee4f0b4f413e5d1814c2f6e2273fe8f94506b2f89b7a5c91c41929aaff76a7b23271649636520751478bcc2759a660a8bbfec67a59a1db2df53ebecc903fd7ce05f82193d7911b8ee248dfb169f361fe95ee238d3207007f63b6509ef792673511027ef79412bf13c59e0fd0d2f465961241d7b583f59ff9727fd03de82dab4612de22769a9882a61abfa75804e3ba920ad6931821af014e6e80a13e3cb6235a77bdf17630dca80fb581eac0c67e5dc8cfc7237a0f21723df13a1ba806de9ba9316b8b429f1e27d7c39f43fab93f68f9e2f8b63719a85332f47e8a6bebe22170f2b5edefac654328846db4fadf661b833403404fed3bf6d219eaa9ce608f6898acedf9d531cfe5dd5e838e902bb38a42248900c7404747d1974256b4cdc5ec04d7c8b71ecc59a8faf51b7cb4a01991d1a4a6ecd9477cc6fa73fa3d139b022bedad90a95d203f4a8b44adc159c872892d64731d56fa4906e94ef7a5b57661b94a0535de4c6c53b749307c76b6b8a482273a8371a9bbfd79dbfd814e92ab7851b468385258f4c3ffa56f1642360e777955eb2e66a58d8a33a174ed69dbe51a32a7f3109e667df898ea37d13efbcd4cd397bbf5950b7b12f1550e93bab9a7fc985cc7eea3da14689d581673e0336db0901f23af228e805d8a5e5b2643b4485c85876f101ed89a83008cf1ba29f0efd67e487c1bf95dc246dc32d475c559aad370c2b122e3bfa357d47f5d2158b28d955d8e82c207b256f8e6fec9c75c923d6c533c1abcf7178d478a69c1fc04f4481672bda0e384f2d5f4f743f24be0e2b144ea993437ac259faafdb45c61eed39c15de9024e14b1b7afe1190c169ff287a6f7bbd6695a9c9112cccfd3c1d54c6f7aa56683faef3bf49c02d67568e9fa74881949940738b9ffe975740952bb082ebf1ef8a7df569a42b4544d0323fe2073376a8a321a9fa49833a8018a48e9eb65f74b94aca2fc882a7e72800af211307424e58af5dcabadf2e466b915a7cf90df3fe2d631856201661d526ac8ffd0cf624538e9a64940cbb5ed7eb3533c1340b5b32373713869bbedebeafca4d8e457596ba28bfd4fee010d78126752e208378dcd2091cedc4cda26287ac3a1f8ff9933665b4f87cbcdeecf090de2494b3017478475ebf8949c544fb97130c17ee1d6c17fa8b0fd42ec6fd219501f5518282e29cab51fb72070281b80c7c1cdfa99bd09ecbfc787712050d83d2965ddc7237adc840a3d89be2f88d3d89f090ea4117b053809f057c26e2b8af7d9e546b266a081599449ffa0355a7e516c4341cb74208ea4932a47d6a3912c1c5e9de14ce4bc8b605aa729c7c67b8d9274e7e19219792b8b3e90a041989e6f48c177517364ecdd3537bccdfaa23397d3f7aae509f3f94902ff7a3bfca8cd7727ddcc18531a2ec8f67ac492f1e7cf03557c681ef9ec8b6d658f372d11d3860625dfbba17cec7bb0ef101299b784a1f2a3c8ac3175cad5cf3851d767d94e7b34f1fc72ba17c96499b27f2fdb498b5c2861acf5a1db8d862a5a894089760e6373d07e9d47eece1175dcf35982eb0dd94f1c9d5da1a87dfbdf0a858416578ceec0fd943a3ad31f066b513147ccba551f3cd68578f3aaeb8c44f1d9a5d78a4ec2dceee53dd7f9b45e64dd4cef23cb4db38b024934a3299e3a6c98e7bfa3e301237eba54f12eb973eb3b117be61b00956c8abe7c86675a96fff52263a3981bb21c673d0787bcecdf4d669cf8002bdad439ddcea017894c7d2a782ca1f1f4b604e6bd2be5f10944ff47c5b9857cfe061508d663d5c4775f2526010cd8da20c51e1ed67c053f0d5bb07cb431cdeb8e2446f27b8853967858c4e1517d5810b05cdc28add6050d02104a08fec29f292db63c37168cc3e9319948d2bfc1cfde82e19cfe30e5c3a47b76d393f4e8c1e7b06b77ba1e1d338909f16c528cf0137614ded83a45d660949811baee831686347386f75f5a16b64dd7d29fbcea6b757094f0af1325a983a051f203504bd72ed41bb31f37a5f0417407cfafc0543d17d31266555ae8c71fbfea0749c424bbdded74bdd721b668295daf4626b9c121012d79cb1025de1bd37151d494a59bd17ca5a96c45cffd08141972dcc2755c402b357fdcc79de71cb26e44608a9ddd4b6f4535599e9a29f707cab3f1cf52d9e715c9e20ce3ebb42434dc0e0ea06996834b3ea81e304ef14637785d6f690411bc7b2419ec8ca2100d9fe78a0707b6ddaac024834020b305bded4777f8a6fe6db157fee3fb8047a4535a9e6d946be7909a90d8ddb54088aed8c0f9b60ac61e6863646b688e0487488ff740985253f204b78ecc388eb07bbc886b582bf49ae6b9eca1d94abcad4cd2a71a8be625272423f343887850daa1b6b3653bc4f973e719cc6c48022c747d161b10251ee1ba127ceca505ce893e46c5dc55ae11a4d76ebe88f9e3c0328d3cf73e869934a2957677d4be774a75380341e08d79b7a2062b45d95c40df64786b59cc5c9056e3f208bc902de8e4343392d476c752b13bb8532b19c0eddc9ba6f216d202bc57ce061644ed72568dc8ed2c2f22f0242149baa1148a7726d16a831ee105f075d14284a880910d03010d6897bc684e6102c750e70cb12065555d224aaebf8941a0c2aabd1e77462e760b260db41517142a40587f209536c2807ef21eb6853356da3f611ae0bb34cc0df5da88545dc403b7fe047cd3b7b36dd1fb0e0a407288106bddfaa4bdaec243b9e1369145f5b212c06352faf6092659db0b983c39c585200c721d9467b70e3bae336bfc646b042a52229e6b3c565a73aa7587ad0bce36fb3ff6568c77c4eb1bc7f5a99f6cf60b91eab437cbec2fbf1fcda65a87f8c35760e792349e915d18ac20b5503e077b171c0d53c7dbe56116616c75261337a8fac959cc3a243ceeab4bfec4b2c9ccbbdba64b26e7359a51292261720b99729931d01c6724c960beea35b62e259133f3df33ea8c0085d2ce9c219cec0ee58f4f195de3990db5e8901f76406674b72a476bcf41b28ba44e8c8d446461e6c471274889fe10d545a998254103f01d03bbbec9617893be0e21263af767a947273c8aa494d1d0becc6ab2f64a38623a474206942b56525bb7b17dab17071005ca0e7dc67e0baacda90226bc5f8e6c937642aaa96f4fc3c0765b6d145d26f41d26aeca9e0ac43dce7de73848c490203384439441ef7bbd079c3bc62ca6de43964bec2f76d2443e7793e68b0e63042c45793e53e9e0a1b7befbc21c1f183fa57b2c73d78f97a346c2f4a87ac9d4959cfbdc648db23205216442882de54931e66e502baf72a3550ebffd465ce0289d8cc4925664c572280a492861864ced5fec1a2bc09c98ab21b6285099994256d3a57c064a4663423a8e3f8e8a6118700dcf5e50c2aa2c087116c6c5e70891537d7a8f08ff43cfd72e351072c30abc42ad48bd0233320358c881c56f800ea4eb175f0533147596ac29234840a60d15297712e80a41c5bbd8d4b0471c587a3d463b1ac68f0b0ab47ab564305e75ef7fe4d41deed995b56ff2cbc2bebe19f934dae5202fc375874dd6c0456303d31d3edd824a635a9c4fe777ea02edf4ae02c07af6269d6ed395d35ca38a0afd3678f8f5ae27955b62b9a4d36a226c7f7fe7105bbfe4974119b85ca09caec2d719e7b4fe98a9046da8519c294227fc24a01b2e87a17aaad76b8f9bc885c4e2f6d7cdb38f1afe6e530742329ed04c203c67cd9bdddcfd69baccd9b0288c426bbd4a142ffc2372027fc7de963f0fe699ac311ef3f960e3bcd46720a6002d42503d55ad8dfec46d9718264cd945eb89a1404f08e72a89cd1898bc534c36d356314b8ea6f482caf8cb4ba176706095ef6f507f1284eb576d6bacbf765995ffafd129ab35f074edb23e186056754691300adc2621be8dfdffe9d75bf038ac2d310ba074f0c483e14fb811873fc1add882cb4884625f12dea4ab204bd043796b3bb80389b03f4bccf105bbc58936be64c603860197bdd75bd5ff5c28793da04ead3a546e447193e7ffd8e1c59c40174384905894f4425ffee416d06006ed0165ba65e368bbb6f5a5a72a4d12b88ed32aef89a9592ce28db5c8205426fec2480e3d80fae016091c278236c5a92e4dda13371f45808f7a0dc93ede934b37fb12d0172b73b9f562247021352a7b05b5d1e27e4ef735fcf2158791ab7016872d46ecac9c86e6ee88716fca41a8c0909e916d056a39588232227fde4186a1e46094252abf4374cebd94bad43230fe392b447b57521d737bcb7dae7aee91981f5b0aebb140a0acdc22f9d64ecafdc305c285b891c07432ce8f0a508b517c0f37423cf4b90647a32e8f33f7e2fbada3be4bd4fef74effa8920bc2befb9dbc86e659439d81d307e6bab468a0ec233ea073d072f243b0fb3f680ada02b66f5363c42dcb876f1caa07b336a68b10124ded93cfbbf9295ee1677f4486a01ac97bcaa7cca080e07a77be4f32e97bedeb79f30e44064b49f5bd24fbeffb8447e64ca54f94aa60af74f4c1be672fe62c0212c0b4dfd1cfe3edf270e229f710b1d71acd6109981159d682a6f8786782475e7d85d04c2b8718ebffce35c446db33b6a2e3cc00d9406653f456cd9dc93664ce81266508ff91692d3e607f05c0112b81eb4b872240d87e32907785cadc9f048825c0ff89e7d6863e208f1db60e6cf5a41bf109bd618dae9d4b8ac4f73063c8ff2c56649392d00ea19ef4132716959c7bd46d0923c2c04e073c6df79fcdb920ff06332d42a6383b5d8d0132ac81fc0e2428a372c8531f40b2b78f1c2192b19fd8ea9cc3a210f48074faf25a873104221cfc416de2a3b35ea5a54c627647f41d199fc0bb78b8f537a45122d11e5377959efecf406ee792314485cc95a2aec87f855b635695145e105435bdcd7eeb43634707107615b8459d9cc93dadff0f72380cfc9643768c0dc8c7631b8e9d762564413b94eba5620c6b3c4c4e3fb4398a3b82b5efba4b3593859bc8ee48afb751debe9db0f633a0a24a4571c2584f169880b068f82b6b013ccc5c7c69c2415a12d85b58133671a82ebc829218e0558d0b2cdf6dc07b0fec9bd0b8d07929f8e897a115ab016e81c0e2723dd3c538eea3d5d43e11df385c9438685984bff373d8ad4d7ea4e2f2fa1970c0b8a540bfb13b9e073015794add7d54d4b781721373cc9e652c32d30df223632d9fa9a2e92d4d7a7cb935d35d9a306d0e5c085178d50b41cc00c39b9f4d3e69469a143d55ba3edfcb6c61a15fce166062d9566dfc7f2f6c1eeb3e10f4b8a50022b4eda546286e041bf389eb5b063f5fd97257b12da7f5aa90ee138034cff680794a650ba9ad8b2bce4628b66290cc1a495bfce00bc3310dac9ffec5bdec4ea1ceeb8c750012488d1757ad4538405743e405ff318e8f6609fb411f4b357d7ef3649e51c17043050b7e670388d29306c8d69fbcf097d18521590f72a440926641e18127b60c7e9609186b67e0522ce428d52a2d7067d82ddfcb9d6f564e5b8edc5a3c7526def388bbab11e1b181fb633008a95ad4fa303e326bea2f1fb6f839fbd0a2586b88963ca860f82c6edeef605cb768f9184a08768837bb30807ad4bcedd81e5fcf6a2b7adb835a585561e02502c1b63fb01f80746d7bb6322196038c9dcdb4117662144a44b3d430c78cb6c2c690c7e7e8a79b5f067614ba210456ac855f7c810d63046285f98e84599818e89f6436020ea40bda7ac91f51c40e23b7d375d2ec8584a4f6a66252d5f12d856d302c20b865c4cc914b842131b9ebeca02b177a7adf9b991b300c64cad3726502e2d67934100c9df218347bb7224efe3883c0d44cf839e233a68d93f7ef980b6acce51fbc7801d68fc77a67081b9678f8f5eb4eb8d291510495414cc5f5adc01fed14c44af610266ec46da690fd03ba10033bce733896c6cc9b504ac08e0fbcc136ce37d0ce378ac5876bea858512b3f6563f875a5fac0a2a3fce24032c1ce2ac9aaa858d88f1020e6dbd48bcd947590d5c1bfeb070eed14b462f13101bdbbdf33d37c967d3877203a94d5883d4f3d808805b67b0d49c51eac4caab08db2fc5cea9ddf7bacc3f525e64904a7913df1425175d4a64a6c9e3fcf38d5aa17835f71d0c74345d8316e3872fc3590d42bd81b8becb75e18843b998f8681a041b09e8119aacc2ee2fbb6597819e9dd017e46e59a9e46e0d301ff83704b007badc99452670a649603933852835a9d01c67c9e7afb2472fd766d305f2dd3e184599a5a7508d0a1038e06e11ecd093c73d2e23537a504d9fed74e920766fdd55e70a645e7cc814b8729c07176866f33da4a612f35ddd3c36600e19e55ff8fd20320cf8d95d61ffe7fa06bba2d46092972b421cbeef90cbd672cc4996d64c464847fa0d6fddd7de26ea351deaae24291d1aba1ffb23fa2b732b3fc17e82c379e5c65fa906455b76793bb3894ba25b74bcdacaadb0cc5e3bcf9ea20d2dfc10b35bda0c1267158ba9ebdfbcc3e2523751dfda5e089b7ad65bf7f9f555bbbe6b0c5ce74a3baf49e4bfe89a725283667aa2356f4cee670952e0e5945a74dbdb2da2ca98dcee02e55525d0390cc985ba024297fa425176fd4d0cbc4dac7f1282982b1bfa6b9aee6d187bdc03b6fc48ccb615e4b8350a539e9a39f6bb869697fef3f1b3f198646503dca5b0232d47a9cc85adb21666f37fda92110770e64c9868f3b2ea9061bf64e6d47358c4a1af7d3607911d57b307d0b95c46e25bc81f6cb4418f1160e92a115b4f87428ab9a2bf4a1523545e0608de3f7d5bcc0c53bbae9ac0d6d8a9a81933a81805afe706111f2beca2735e206505e52e864042d558ca7e50d0ca9e5b0780fcb4e22cde8b8f5d43d62b16d4d1406891dbe96dead9acd4226f4264cdb528dc85b70a944477e72b3442e10f956b3832eb8c34d49d77a5fce52c6b7c705ee837cb036eba8ceca7fc60ff25c9b5d72125b96b0568fdaaa280c4b10bdf1ca378e34d86ce55507de168b36740c079295abb4c35bd342a8ebeed119002b8557b62c622022f3a3a5a08517a7a75f3193ab6498d813ac030daf435dc3b9ce1d2fde328912c766c7d91f5b7d0bd8c70466b9a51831a1c95d08daa4af593622d36db63c98d8210da650aac62281abe02019c2b33cc09c1a382dc57e7327f0ce80cd617581e7b72d640d4b9a11a156c8bafe502cd7d1219ebf687c1fc8c3fa31c91b7d02a8d5c53b1cea26206e941642a44a338efacc918952b1e1bf7e69ecfb834b40ae1cb1298666ceb0773cf00650acfab8654ef2a08faab2f268f73b0d499eba7b72565b1cde3b7671c7412220e270589d40b7d2eb1db8c4ef456d1f046e78fbfd172e704cab927c9c42c2a02eb06dab302b95912b21580c047d1602417c71ba5c9c44f3306b8bed3d348bfd82f03a21f5a24ec6f32cbd5f4f377658b7ea27f35f067fe0d12fba3de7606a0ac46074314735b6633c84c202623196e8e9296d9099b72ba4e3ab2ab9a69175301f05afb3c494e56978028648f98e96f2defc9f02f0d9ef71b4e71e067b8eff6cff42238bdcc9f324e6bcd3771525afebbf935a22d60af0dc94e256877727dc759f05787d896431b8e51726311dfc57df039c3814ec2c33444b3bd5bb92b361732985b0c01531e759cceadd330d00f44e480749ba44d97b1c8fa2f64d09cd4f0342150ded2821e0915d50245ab59c7393368f9951a76c46a31b897c5dc6efc54aee67210367de75007432a282096f0daf2a8dd070b5a9c7a23fddd3b26508800df93284863a84cc3955c77e3d75bb794e28ee93bea12d789e1adaba4da3d39fb2db6abc41d17c7ed8f14855e617fe3f04de13dfaa13a5dd3200937a637e413d5fb96f0cddf029c5b0ffa9e0d00e71b52355bba7fbff7d67617517936a61824c6270192a57c2f338150a65bb585b9c39e374d03b00c123cacb8b003ff7746c62b97b0c1e4e3ac708812447345af97a05e4814398b2b711e4aaf9808587d8f3f8857f6618c40f4ed791b61c195c5da08e25f15bda1713418e7c06b47270e4b408e6dad05cd23156561964a3042d5fcf2c10d5d22dfd1ed83def963f8538be4595a41a45a92dd841765407a558e02d216571adb2930d660cec22410ab82bb36268f949dc10cc54f4804fd7b1095903268eed2083298a7356ce31319af5037911c9c9bad7d22a63a25511d0747aded591d1c7a1235d93ee1363e8ed0959433bdbfbbb74ce6205b4c42db2e83978bd2231ea265c9186c45dc087732239473bd8c5252dbab37258207b3b278d7c0fd422112cfd6cd7e528a70ab0f44cf3d82ca7a90ab5e659080c1bc7406693b0a4b5124efe0321ab2f7401d2bf2171b83cb31923c7c076c9f2cfbf6f5b9e48816f1f20b842e4fb0759ae70bece25d3d6cac6e4fbc9f066ce010f3f287920f9b4491240e35b4e06f4b7c8d889c922fea170bef436590b0839d832cea2fde372f24bc19fd89b48e216978e5720138914e0c1ed6fa8cbc6694e33f1a6ed089bbd40d11df6233313e86f04777b41ebba9db4ad2a079d972838faf729952189f2c6b95c8d6596ef10d4cada7a2f0dde6d80d1259cc839f1e070b40a245e581e7ae4f945e0fc6ef1390126e005833b22b5d85748e860ec237410006103a44e85c0a4a0ee39ed7c7204ad80c87de7956175d49718afcb6668951777b93cce8edeb354cc047e828e34ae22d2d1fda5c89e4b8029dbe3c57e22430a927e07d7705e451402fd9048ab9d6dc8e64872f87547d6341b296147c901ecd7f1c64632e711251950439581bebf9e0f8eab1227c3e7630a79fbe2c7f3c0fd578f1104ca4b486c2004a1b96684c2077132d22897946515d7cf9066c5f14570f0449c73f740a22731b9f77706d92def78a8130b273b7f83906a6a24bea0ff314b3e209d214621a80e01e73c260f925aa9a3df798606dc1ed5089959a52e84f8a982b68edf22d97a1abd5f301784297d08af1d3c7163b74b06bcc9a447a6e9321fa4041d2d7ad236b68e5698304b7257dbe2a6b248a95010a463cfc2d31e5ad1d684a341ff72138ad9675812463ad83db095cd59a0423aa2ea2d8f70e53f5f3d3461263f649c5210026293a3487ca90eaa59228604582dec92687d29026f73641652fdd73d6bab5ee9d7a019e9c199e94c96950ced583501cac1cbea77e2f18a820e279b7edf746a9289af415df0ad56a36dfe6bd830f77d5bcb9b4db29efa8f9e15410b43c6297bacc1250a0c473e8e1c838824724179e4e7b775bebe394ec4e2c6b52efa5cf5929611d75f2e355c5aacea66a7973499081c6e1f40a7ed8e0d525f63b584e977d144b05c955e9a9fd264ec7546e69438ddf27805395d9ca29f9956249bed5e3ca71cc7267da35042c647f83ede887e0c614afce9987930c2788928c2e8cea1dde4b18d87e1321992d089fcdb31b20968ff2434b38c5ebc5179ca3050a7d28f06f014dec6201f59b688d248ff400651bc886b35ea8cd8e3887378b6671ea5cb45b6897933f90ebd495892876255fa45a525073e7cd21f96564b44025cca3ef90cff41010c11553ff86b510f83254a0f03e1cb99a983b23244c2681cc83b884e4cff7a35b1db4645badd27fcb4cabe104bf305ea11065b85482932f2ddcdb65a6ed9fd6efd0f9f3f89c0ed0b77ed183291737d1d66dbecfa55a2cc5e2dd2fa3835b9081999cb5d1b057620cc6cea4aac6bae200500a155f3e502d5cf39b15e7fe9cdf2ef530644e8706e0ac892e6cb625f43d541bdf39a9bf1835a971b65e9e3c6db6f3cab00b263d3ff1af0c392cfe37f2e8077d508bdf12051b533972a45d765e94ba99d9e5f08d249644a379dafcf64d8392aa07483da338858d30e3168a42bb4c7410202ea8b59465c8ea1132d41567a6de2513532748b60400d27fc60db5947288de2f1416c8a99d228121fe1d738b6b59128e41c98df364bcb1390ce6d386026188ddf3af42ed58f6d7ded9d34b9a4adccaefda521986d7fe69655d02875a21d27f33c0cf71daf401fef5fcd024d55e163553e477d8ea17692d106997e9954fe51d67c62796db87a50d61d884a2940f86bf91883a1cf81f8c29c46617d4dc90fc32ec13d7a9d7054b9e1fe492b9704fafe86e78bf772f68470542e886529500f4245954727942ff9c15f8336acc97f29be30f3d15b5294e7dbceb721cd2c5680f144765f23d7cfe120f62d98b339114f92a0676e6f48a0df7e596ef5a9b127aa292339a32670796766e1d654cab5dfecbd7824cdcbd7d1b63f095d2c3d1a16ad7ac70e582193c54eb3a764c71f3c8b96609dd79673993c00be8558b2f5bf0fd8b371837d5c7548ec5b9d4a4260e349f8b130a80f83bcd42c5a7e8458b3a8a8dace086b99a795d26e1289f73c95429147006fb54fd6d5a06b7df4565c3fe64a3c80176d53bb06698c8f81d9843167d80a4af6efcabffc7616a79f1b5e627de99a67483f4e8b1a5b0a70a0faae2e878204be17fe19eeee66374490ecf0ad675326aa5e19e7d780cdcbb4d4cadf347664fa07744e53ed7a48301061ac6d719f48bfc5757be8efb8f15ff719de029066f2ea2e14026d241e289ca3e9259b7be071b222fb7800203bf01819d350b34e11b6152c33569cf22d5de196ad3bab4d70c8a6c97fcf3da8495c5534577588bcb13a6fdbf19946f5d45707d3b96390dc8d6cbbd20a22829a69020f826a54837be376175f051dca891d1e935087fe92db1a4974270e9e496d8bd39c792dc23742a1a177938abf61a70d03923674b981c63bb37c45ce112ca0fb2e68ebbd23a36ae0847f0202b0d132bdbfa12ab641e1a4c3db4b2a6bbb876b5bce3c2063baff1604a3bf99697a218928f4c6e33952c817af461ebe0b8f12b35424eb3f6ab53c75e31b4e36ab1ef5472a0d27062d41e184e29abaeff9e781e79fe1d8e88eb750b9fcfddd67acce769a4ae7823efe960c0e65f93af364357aa30c184d75ac11fafdab46e0fc67e1f8f8a5f4cdfda8df4d301983cd7db16e236d29bbcdd4467e3258ac7f65a351b01c84d301bd1be66fbe4db3931e2eb342aa156f12b83fb7254b00589a20d1aa7c57177063654c6a1406c991d7ca8b07303f4e092aa18fa3c2e9b86410baea1928a715f1fff35b1aabef31f11579585d6e9152650116fbbd69b8837bbb1fa6760aed9b04daebd2cfa24cea09c9d2bf63d7d4ded0dbd1a5cf488373352e1ca1c49b48def52b097be336c03ab0cc5bfff49abd529d0b190af55c166fe861b56127b58fb7ea61a25418745b21d12ac44787feea3b90306702b1b7ae424beb8743165b55d1efa09a220817ffe1896a477b26f1092f755207d881c960469cb3202f4b5596abc1afa48860b727a754f9058f1eed1f064ca79a5a14914a157f1655fe6cd921e56fd1dd8bbe4fb15d8a38663ba9f17e835cf13e943b1da3780e4c5f7f34ac4b97ffef2fcc6e2ee87316e3e863fbf87cf8731fcd780d98df10d03fbabc3441e42b6442c271f50a72d5be8db896a0234615c26081cb660bd20fd9110f0ba84f1cb6610d8f154a5da408d1f2fe5f3c988bb96d78e59a15b07b1b30214c48b20019bd1c5a671ae10887b364e4630fbf5a7252a6b5d39fdb24a7716da6657e2db7700457dd0948e324bbfeb955446e3a333ff2cf5bdb821b56de151ca104546d2e9f9262135ff808bdd229541fc430c661acad17ebd6b8d1255256ec3ce428221bad508348eb173fb511e86fd58dc2ebaac2cdf3f71f968b0034b18371dca08d04f298a07814605e6f2692ecc8387ce004530b25cefd4d37702d40f178d07cac5c23b060d9bd769caaf86ff937d9e399ec07ad53c59c6463326005a839b1dd07c8e00278f5bcdafa197a40075f2f4f1b2fe199db5832e0fa00b2b69090e7284da76a4b773f6db2d0c533529745a2b1d87583d053b0699088e5cf650176a9c3c29ba1a70d8ee960f8901d0b194e23c780bfd988edeb3bbf5c6d34b691cffdd559335dbc6faead3e5fa980f1f59ad414d7f85b39546c9a0bf8ee0a230536ca74fc7b5f79710f800e6efa060c9ee34e066169221cd39e337ebace118bd80f4e9315f990fcc60060a73e68d2be7197949b094d57fdfbcfa3d4bda0668ea64e9403704a983168b91c5365d0b1a3ad25c95465f22d8936d6b473d32fdc73647968fb0b2e4656eec0a8bf304809093d8b04456cae1d01c56602447701e30c1ea8e57b45eb6da9a33410cea531da4fd2d3c0e522da57d7c0879416f70f6397ee3cb221c047a27f83c718c77db69b2b464e0e69380568a0dd019425c61ad7d46c94737d2c9b3cd2f74ddd152948454ab9f2fbaf175b0abd6554a3cf670349f9177c6c47c7c29f790854264cd792c42a30b1904aecd80782e5becdf9d1aa03f036e91c36ceffff89e7683af5842ad18c12da31a262db0645da1cb06b6818953e83fbbe0c4033562d06c7c6b7b0314620af7517e95e5693f319fd8736dd03623725877193a589fd901dbf97e4cc9666016c9eb8f87f23d2d5124f361b8481113a8a2a2a9fd5926a660688a12ce64f3700901af2c7a118c2508d4d1100b5e2c0df062634647b030872d4f77b975d49f961c8bbc58b31cc4bfbfa3ecd6c9d074b34a53cd74ec2ec0192b0dd3d8dc784dba6478ecd393470ca1183fd59337aee8f93a7e105ce538a1b1b649cda364bffd4c775bca13176e1d9abab01088f3a129b107ebfe8e8c2713ea6302f4f1e70762b67c14a21afe3c9207d45183d51c485e8a8026ed656e4af4a65c21e60f8a01639daf9e7aa22b70c1e7abb5d24bef7c75323beb10b247ea8b63837b309659e0e3ef9219be9b496c9db7fcf72b2094602a80e5531dd3059ec46f580867da54eb10c7fbcce6fc8f378cf64b17c9425eab9f7ca66ebec58d74c2f32d1771751dbbe81480224f516a20394190d2957f9bbb8b4f96f6ac75560516d3008ba47183e66134871809c4009c4d0e2420827f13ed2a603d916c55c1bf56c8c3ef8c338b1784db3a4e6f19ac69d510c9e4440f82ba9dc35312da10f438c410a4b4cf7cca1170c5f78919a4c3015bf75faef6b779b71eaad5648a806be01e36ee12d963fc37a14835218bc5b28a18bfee2e86a87bca07e751f46b15070bcc005071f538f8839105ca240d553480fe2403e5a87d74e47ad6e0d6cd8a79d3ab97e2482ef629291d8028f5a18d7d4ed5afb4ffa366bc40e218d831b41651d320c274a82895d495c9b14b57d9940d7913560ce73c528e7eeecd827d330f5f064535d8a90eadbcaf6243b87e22f512bfeb5ab96f7e09669e4a622e7e89bc23fb43f53eda4046dad60c970fa3dfbb9e5e3c8fcc8e3b222cc5c6d1b41af0033c97269ccb01298861b37c3aa958ec28cd8b33c2e43dd286282e94dced174d54d0b1a5d175c70659edf31059d68c22c905f0f91743b8fedbd6309c6ef9abd30c802e0df1c71c69fb395238776115435fbc4a85ba01fed1e883a3698d8688108b7bdd89691ecad3d073bd5d07b5fcfb5f679cca9cd07315f70735de60b567d0a506e77eed08fde34d8137274eb079ba3ac740e72259432c508169f884f6e4a8c0e69afe4d26d80c981f5a83b581d0ff8040a2a673f54203442b58343fb2a7e2979969b7cc651e7d50282848c71c74c74a5c98d04e7e3333235814e55c1edbef00e39ae80fca0c3863ba9e41a7ae00dab1999e00cf45210ba119f24694e7cb3dc241c23799dd920c16e4e207edd56ff519d514f61462f551f874b9b4fcf590784a44c5f9a2c8e357dd28e8fb3af8934089510ec4958d5c2cafdabbb74c168b4bb270481c1b6b6c79a23da5096c0ae063ac28d08d3e4b8a166c02dafd9d3c2f48b80811343baf894b31e1a6f8d2f77b5ab2df65bb88447e1d470c58d6b97f8d8647a38da6c5e09c9cd98e607ea679f360f4ce61df5b10cde33af61c1214d8b8c53bc689923d7577f7273ef3fc22da03cbd5eb91c48f4bbdba3e1b88ba070483b2d5b2106c972eec1a237f9c0503dd986b23c88fce92bcc34e7fb1e3b34f149db4a2746e66d929734d13ecd05db9a6569f0d245ae7df167dec3675722f712a4179833c3f2a0369d7484c16300f9286713355107b871d0a191a46253840ae6478e2e1f6f5cf29d25a633fcc64c5c61076f63bc4a5412c026935b3bf2f5541aa553d26d579a90a4c08433960f768b6297610ae283c0c73984705e2f1309e0064999e3630849f743cdda9d9d781ee4561c69ae1f02cf66365f1f8e8c5f0ecde717e0bb440141b269d25db154095e85020a179bbc0aedfb8c092858d625f64ec6654e9bae63f11dbee1e05c9099fb1b6e416dec416dd906df86fd1d33b5ad6427a29eba06dcf69e545846efdf8fe74c141c78a099c61778225e4ed5b816400ad4823fe250415dc8f3634c56f21f62e5fc496ad968faee2ddd56ebfedbc736a90872f140d08e96758701952a09605aa4c44fb45e53096628a5bcea3ae0352e3d564a636ea6ab17ef98ed34dca5fcdd81abdc6519aef0a7220de92b94070d22c1cafd9ce8e9f0c033690e8b5b5ae1a625d14ab7d0dc8b0384421bbf66dd2ac9236336a1af2aaadbd2d00a5b3f889ad5931cd6ec348e33e8564f549715382b36d46d83b54666937a57d16719e2580cf97314fe3b16373ae5ca45f09cdd6106df68cc9e3852ba1f8c6dc0c77a8260dc33fd50f2b674f1d91642b02f9e27bb070bf6e0862b967c38e01da58fddd2a3c82c55735286add5b7328a68a6a982c887d2ce08594ac7637e2d4bd36de4929dc51295879a5aabfc8d7d05afc90663fd0b439285478754cfb5ca23ec1671e155bcad66c5e66417ee5e37fcf339aa4adab430d66924f0a5d08682d2d07586072e38b41e70255f4dc35783705c39184f6faae59f6b310fe7205baf5c62a90f0cc81b81efbb5337df1cb32d34c6d32da14d9f90ea0ebf1001c5a961d6e848ccec5d0fba513b60e1ec8f6e29c5cdb21fe793898b4af57fcfadb4e1da4efb78ef36c0df96a8f6be908945c7d25d4bec8cc48aabcf6769734d2470eb8c6923ffd2167de0b4bfc4976c88dc8f911b9c293e69fedd218fe94ada884184f27cc3ea6116a4689f2bdc741e2ff53106e4e82a45ddd5a390b397e9a102ff3bc6b6122a4e8b8a24a575422446196eb8df437cd18ada1a7869046d3060bd6764609ea15ae3ae1b05cdb74f650ce10fb731b592efc8b848ac8fbc9e1072bcf0365297f275c1deb72644c80f4ed9e9a5b1663eb33bae3e762d982ebb80ca0b2a830933ab513b073ed3cd8ee7d153c6b206979d3d0f7fc9272c2203fbac6f823a86dce2c5408fbfa086836b8f255b60c2ba38e34049222eaa960cfcbbd770cf7859ff37afa1447296ce90bba446acba390a34dd8f588523fbed4de7c57a7fcf9f18bcf1264dd8d1e327aae44ed4cc068aef6ca80cec1e818eb4f94fcf6f148c3387ca0bc7775e2711ea4623778a838a888af697c8dc58b0f9b9aaf5759a83aa25a4f5de61c35485bb269cd541c441965a9b96fc41bf4a07f5228be4ac23615b31db72f7b52d56208d6e7723b7c79d55ba4a6393648be37541e9e7e170f89765107f8d3be7a016c79db059ad2d0167b2ed3af5c681b1b8fcc86657f3c018a6e712fec3cb47e5d0684e1e00b4c5461e84c69192244ca042d9351467fd162e66616bab50616815a4583be5006a8a382a7b12c94087e8a5c940223003f6d071949ffd13f6ec6722ef03f3b0371eee0ee9db84546f4b8c9046da0a2f5d55fd9eb724c6d9e3f2ed323e9e8841899936eea362317770d11caf38c51d212686d6b889deb94ba57e7efef3a772962ee12ff89822018f30259692f66b75fe81cdd8bffe7d204284a72e2d71314e93ecd45300ba1c82c745ccc24fab7cdc9728d6be0138466bc0da448abff1edf99c6986bc42e1356b7b1f2a7f295bbec3468b6d380a4cc0035ec5c43b18591803b0da2afc3896d5522891e92f40aaecae49488428592ed088a55f069f1b78b816ea7ddd07c200524f8605cc4f59c3f57edb6e04740a0ebbda9fd49bd4f8ba15e90afb7c14b08c8f3bd4effd2c48cc9525f94bf96e56299650c1e4a838d39a0c2168209d4e102afcf7c88a525c647958036296d5efc9f278cb3fcce466e55425faeedea7cdaca3a032b6f811f90bf7adae0b942c4daa7579481884e05d89a0e1a16ec9e9d65e47db3c81d03c60a40f29ed5dfaf2b6f035ea5d9e73d6470a9546178b4f7c5c245383396725e082b0ef43c7ea7b28c9b779093e3d821eaa7f7615207b3621f10c39d5eac0ca03fefff94d9ebd4115ca7a8061cd5d6b758766ebc5b3c7e3248845fc9a7ebba5911094270f7be017a146cfdc7daa9bd8739e848e8c28324de7ba320d696f3d79d786290be08d4fecab9200f6bd0edbbc3b829557c48e3237521d37ad7d61fccd0fd9298ed73aad52ea83468dec7c88c8c97425cf57e991ece3fa34e4431c5039feef4a5361af7a12640b604b60034070eba27935b811727e1c6eb59dac38d53f4a84d39b04522fa254f6fd4cad86e2ece30c24e65b924627903db85e5a2c2d23378840eeac97aadad9283abe8cd239ec9ae3091b1761dab84c1bd9dfa42d98e400dc20409572db9b8bff06772500a884959adf0e9a2aa0d265c2095222aa2daf4dad4da26fa92633df1a9c16fe27508c7c023a3e3dfaa4d6e7377e592730431a4cf9be113cb77af5937f0b6f2bc8b8ec1bfdf3641854cddc4b51a09b00476acb9ff9efc64b6b93d989306db89f50738b3fce8d8d5a2197c2defa07554ebc6989cf444161f4fc6f0a4a4242f3006b7905f55ff59e5e08da67fb296fd58315ab97ce652ece69253732391db084e81f0288f19d7e249fb01c0116f6b2002fc21897231dd28483ef70feeb5a1ccea87a5f26911a64728cb74995dbce9042351d8f59323ab007afc1de20c77535e6d3ebcf85af574f5e945e454016bfd953bb1e33ad1a8ccab57a0eb290168ca5970fdfb614b937377ed8ba01cae8bdaaaa250078a2ff49cbdc3e357306e7aeae98285327d96c37745c02bf37c9c1393802a06fc9120513f9cddec5b6bf7738abc24f66b2660946021598414861fc73da1ef844a539a89cc5177ff7fa317b7cc643af99abe907d379ecf650b1968a9c0adf54ee410ddebeeda5ee4a51b8afd83c738da34256a7bbfc3afde9c884be98f46ba3d6e7a997faf7496cadaa6df0e63788294a25a62d4cd5b98ce4e91e6dc74cb76d998bf2ed778e0b3be0765bc19f629f658ea0bb04c2405ab7c4b907ee418e9c519ee2ee87770b1ec3c9ecc7e55288b68e84333bd3899a33bfcfa1085393ec0462911311486dfe084bda64f94529ed5563ae7a626c7391215c8bf74690745c00328470b8deba7736bb1506417c5ed7714a55c7bb7a42412038b86b08022e9deb1b70740fa2733128cb9a30ad5b4edcb27364312152491110c52f76199b27c23f600c47fa1eafd4f087c1ad72b3f4c25b1b18f06fb78bedd709acf233cc8a1b6d40ed2bf7312a3c003055b9a00fdee16d770ee82af67eee82c0f48b5cdeff48d860caf552f640560aac08a9257ff80a5ea0e1e3153e6cf5c6d5ff31bb165411231f5e2d207b2cbbe9af4ea3190802e22f337f5736bb51f7131b0d9c5da4ab3dba799b8266100a3a0018dbab2add770d9891980bc49ebf4d05171860a3f705596e503c2a1f39255b99caaea45bd56fd1690f0ef08fea017a29bd07f54707741fd42e1741925525f6335e0236d5a4c56c3609d94c995673ff941ebc49008f8b1b9ba01866f1a13e965bfed5e1afbbe90978da3c279089d4508623d31cd06d08c38fffed152c0a7935bf5358eb6afe87e54075e3e133e000cfb9815b178748bd127a54f11e56e347b77b3b9c6822d36cf442e14873c84cf3512f9671b78c08971d0cfac0f199d4caf6dde2a7a1fcaf61b3f74b529a51ba451c163ce1f59c0c0e025eabcbcb73f0897a0b80568ed5ff3f61f5590addfe8303eee1cfd917e7a16b739e748b2da16c348d1bd73410d14b0c0254a2e9d5f17d78a51c4fd9cf3d011b42249125df340bb086de570525fae2032b7609e703b471cd7f11e8b1b62e1a6f02e91b327e393a9b4ca0c206130ffe3c19f80a67b6d662a0cc951df713ad50708f5cb7ba4d94ae83d030b4d57835f95a626b1733bc186b774b45167e4ac6815cb251ef3cf2a2162110ea7612793d2939f357f10ee8291b4ce75b079cac6f032e08d13961d2a3ce79a0089d71238266ac31e38222217d2338c1bc9738a5f42f19a46aa8de34740e15d4e57ccc42724f65f25774d53f1e9d803ddd5448cead46ed33b0e89dea4b80338bc0e1e4ec2c2fed349d72d2071fb368a9c9eb198b6a387f91b0997519d56e8734f54dd82238e5811a23da7e9bd66f25819e0de753b5319f91dcb40559504d7725597a60bbd3390e5cffcb64b2d693583bee2616362d365a3e01f4e4ff55c6a6c92c1386bd5fb039a399b7803d38e96d7fc6b31b338a7187b98fc9a1f55367d3de6377b640911fa6ba1d91f309b37b41cb2ea875b03bc7d0139e32074f8bb977797a86f55403c6911689cedb30592267bd5e549b0912ed30de98df28c4a1c5af4de0273251067f84c6a9c0406e79648f248b2ff643a88a57184f77c73127f92b582518f7be7f4a14368eb7cd97b659c5cc54d3083d3dfa961741c36655096a53e73019d20d34049c63ba3f3f34d439ac61941d646c09f712c35a4438b04e6639db92b89786c86f9ce517caaa2469337cbca94edb096492a65356062aaa39cc5c3db6ed387b7a9849767d27cec2d33fcc8d23e015b5bb2903e47f1bb78068e053333b02ea3bbe73135fc6d66c02cd1e1ccd4163cea5b90703d4d2e5a576a407e92bf36b96d76f787052578509f24e096a951ed129014be9b15395d8d83abe0f4a0cadbb644206b2fab4b52ac4e4fb9141826b7c1c27fb4946677212c4c3a5f9ef9c66cb5c61fc33e9151017eed7f7f8f3051c8fb5f861ec1a6212d82d561a4b54c5c51640100c7bc72026c6a80205d9b50fa98cc573301ea615ed85b4950a7473288f2ced1e550c38ee22dc36241a38a12434ee8a962d4206a34571ac8401c9c8a9f141a9012b8c4b30ff9ef957ca72a5c913607ca070e2cc9c7d9075dbdcbaae8267e1fb1a484a75ae3eb01f1af76cd7c956c1b9df9f93bacf1b1f73bff0dca16cf02da29398bdd16ec470855a03564126aa4c3ec781c4294db4dfbd5a8a316aff7c6f7e49b4f45df02ddb0f38742f21036382a6b8546a10b330a861b476bbd4819b64a10b687b7473a7e6ae80876188b99b930aac1aaa4dfb7a5760d765cc53eba10d9d8c54df0d7deca082d79e7b4dbc0150f1e9b5d373aa1b7d08a29241222438d5c9cf03e81407dcc739b813c9a8958561424d85f89578d5940b7488412b0e4048c6f96c361f0b551f813641ef80dc216976cd6020e6015229f488f42787e78544573df7478751c66d27d9bb49fe61c89e3d0f54d43d7a9c5dfed50223859d21e5e0c1c958042262571b852f0145a0b496ab15f35f070a60b3ad81912c6bfad5525d38634783bc0728dd9da651d2351a09940424970bfab71c1bc0d29be92e35e2e641774466d63b0664f873ce04a7133e20ce1bb2c798c785f969318368d8e58c242cdb9aaae076c90ff947a226ce1b4a663467e4c0574603e041851d03bfa1049e9662e8c5464fa622b044dd4caa4c37014326c44f9a18f0d248d1fec603fda143b55e224a8769843ec24176b70ee61ec0bd6c5758b9725fc1a8870408f76c08f44ede6ff53c9a5c210355627019ac222c2306a1ef0226140555a44e443578b6b5cd759e0c33fe7b0e5c12d8e6448c5733c7193bb86fe7f56412e4a213757c3a8930190e6c44da47ff3e8fe62150f2a325fdd976251f4fd6e608a51f722a60311a8d99e3ce4cdda53dd3eff81228aee821edd3cd466ca27810536c06a917727c30820bac4a16c70b396be2e508f97adc1ff2bb0a530a3e0544c7dc056b693ed188d1bb3b8a375f761060cdf2654de6afd9527baa071af5f47cc3ad3ea987b3afbad02c8ed5769c4d8743659767568886eebb161a91863d6ebef2155f1916e1ec42f55a1f3f25bd3de90b034f37e1fc6f5ec16bec371f5e2d3c8eaf707507c797c6fa2323de44384f823c250a754162d1b791fdca661f7e45a3420ec45cb9a05c57e4d5616123914d1dd6d062497ab70698205163ce06439e65cd5e03da486f107edb3237fec5b4712f1b2cd3aeff57f6064eaee3d35442a5a0c5d2660a5d47fc6d8a6fec002a317ff56e9d0592f53a799dd4aa4e467d5cdacf5e5f66d040374870cc2bc710b63530e931dcf414f200e8d5d88b7be159f40a3042236e81d47e3ec3e317b88b2eceb523ce7f0fb669c855e51b1909ef46e68b3ff2dee4ff3909daee29dd53ce187e3ecf2663d33f5ac5e981d66c1e7d94d896efaa14c9d8c03fe88d7e32175bb60b5d0008f7ddab3d0f77f5f880b6f8db90a1838cc66d156ba2a3d7c83ff72f5a64ed268c3c28e9f498d26c61a2cc51baaaf4ec56e8f0ca16e6d911422a3560f7b5553e42f7901fcf603ddb6712f750f420af0545978863c7159a66f395026609d6df3c2973ba1b32da63b53d1756f14ae0354b294ae627ec3de6b790ee0127bda56744e41e89afb9d30c1fa9e250b5b24a7c1b90fa3a00606d51425e27dd9b8ee08eac12a9d1fa31363dcc1ce1dd54882c941ce1137b5a41fcda7011b215b144cfee922a882ce0d782d3e05eaabb3d7d33097f7cb11aea0f12008a6f4759f47919c352a0aa0a3d5724eae2bbf5c941c847b9e40f0654261d14c498de62a3a7189d9ea5d9e014f352d2e8877fec74be0a4d21db216fc12948b70dbbd0c07348dac8273e3460d4e59f1de77026ecf01cf32f5416f41be9a5bfe0a5f3027ffe7797060f690d616aac287814a8023412b990796d3c2f6dd397318c7e746f7f1ccca6ca675555887d26365662395d4bdbbd32357db0e20c5ebd12e1ab013a1bf5c5d8ec8bf59182bf15261f7f3d2b5a41404f628db3d144b27d6efab3b6d829ea565ad4ce6113b0dfad2219891034c42a6874abc6a534d6a2657fc839bc5f454f8f33b364bce52c8dba53338a6363e046960cb02b782e6fdf2b5206ad3b54c990abfb7ddf62e8da1f79d164d7b10fd9a16e208c916780aa16278ad3bad8d99946d888c90beec1c319dd16e92d38c91f995d2d2e832cd671328ba7529196a54d4224e8273c8e71d894891143d63e90605cd77482bd4c3c830c2bd63f5725bcf848fb34c542d18813e4a19e04cd081dbe7096b1ffef558bf047c57fb40786df53e3572bcfd5b8d95463e72c996304d4130d8858f84426a09ba29a95c4598e9eddd5e0c258ec8a2a2f858be636ad7d24474eab4ee833b877e18c64a332c71cc5c2d08e51224cc868f71f39829b05a64d9cd57caadd4333663d400612450ab272e6df41f1ebd04f90e13a9dabae015dd2bd290d327b40a96e8448e95b16525fdc3f4b0afa81e3f9b13ee190900992676c2b54c92c0734acfc5c595f2e713f34f1c5e11f926a8d60d4ad1f54447636f5eeefc6d2622a6df2905af34b10574d021063e1c8bab39af5fa94ab65627ee3f1f95a7765e1d90a6a25779de554e622f2057e3b67aee56565107378c7015d171a61c2f8b79b8a05df81ce7f154568944680da8b563e9b4ef41a48f482bae50dae77a4b42f1b84f4749e90b05270452a4b4d0defc4d725973704f28e29bb1a77985bb0312e270136ad11157faaba3fd9923dfa5090d1203e9773404e22b6152b45a1ac5c12b1e0c3d5488fc1214d7bfcf156d43c4af7180d6f76eb53697eda2501f862d95f15848e3c359cae27f44e7078a2fe7f339dd3170793597ae170593af7f3571e5b49bc1dc3501b739bb0af23cb22bcbe01ef78bbcdfeaaa8951093d1e74ed8c8d5bf91723421572e76297c04f20909eae9ba21a306e55a4f49bb241c5da09bb43606b06bac862704500915280f7873d4bc15ef2875285224befbc93d0f400bf5bc9ed94a53ef4b248d6c6f274d63e607426c609259ebe03c54fe2551d5b3f3165662ac70680bc230ab66d8173b40b94589f16899833cb83d440829ef88a99b74ffeb4212a99d7a297476fe4fc8e8d2697f43faadaa61058aff42986594bceaaa963e5dbc9fa535b635e7cd836661abd4e4c16125545f7ea7367872f986f92e67895c4cc4e4a5e57bec0268c18804088a2cf84b9a669151bd8f9f663ad8b85ca03cf79f8d4db4b4f75b824c967b13626f0abff39c989c8c044604d93bb4d392b87f0232706a74e374e81b35d6c3f4ca1e21086c21f31bcec94f14326bb1134ee2c72bcb195fe6fcc61a90fec7b829e078bdd61e80bbd57d2e81b840d26f3f61c6dcda7d13797bc339854d41961d9cb1790eb4572ab894b14b93dec99d62932d54453a0374fcb3b017581479ab29c7d052c92187896386c7e290ee5dccac4fa3fd391095b8f29de00252e69f1606f6cdac04c17c12e54e21b56c3e4cc8d66f373e44f9f00a2a13a92d9a91970895934d2a91716c51c0e3073c80080b99024d6443f545ef68e9a37ff4d05dd557526598f6c7106c246e6b4c22046c66c931b710166ef6abde39c29e883989068c6e687d212fcee37aedd2166d40f351192c6900989aeac8cac1271c1f82423cb2d197b4e697c99f94abb41c4b5bfe684ab9e3ca06e0f4f50931d43588816dfaeaede6d0f6a390bdbb8cb7e2d97f47a1d1d5314eeba5df3fdefe26b3684065df6841c756e1635e7c5f0f2529ff852cdb3cdc12ac4d0a71042fafb15f3a6b8ef6e0bbc761014cd801f427f4168c12d0693068b8d62cb052f6ffbd11abcf697f1020a843a13d8251047603ed306d54e3bdb319f0fb2e29a2a5870d890ea2cd3638abbe48827ba3ee01d3c0f952af109894b74b48d672df9fdd983e0125a74db692ddcaac15e58109f57ee390f2e3381d534d51a7289663873ccfed599fd98d3f9eaf8851f28af7c62debbe265d1d4067f73f30d90d819f24794b232311a2ef0c2ba42c5348e12b669e5e6840b6585ba023313ef2dc4de010aaf81318cbda3a30185fc8d1860d28bfd950308a30aa7d5d998440ab2a7aebd9cdd89b3c2e381dc3703e1e75e9553524807f5cc6ba7cdf43cd64ca571194dbfc43d912b8fcd47326094ba5ba31640dbc076edf6d139d4e03ece97f7ebecd3aee2999b2462eb67e459e9968fbbc5cd2475cb5998bd97dfa17402cdb7ce15801ad66da08ccb6ddc2c016a97f0c3f00ea018252b7c2aed9394b69b079431d2ee5081a3347d25c82d2244785bcaf4e5b7240b9edc4ad0f9ad18987da37d455a210b63cc19653f454dd23dc99d2f9cf4487c4b4fe47588613ab20e8d4eebff9fc466782da72daa431c0432c6bea58180759e38fc46e66800bd6d303565566e500070e8bfb8c26b1f13ca01a0ce4b3956944282f27e35a30195ca89272c502c6c8f4da205cd849d81f12ef1d6107c3a7cab7574ec5075b181b90e7dfb709e0a10dcf6bb9e8f31d8d9398f7cc067c35577ba3da1fd7cfe030f140074dbfb4f7c5c8b6e63467588225f6cd0a460795d71d0b2f1525454567bf3d88d3630e9b0f39526dfe4412e803189e6205d7c200eb4400366faa1846b2e3b170f05c948ca5c20aad51e51fbdcd25ef3642fabad84055a46af0d1519b484576beece37d13ed299ba34963394f80b9852909eb9a1fc23fd206e90e73fe6f43c0c1cfb8ae471c7bd9229326334145ee77204f6b1105b6bea5d196a1cd931dd0832043b474317af2c68beff18c393c6577212ac6555bd7cfe4a5a51dfc03ac16751ee873316c12519afacc7ef609e00d6acd46ca9d38db237da93dbdbf3af9298624702b1750d05aad1a6e2292285fb6a5bbb0004de50b0af005fcc10e4c699c073662e449f318c9f023b8be3cfa17e0790cb92337ba110b4f92c5f3ff668ffb01bab361d051d73543d435bf0a2c07628e1ba789fe0f317b45208ae5b8b36eb8723c4c68e176c4480bd7b8881ebdd501e754e2b3a84eda263d6cbd9d5cd7e0a05a7834934f189af6828841315041a45084c7a54fac2d1dde0491e228bb227597096ab3e41d645bee200ace5e6cc4f1c532498150c22f76b6b04c4b8d26dc68c535c8dc241d6a5ef32a1f7e1eea7c348fec392c96eb626da3b4b7a5c955b41e3f0c8b11fc4318f02deb7a4a821addd8d980c095e64026e05c91d98d5dddd869eb379993f163d544edb2ee6541a163aa0cb7f02fd346b0884c3538707d1832b3f5e26a5b7fc4e8534005e38522b885d33ca1f8c7b5ce41deb02395d01a9866ec590ca9233280c01a9707793848cc987c9e6cae00f4b0989affcfa85e4381bbfe6079c57ed25d4d6cf78c13e1c159186e00758ded309e35d8a161707782313be0b129ab7f85208cada006ec4c40e38f930eb932c1f870d2bc7eaf27d5a859ac3694b5b0316daed6e3571debf63cc5e366d6509d9435910941f111d1b99b71f8a482b9421b9528b18b4cbf23823f392d1b0710b91eae81b31dd1f0bf82253c4f9d5d61e3ac0a78a57dfd39c5f5fa687ae133e8d8032bc6b3e5a01f83cf63a0130665dd62c31af18b75b20445f5c8d83d4edbf5afc9011981ec725f149cfebec6c5014a13d17b8959dbe3ba947f9804ffb8ef69ff719766c03386db0b9c419e059f85670ffb1b8ed0a28d44a5e8afda8778f9db7093843db4872ea0e61c845d99ea71ce9b279ef6bbaa3b6546b2b840b57ea5567e56147a1249f946d51b3bbeee9225448231af35ab4f29113de97ab32771271700cfdda5118d59fcfe58a1e0ec33713a30c6db93f0c8b2fa196096dfb4cff334e6066d13896c9fd268ae439ef83555bc0d02d3f12501e810f6b02bfa23b62e7aaf88ffc1433c112c37839baca3539edd3fcb6e779d8e9edd691a544e0f1c304f00f6efdd1b3703db56f91216f12c34e9f8177ae4f2745368c6f7928b4a30f403de53e8b48ba7806aa807b376570efcfdde22142b9b5e7a74fe907e1fb857ae08baddf3624723465b9416036bd0ee55511ffaa3cfb840d8f86808c935de869f2ab5153b9332e0b2965aef0fbda21fcaf3f65127c2cd2d8c5155227417fa2c4362c1631adcd7a0ce05ed8ee93939abac36e4ae87c0cafb30d40a36e27c9772aa5e81c8c639d44c0b2daab54b28134f55fc3baf2401470c0faf31811460de349e6e162f43d6bc3c49f0b4e6c40a215f42e77450b207f2b9e5ab237e6262ce9b8bcb7dd3fdcf19c6c515afe6a14bc811f464c4735c8b16c539bfb123b03280aab548bd0f7eb64238037eac0c101f21833d57eb0ad69b6641cb1363c20125d2417731d8a5de269e7387f7480adc3f1590224f54f7628f682087a06bbddd9175bc6d13bb02a54549d08b241fe93c5a823de37f7044a57a2e9b1f8e3fb291d19a60bdd22fecd66d844ea8ceb1c84e924415b25b0ac80a312e806d1d513f43af5c44947a5a4b8db71eea0cb4abb8429594c0c7792b2cf603cbf5455312394567ce0b64cbbc589490f290a0d17b2e44013d808bd6408a7fa269c30d94aa84d48a8dabd6692752b77ed84448ff33dc87b38d7b1329d608208e7cfdd43bd7035c6feddea75b5c1d0ee038e845048a29f736ba519d281a71a3cba82d89b265298f750dc35b4721574bc043eaa186fb0d91be71143b73632f2f7ca1173010cd588fc0166419d709acf62820719b4051802b284769f0b9b39bed51f0153682d05f094c8044f93d2a235a038ce8731cc50a78371673a8204365d1703de8c99e9ea598122957bcb3b05de9385da23b23511ed99ec6ca39d174ae8c4abb020b598426168bf76845c0b3d7aacece894197aeb1314bc9ab2025aa29cc15b97e7d023ebc05cdcb64e1e3a594044520b8a9d8690820d26426567cceebc6ec638606c8c9e78cbb506ce089d9078fa44b20392cbedc3eb0aeac5c7426295621236e0f7f8307693cad89e7f75651bad37fecaf366d96fabe1f4682ef30fc2f8fac6a809f82d79dcc4f11e7fe2003574db645acbfcdf20d2012d119a09fc83c810f69a704cb9824e6d54d0509078238f8f9d227e2a8ea73ad17f447f49d8fa1841441930f1ac53310c2ee574e47bb7a1cd554eb391588e6a4fab6c5442ba6e6449f6f81886fd5e06896d313a288e1845dd30fdb15b15f41886171007668aa18365423770880bbfb1e9a1fa7ae024e08eb5390635383b683dbbb63a59117adf19daa3081a728cc857bc710998ade2f900965bfc121faeb3a7579991d71949a1c2a62b311d3a99e7f6f5dd28d732d138e60fe0c3b1658a4c0babd594b1f729e065c02c4cf1c06c27d05801cf52477c8737ffde89df79410c3d3785075852eb277c3735725c48ce447fdea471725f1cb63554f4acd1b395b412f011ee1e1208cbf119f86edfbecb1d7a10a00584003e680971f6d621f9987ae393f55d9e26b5b7bb0abcc9629e795d886c3327d6b93495644669d323a1176c500b4695bc01ef55d7e2c2a1e3f8f1f717a37cc289011016c03c75814777f4e30079698630fcd8ced9902ffcb1d7681f2a9d2086e30f425f926fa91e66a53546e5c4cacd87ef913d482d7f70959bf00698b7134ee3073846f195a7dec1886eba97db07c3bc1797624920957db8c8bc391fa228bf601773b6dbac1b8e3d31f38ed14d53cdfd950d6778d6bdc81ae0c61d6509c022f909fa018f7aca990523bb533bca6c26a8f10c2a250aa02ab7cdd74c1dc6ef0a4efedc0990e71c6c98693c80f04795d0e093a0e94aebfc2a821eaf0fd4152f1900069754f6446a9bfda2c1c7658bb7af40b0db2ea741b8884c9f1dc01206dc129af37399f098b511f57fbcebc8f18c87b160c73c0417de673f7b58e34b8fe15883bfe09e8751b34efb8c1006192f83d7994083cc8c555912566459fd4acb1fb333555046c3da1befe371888647ced59cdbe1313890c4408a3940614318abe372cadcf801d2ad234dea467a202b31c261575cde518ba314f7a99177eca716c404bb4fb8bc6a327cca5222f0332a6fae46bc3cd68daf1b172457a4b14378ca8c3f47b6f8af89bd1e61d86353500d8958b1148e62c46a1d9c41f48595f291cce21884482ac5cb112a54be29930d4d2b9de0878b6cf4e624ced31fcd9d5fb8504ebbb07c8af2102e3896ea42722e5d64a2ff50c5a8376ea7a0e5b15e54d3e0b0dfabd97c4480b03e0f0ed4e5faf8a776a195dbce57a43e4b1db681792104ce531e2310242cacd2eae6223d33b5f5c1a3144fc4481e2e227fb3fb9ea2b97c0e5c043a2374e0b0806b1654ef8e81ffa416b0084f904723902ccd8a705c779df68ea91372e03f64bd290399dd8453865a635c3879c1de1ece485e3c4bcbf5b6bd475ffd2308ce1d648bb5b6aba36ac62f90c71d22b9e4e04cbc6324530e8a53fad86a92aab39d554026e8cc76e189973de052855753917e586e3047803013ccc0538bab9f0facd224ea207a6e1d522da12a7f5da1233ead459a345c892a559dc5076f26b3fbcc369f664b6a11f73b159360c4c7e8d02e1fa5a8d2f4761165c8a021354e28c601afb19bed2f600fd0f0d014a0ba04fe86bab302e94b347c9d1def0e9c4d1e7ca5d144d5aaa8e22ff4183f06a50da016112c3737814b30d45ac23545ef5b319aa31551a4d01adf24f82c21a50509983bf31272dd9e54e3ff32bedf7773bc87fcece535c75ea135635ef1f6475f3427886da08f825997bc00466e5660593896d029ffd6c16d24dc9b3958696801c9204c3f62b4fe4f00af3ba261c467ca666851d83342b808a462afeda48aeff3f6434935f6ec8f3f7b460f9dabeef003941acd413ea9692f9faafd29fc93c760e7b8786c96f7dc55207cfb2c662c15bdf1f5291f9f28d7e45bf7dbae9200725cdc4bfc22caadbd61ca03bd74a5fd44d22c0ef530c52ccd7542f387d9b816bbcda469375de20685678846df4794723b68fb00837722558f55f7688892ce207a5f5d09df5b84c295534a14824999c8e6c81aaea9f21d68f93447c86a245059db95a2aab7949079ef5d4cce92cd344705465217aa71a2dbf6f878c4046013c9ca96d4d46694b03ec9775e1a2b4e9e156400ebab2cb4eaaca71a25fc86612d4efca02af7d9fd0a8b709ed34498cdfd985e30bd7b35f583e941d48c696cc595fd76c57afc18002b81332445c5b3cdd09fb6b9c65d8d7f7a3fb9f04e56de666df4b532151df88feff2b46ddfabb640eff97158b4752c5d793c6cbef832796e7e509078eda84b6b70b74f20212249c016769e5f9744b1f7d327640cb03607da770dae5d4ef69a11d419bb1049b3f1e19b631f666922cdeee74ff34bd3a210ef1292b71bd8c1867db474e1849767ddfde69f4c8e87785d211e85b96f583078116ab9245194fc256bfff194197a273211aedd36a152d586a943e59fbb8d1651a1005ca62187a5fc591d23d3ec1f769726e843b4d12b3e57ba983028d8fd003fc42cd64393281424022c0e90e3971273d7770fc15d72c8dcbae9c9cc24760bf6acde1c6d41d1e30b4f622a372e990645e05c1b89cd98b4ca750f505afa4d8401bfa9b4cc805aed7429bf1820300ae3978d8789f49a2d206daa98393f1167175d360e63e3d63fa7cd4ce344852e8eaf23dffc8ec4e36158079819ac6a3f382b0329512f5868fd3230961d40103b742f99b5156a8ec498595a858c353a3f05418c59ca184c1fa0883def69a4e24d98b3e61ace85b4b727091ed16c2c54d363370c33c840ed91ffae4c3c916597eb7741e33744a4066fec3661d0ee10d83b100f431215250b9e56bda516d5657fa727ce19dc16d01b4b369a56312ea5071a5942b3316f4e0634cd39ef2ca08b52e02b3e76f6d40b023860ded49a48dcdec80fd3049c45d41506ed08aa16dc37bc132cf87d152151f9b115a64be8287cf38ca843bf6404bd5f39aaba23a75ad8384d14a013f412f6828e01c9aef3b8ed6ba618ce669849fb89274d248a6e7d58cf1cd1f5e43ba5453fee8251cdcca779174c5b8674a215ee5ab92a695b48dce65d58fd06bcf5a388915532a554b015ee8bac623ea6a538389d466ddafa0523d43c74e7b85316cfe8a5873fcfa624462191acfbd361e551b5e7418121e9d8eef19112ffeb56ad5c7ea073ba26227140da02b035d37bc9659a682cd18d5d8b6b2a7a512c8dae9c559cd7514f185d618457ec2eb2324a6e28bb0a64442f185fe131002742a16c5abe28921927ad5f515bbec10ea5474e8d74d992432be2b3cfa48183af3e2d8a8b312dd8bfa68eb72cb460383329dfc346f21edc9e0c202433666a33be1b8611f10c5eccf589809c16746d570273cc5e75d294abbfc5d404b0ba5a715de665ea5b57516c6429c22bd539bf7b923f0a9e5d318f1d8886aad715a6fc4aa22c42a05117e4fbb339d2f09722f91a9377575ddf1615bedd220461f153c486e6eecccb8d315cc18f49e5e76d75ca3c08ca17f68b4cf1b3f96e97e401603fcc369eb121aaba5f5d44a432d669f99ea4e77f611095e6fbde2b88533a115dc7ed851fd4ec86067602c7422e9883c43117b5049e93eb2f5d36ada167203a416b831b08e3bb758a88d0c012924d5b4ddcd528c66f1016526a3e3e31900e6e51d6bdec49fb3f53954a7cb4dcfb2e7bc2f8ad8e156c9c05fcb6dcd36387bf5832c9be24e92437de8a3f9300d5a2132014e54684d468edb3afbdca932c124d02672df381af23726a5cd9f634fe33c9bf7c0afd3eba82c0e5784f81f3f12953f5e5087f2f0e69b87a2cf2d74bbf25c3d7ecafb7ca8eb11b3259fb5a588b7c9a03d19977128be2e15da3ac3d32cce234f155a5774d2615a35097cd11dcd1d0c29f2a356d5eab394150cdb83a1d31db3ce88dd0759d22584940146dc4f4f8d69364a814a4d44993b932dae19cdf8c447915bf6dc647f87fed40b188016c6713b8b84500e20b4ae5bd0088de5337c47e9bd0da94ba2da72b9beb83c70470cc54caaf33584965b8c6dcdda5b2a6e2a8598703f8a6db7f057759f3a780c9c5488eeca96304608979b8c618d81e278474c6b57c80b2430e26dfd6303c0f89a0db9056606e28c63ec6b214877c6b808e3f0a576026bf30d3cea3d9ba37a62f9ed557bf6a3f16c035861975bdffe788512c85422447b7ada1c8f9fd92bba5c6b35019502dbf963c16723c6875944c3b256a6b6eaf48d98d981994ae0b055109e5ef9384cc9a62d1f651a166cecb5e62da48415ac5b4c56743cb2c116ef967b6ecb8f784bb3832229b3fc5ec0a5ea1ee60e4262b690b8f704de30a08657e5c20b46e85c26fa13f7dc91667e80fa1f5951dbe6ecd3e4400b27654e428e8bd9e108bc4051eb3c16bcb2f243e89f00c9e663c731538132c3259d065222b7aa9291ab4dc4993611784cab7466b4ec2ca4aeb9142eb9b2748bf4b94d9b8a498c3837c3f08632cafee3ca73bd0473229778512991315333e410d08e9b761a4753c9e64da7cbc366caf64afab2fae8b10ef937d1d63b7a01026f54ff116dfeed29ca0cb6241b4fd37ca7a5e3b5ff95836a0855ed975302078ee3e56bc2be962c3356478dfcb740b9352b795faf8205b8231ecaf2a771734625f6eb81da422294ea529572da0f1448c6c112da25d0ffc6d980268b52d331364ebce1a3df281e26bc867a5322c5b794563d32153af72b6772dba80f2b178eb01e9492a62aa88329ef97b8c5bd6b144e06fe5711a6dd4466beb94cb0a378f6a24fc10601afe283cfec2f9ff3cace662a0aec386ef59e40489ffb3dacc8be78dc2e3735bbbadf01879f5a3ab60ddb9b3c48b81e8a9d398e2dbb8e76a7b339d9b53711552795a67ee0c9ad226c2efd34d15661ec5c95242a5535c166b924d912facbbae8a44a4c4286b7fef716d4016faf6085efa985d2a578c8e41950abb8f9fdcbfbb028c29863c9b4b0c57be6a0ffa743e65de9f434abb55341a8fa226c97fc1479aa122aaf85d1ff271a9ea28188a9d90b322a71c5e4c8c0b46d2a8059100a87e37d4b37415b25f29e57e81c7425165d36baaee0c2b90bcfbff790123abc0167e7abd1d0380bfabe48a0e2083991a5e5097554e561352ea0e7046f94599af8c95646297dc5530789311a0af2cece1b0709fdf6b404d6b56550d3d93d10f5c64b9811115920414b141567f06dc8f6d6f95c3a3dfadcc07986f3aed125c66b3628fbed64526a78c85954afe8d811622c70db4db7a21b23542cc302fd2e586f9bfc913539d376faf5dce7a86b3d4a15ce01694c717b8deabec71d9ad38e55bee9ebd8c9b975906a3904784d2f3dd62de5aedc26895bf61f4eba0c188f2a0f691f74ddd09fd9db0e3f7296dfb418adcf45424eb5e8690427ec9113a77c0637c40f8fe505e779fd7954f5bd3b981104db253624330a126919de1e791d3f444db5b92fcd1de094f74c51ef6ff9312973c1967190301fc86248c9bfff172e43c2062674d72f2816835d39b0fe05a99553a8c9d72867d69ecbb87c2e86a758bafd5fa439059c756cc4fb8465c2a753dbd66497cf7e1d1835e28188ed1582e8b581372ff7a0e22360b8a9ee1c1ae394a8f20aca07ac1703dec5c5c3a2377148970a03758edf5fa6716239f3b65c7b6462eb2ad2fabb78d992e5ee25e55beb01b3cc1b0a70f5a2e007b7dacd749732ba0d025dab4420ae2be7964fb1a8306588ec080a5fc43b841dce240b1251fc5a7348f01aa79d8a231ef5360e51bdbf3715696cbab58f3033560b9b9a265cda25677a3d923b0bbbebc32c80b31cad881fecc586d3d9979ca653304c7d2b80a21fee63b44e05e944e756d28648a1b28ee393d6c532bb7e1cccb3bc75f6c4fe3f667d34016acae4e5d9fe61b161cf167dfef805421570a97fa6a4235688fd74d1bcdd944350baac2106120887d1b7ade7dc7f35d8a423f2353e6fbf7f4a67d9f41c4904f710e2c88bf0409c783b30d5c128611dc3c0efd113f38f44adbd238d1c8d99c131de921e1d136b158bc8e3d8555d72f86e047bc4509f4230f947148e0845c754eb13c997c9cca79620c6978f329951b9d857ecffe2e208af911a694de17764cd1a5f15bb133020c248c0c49d88dc809c72daf96dc4afb88511a000794d5f7b36d9ec935709f3079cee199bec64d7ebd690a27ff9978751cec0171ae1c116643a246d682b693ce5044d16e70907dc9fc7c931342acf3af3143b83a38b8a5249b563889d8e58279b7ee0420f6543d34f804f51cb769d952e816be1bf07435fbe2d11f5c8448dfb8edc65720ebfc75186e121388a24dcbf18fb8f408ff6f2d99fe9dc8eaed7366d87251a2db5b74e2459c095ee59509ff8f05aac006fbcd7fa8ff9fc89a7b1a6ac34d964522f542b8f7c806e47b02bcec49b94a331665c4680d0251f73303d76bad03454365b7fc21f284042de97c6a43355064fe374347b080c023944144a62fb869feceeaa779521cb764ba540596d6c8af484e67d12dd4788b39dd9a27d849522b97e41848445534264b1b31aeea30703ec770515945ef7bcd395b6366c7d60a6af00e91eb84141df22af882f4ef474933fa5803b3a0898aca9c2741328aa91a0855349b681b5e70232c3f24a337b5888a42311ebd2962be33e8f07cc208552bc551e4ef55959c14297c7c28c6fe2539ea24556755d29cc039534a4aa3065c4e06aea5408605788c34e139c194d3383d55b571b983bf7958b958d27862c668b2d7adfbee4a0944bcd8f8af951277524500cfb141d2af8249afe06cd1dbeb15da50b7716e5311f24b9627debfc67d032b933682bee1f6dc957aada699f753cee7a7d4f81212bf5b5173710c1993bf83a0f2968d9518738054fca09a38f3f320a9bc6ab21bf1360d2f84ca267bd845079c99bcd2982df47e9b36cacd7e14219e6776556bd16eaec6382b3e21b02bdd5fdbbe1e8127b9e9b124f345d6a0522d87ed4366e0fc6ba04575dbca514e2ec0d07a47b8d253ea49d10e6bf6d6865184ce6148175f12113821bfef367f40e4c63a4f33f951bc95eb9a10e9ccdd5d93007deff6febf4c02de66fc9da1db383c2e358c1d6ed0649a75dc66334f382473e3ea838f73b9cac3e8b28a1e5e664ae8a1c2422577a8c8ceb12f55b13fec6f6cfb72b12ff9cede227da44bf252b6661b06af742253ef3ace5b412ce711eba54a8a56e7ddd9c824cd6fd49e1f9ee78eac73cadc04bca2e96a8f227df011e6c0e45b76e4761797c1b224546ea26b3c8a6c0454d580fb16f285721145aa92b1dfe648ec247555ef591ac001d05342bad75954d1fdddc9a03d0b5874941ced1135eba8ed480b2f51d6a6171ad08b189790fd45955a574a9096757978af35c67b878fc8b1d7381fb910e7a769b07277199ed513144a84373591d7be7e174deead26d73eec700d658da17ca7356ca571712d0b38804091ca03c0f85a77c8ad0e5bfb2e64e58975dd374c01121cb15eee66ea08170db3f0c6a437bbe0eaab0e3fd0d9f0093c8165c8a0efc0429a0151720d7afbfb5dcd88e3fd72461e6ab5e8533bd44d61a8b0413b8044b34d00102eff6aa1f5bd42e3276d3e247624a2fc37408bbfa58a65de5f0c6a2203d7fe88e586504fb4b431d3e413cf9e5bbbdfb86bc07cf132bbb31fe98b2539ba9a0f818c3e1805f14a29589943738bf4592fd8ea456f142ed9d03dfa5e9137bd608929be029b98015b45c6042fe7e8ff45cb1e884e3232efb3fee1ecd4861f8e3a814fc14508076fd87d261db7991a9c6fd7cf715127cbe9cb19849db0617e000e80951daa6647820bfa966052a377148d9ceeb71384d926f8814287fe310e461d9807633f38489cbb34384a7c70b8652a95efc8e432315e4bf5d09639703777c9865dcaf9b8d3b7f6b9683b1d029929122f4d3ca8c6124600dfa3c0d9e91e5f038d39a4730f1eac0be64b49af725c44cc917a2b08b75e0313208c1285312a74fb07b4f304ec06b3156cf26c52f46b0c24f027dc56c8bcb6ba5341cd59a95eabbe638258eb798644f6c66a5f8009034bd4469aae1bb43cd81422aa686987ea9337ee330545587febcd6ec299ed5b5c1ca8e21d2177ee9295249528645dd242bbf583a6e8a7fdba240e649a29737e00eb36949e5e6bf4490a2e6a6adef16f4aaa7fabe38b297659d6b193486a5037b4c597a835c31c0cdc5ca973d6ae86d7df6cabd93fb46827c5255cf07c80e8dcb09418c6b8285a7dfbf7472b00ff5ba5158083b1b2469f7d39987de3647c480c8e79618f35aeb17a135545dc660f94389f7dd73293fe29047c7d3ba3804bcc60dfda51485336c73747445f17035cf4ec677844a18968004ab58ce0c8a5c8b713f107705179c3cd12c2948695230e0cf90b03a7cc073d17079693d26a01d46a2c25c96a1f64574da8f73696413fb8d27e5f4e045304d2ffa32ab9e7cfe57dfddd66d65e2198964956b2a8ffb43f24cb6802f0ac37fa11a819c8eb843e890272604b7ba1795fda45ee4206b22b58bbc35a3eb564607eb3a262d7f2ebe472116bb6c6a88ecd89e33e0548a33e12d1790ee6a43fc458f1b4e5986bedb72c619bd54b3e78c4e085171acb097356ec3c5656a50acfa138dc0193605e2728667ea137db6ae50ea8964b93de343ddf150775211c2c5740566072885b3ddbf751c04746d2025b8aa50d194889585a515cd0ed70135554e8a7bb59221fde3c8ba5f1e3d10465b8e26d9f3de4483744f92bed5319ada5be0a91135106f950345230595274447bca5c6c62f3fbd5f423dc3f3502b832ed7daba57715624f46208eaf40e69e488f7d8c6cddcfa93ac4b3610ed6e0bb680af49b9c3eddb87bd03f374d56f034e5fca4cb0bd9ec0649f4fd7b494b2acf24923b64bc83721538e0b68a7d657750694dbe52b9b571b8fdfa11daf47b24d1c8bfb78d52921be1ff656449b604ac548c01fee00277939b3ecd44868fed444551f9e28b71e450557632fd979a901d66a5db9e0adb126cbf206989e70514fdeb518bd7d15f32e5909db5c73144fd6cbe11a4ac3a21a767eeeba5f8bd624bd5dc41c20922561711528a72ca39157ce817542dab520e6c1ab7a3a903c626466317fa93dfcfa828a20eef247f72d17189c4183a83dae93f7a839455da479440b08a83faad3ed4f1ab2e3b45a79e8481bebed99172fca1083bb76b598945a5106a80e76ad79bf2c3bc4a368561a1fa7ebd09b53037008706c9c740eed9787799a3f88cf25bc1a81afe1ed7734edd6acea03a917cc0a02c0aefd5fee8273004917ffecbb47b1e28c27334f534ff669ab6d7f956fed1300c68c250e325324c5a81df8cdba47202aa4d25f59c290daa20564494a6d475f4992e493711104bfe5ac8791802b6ba560c25ceca4b3c378b089dd3e21ff71376241383be372f01a9c1936d3407c32175c6eac526b1e008f59386ef4a5fc585bff7bdf8d51ebcf071589d123808838ac2a71b5ac365dd0a46842dc2c814fb00d9666b219b232312a0d86154fa62bb0a178cf8c47a45545a2cfc9f44f89f4375252f02907e73f46ecedf636ba44d6b892ecd3ff746ed81e4ccd73c4bfed5ba2777a53856bc783125f65a982528690298a245de69e1081dfb43937ad5da1b6d88b54ba87811c80b19ef8dd833ef7bd87c67e7c3e757d227464db57d0d0103951089777087bc15ff44f080f23777c3a4f954172c789e7591314f52c9965cccc978727cf6153c4511a7284541571966f28cb5bb974b47cae8666783307ec7657faef44a013860ab3f6b9e7268833762830e54a2d87fc1b505d0b70de50af75c58eaf7962b5919681c6cf7727c4f4331846c3700b9f13ec26454c885bdb9e409f2c1941cb62953f3f19c4c138d5e3bfadc2a6dd106aae8dd2ebab6734663da1791773dd98985a987090af9cb5d343212be5b243e1373429bde973feb3aefe1014054897a678bc746e8d1368d994e34052da59d1c99014cbbde9af8344ca0e701c6e9987c0b34022d4d6ea1be4f2c9b79480685cf77e1c09493f4010e43eb003092e1bcae5be1ff2099f18bdc55e92002a5b14ec1917140b06923c36d6e8675ab85ae9d2add448390a2677a4ddb7dacece747243042087d96021c87993b81188c419e1d00161c9952395d39b5c03c136df4f20857be291f2b84a79549603d3ba55e47e0a8ffb1dea554a1a81194f0f7f40765ac006c0713238a28fe24983d27f43e4fa7d2505b2ce035cde62ab4dcde6be1e0486d5b7516e4562909f8a4371cfb48e019a27a83f30b79971740c0f578af6c8aa174f9b4eaed4584cca652374c1d146664b155a449723ff60e0efdd1ce21a94d1f9e1e197bec5e9fa7073f95d145830721c1ed68447a690d3b156f4c27fc6e3a621fab1792bf7ab7d9be930881926ba045f2ab0da9b5b20f13aa067f2033e9fdbb7a7ebfbaa75e741bdad36e8c776b692c9642c6eaa3436d3c2aac4fc8497aecd748ab126109d2aea323092c63a2160ffaac5f1678224a42e1255b970e34ede62d428ed4b7d9f94863ea9f492e55ee083cf7a975698748d7f067ab1432f64ca1d14f95db6d75f62d20b2405d7691202a0d0fbecb9bdc62edc254c11c11e88eacb4f02df328ed8a836c5aa9fb8e5032528b717e0689651b3eb3b317c17924ea0531d289a423331367be878a4696acd449dc55d93a8ad898f42b60e4eb4f08cbe4de41d9dfaf7aa10b232430f5c6137b64e739ece672ce00da76e7a774ae7006c32596bd3ba6c119c4777e2282bc2e7a189bb58f54dc02774af7d85f53d91e3da8833d119e2d9865ea230d40393d37a8230c515061e499f518e09a7b427fae4f2e57a33f31e13c02a14a123599f0fdc8c4b36f82fec1e559547d1a00d051bbb8912b96827078df8903f93b1afe3b890283417c86a273be4957dd4fd2c78d57cc15f377a7988e30a60584576a22d08e0e497aa7e0a98300276d266dcb0c3d1c5eafef58a4eb36e8ec138942eaff62ad191a8e4f3e3839a1f43108d41d760d8354343d48f6305bfafe82bc86d5a660e4ed1c3b70bfe8425862404d072b5aa9dfcdde3fd1179652381a9a2f361a376822c33b31d265cead343f2e98bf5425d98fcbe6e36c9c403a3ae54caac77f74f31a720dfa5ac25132af9aa9d9486fe89eb6b491cf0fcd1e3a03432c265d83788ba22b8cafd8d537ea209f966d8d3e663a91e718ad5f31ea8759b47d5dcc43855eb9f52e9f10ee055c481987ab0d6e39989f7b0aba300f5ea84056eda8740c2d433e3ebba39832fbf3aa94e4d55a6c25fbb181fd209a522602baf97396a4a60b0449526da0174cab1d7b41716bfd30c36ade319f27acca571aa8c64b2d3a32813706ca429eb19a926f319568a6705ee873c4ac719e164b0961318d61242bc0c526242cb7a82811c84bffe16b0264a1d4774e814d854de31067021965f58925d92a873ec6ba6e8a230e8e0b8ca71ced0de309c5fe354a7ad2fe8626ff19d0029f2c6e3d712a1b110e41f69c6bfd9bc76c298814007cf2abd226a9a56c096a3cea69b10d045bed14a336ffe7d88e094e489a8c3b5158e6e5465294d06e017acb385a9a3b30c140e34a40c938977e3f6e7e3dca9d974bd578d19b2f6ba6981b7cc4b353592363f257125c0869b79595c7a9b6fa52af1f3fee2f55d8c88a8c02d3c41c6518ca509875126a6f226a923fb52cbd88e1251f49d070defd77c6fea1a7d399b94c81a8ffd8ebf45ef7ad72f51e2bf3d8f844fb0ca7250139b43250636452cd386513840caa9e8f00793a94709ca111fac4c4c70bbcb0a1c97b9aaf7218e77ad64ce1eb88e732c3b9dfd4955fdabf7222207cb41912505e5c6a3542edc92441726ef0176c844f5412953f4e1d19991242ae4c50288de286fce11019ede3f08a43a5e94ff758d33eea695ae91713b825fc9c513cfa954ce01308d3f201b9a8d16e69c13a75ca502f8c52fb2d339d8ac12a7efe9b4432e675bdd6d9a9bd6c1317336fadcb18a77f766e07cf55ab3f73bf0395890f65c06b61f5b712d7cfde6b82908490b16bb315eda1aa45c089a81509691a689ec2de3328757ce2faa3c6eed094688bd471eb021d3c3bf0ecf6ad09fa3d72a377ab3d6f22b828bf20bfe48eb69aa484d65d33d4d4d35451d2c981a336326f263895db71a653fc0fcc1ed2507593f93fcae4a6d5a74a5c0d912892c803091eb9eac25e61d4ead34b61c0c862b3096c5bab6081e43a20b9a6ba4c6ce01953e3a7aca6114efe9063076cdee974ba15860df88f7e9dcd7199226bd6d948d5c823eb212d153ac622880614faa3a97cc250b04752fbc3a1aba2fc3e9b6f1700390cdd3a6573668bdff588a7776e88cbd717c58b6d4763db8b944b8b20e8b16a1e3651380e4af85e145b3968c8a04ee96ff072623a68b0b374ceb1f1909250c2806554bedd8c6a464ba7e6f3450a935cef1990c5e2300db4ec835b18e09a7d080cc47a6ee9f55d63eb6f5fae5b82dc43365bf771d949708e46850cd64d8ab993ae013b85e1096ddcce27b19344c52d733e4bed8f58d04f1f8f640d41490c0c5db809412c1b2b65019e5b9e662e268f1e01492babb2b8cc0fc64e66c4c7c706fbe2c3c63254471f65e6a56c732fd352c427d66b173d20d7ac547cb2fd38789c95d9b4509bc08d2e4d423f35bad89a673e9a68fcc4b9a31a5ab22f90b5587cbd1b73bf5139275a5ce850df0a0e9cf732ebf04795adf3bed09a0b36ec82d7773d8c9dfd10ef25247f3728ebb3b46fecb70485d89bccade2e548081403c1a205a238d16c97ea4e3512c9276be6f1bf3e3276b320afd11f5b411d4aa1da63c6390df62a8bda0de751e1e3aae5b2be621e58cac13624d0791c544a21aca46177d7f2dc8b6ba08840b90114a4f3941b509c4b05a005e65fa506e3d226f237d24708d62f806e7c0ffd259926d1f4e2be19081a11d743c586688620b26cade40eefd2a5f8c1372b7395533f83214b6a3241cded01a561effb9a28a236cfd73d98411c74ce4f70c8738f0f43e198b51c8cc3dc096aca357793d1eb418c7365a68f470e4abec8552074931716228c305b9ced2f0a6e108603eb792f084a21dbbbf4e6f03da9d7eaac13b0dafb8f3d1c8ede847c9d140d2a047e2c2d4a7dc5118916dab4557338f82f33890dd0ae92a39544a712b600ab08062262d4ecffa14082f2319a60d08fe0813b353d1d372fb1d4c82f41b5f8fb6b06c1afe00b54f33cc23b7b39d46cfb8d4d9239378f6d11e0e6169ee6aa445fe0ab5c0f2f98fe07d1cb6f9d09006d806b4c5dcb65c7f32611c44717b6be6a6a97905335f4cccaf31ac4de3719c25bc858d9276bc560b4a83a852a762275757543a9c054b3d7255b40b1261db8769ecb61487c03ac8d1292590448a2633fa83fff3e32466e7b57c763f816f5bc88313a12e48dc2daef2fe13654d385d1674766e8ca69c61b0fc68a838a52cfaf4db74c5db516c876297d0c7ac955b0b7acfbf75aa2f43958e1de9b4ffcce5e7e94e397f4ff6e655273d9d9d6404f3cf170fcba18cc7d7e61dfa955e0cc57ea2ae6f517d0cf3867279a6b0d6e01d2ce1cbec31b420f9c5568945fe48ecf0c8be7f2055e5dce0dcf59aa4536fe0f85c492345ed7acaf7f072136d621f5d6f69c0d6ebb6fcd753fda6529c621d1dc2af7cda5c4ea8c51885fa2f0175c41e02299ca8e3299d49e9590b0be38cefb0e445dfae045a57c864062fcc66e06358304085f562702402a6ed0b5809beaa5dd49ee2ec93d41bd70bcd7cab841bbee3348c0267ab93316ea830eb41f6c038cb060905a07e2907768f4f1150708c0ef3a7f4174b0ab6c7f5e67307b22934901a9b67f85eeedbe38fcb4027f86b72ef4450e8a2db4847a8ec416889f92061ebc47e0a9b24b77939a84a0070bb78a83fb04c99de68ae952d782771a0f8e94642b7cf8991a81dace2ea7eb86a6da760ad5ac0f7a77a5604ab326f59347de32af2ba3417e3fad600873e15ea825df2b60527a8b9b86784c10cff032b58deb51578c4fd857de49cefb9c81910ac6f3dbb3ff7d1c8ca1b7a40e53439ecb9249c0b247a3db2be5c45fccf43ea3ce469f3d6d9800e01cb78a45d548a704c4998760c162dc8992295bf469501d5b4846c2360d4d6bdb0f78170770d73004714b72913971b6b83a20f6bc863fd9356b89ab09c1c89c92bc569c56b49231655100f3da283472f4a0c4c8ed2e6b44c8cc5b551a9edcb2075bbad26cad25bb48aa09b6f33c6a176164b2b6c4104c88373192256d665469d0b3fce067db6fe4e09874227ab81bdbdaaef86de937fe961ecbe27d04f3d55ad8b3c1df309a2a1dbcbe0c4c8ab4cfc52a937f48d3bb868e434f7154452255c9b310e199629e5b59de218c32e446c101a41472ee42b28cf82923225b2332046551081e8059f3246752c2a63a9341650d743b7dc1874803aa720f92793411a825d4c8da45007387a7e23c5eed643e22f4c275dce75fc1ce196b59b593de386aa280740ff5db1960cc915622dd3eea59cdf545aff34df1df7e56d137bf6f56cfce62223d68e11f593724a2fc9c8f704bc987bafc627d08c388aaaefe112194d1d7df82a1ea78d2943459e3cdd71d7486e0812c5ab98f51a9470f2fab560e2002281750bb0250058167fb769729d3dc867c9c71d644b2fb03d04debf1368f7207e793cf0dad6b2d679f00b86e67c158b3994d6d7aae71de647d6d06949a51e7600fadc7927342c243e17968d77a0f206d049a0bbdda15f10589339c40e83053f3320faa3588b4f2ed4814111091324af48ab37449518987e640c600cf10443fb5f21ca2840601615f2dc0bf0b0c0626780372311629e26818e1d812097f9e25112bdf344b454e1fb0728a2e58d80d45d2832d16f618ead25a2c93621bfed46bc71a35dfc5d97911036cfe2175fb09dc1bf85f7218473390b1a95bcdd45eb324dbd06510e720d19bdb62d774f71a6c86662969975d921cf7339b617bf673b3eecb535b33e17746128ff66b72923f8eb067802c478c4e58d3dca6f4d3a9d3b39724f2ea6998c37504e163e1271ecf60675c1e71ac20afdc1252332c40390bb7f6b57f97fd4a8d584de60c29b4f4e09c0375969429477416b58016066bf1ee026ef5182657057578236df2f1f39d5d4ec452083e2b10c5172d61984543515cdfabf1c7a10064501e21f6906f6c9d0f2c025d920fd78deec51a64cca814c71be78e1327fcda16529af5132aa587f21ff88d7e92682930602ca57fd5c74c7eae5adfe9c62df3f58ffb4afee865c896f817409280ed77ed81ba6e446d29fd723e936514631105d1449fa16c186b5b123a418b4427cfec6cfb8adc739061e5c20529a9f94a97e080a82a40efdc54089eba5aface402870d76ffc5c28fcc0513473b689182d18c7da6923a860128b2e6c29c003cf7efb2c2605857bbae2c1fb361a794f7ff01a5dcc6965fd02b8b89e98686b76fb739a1328698535827eaae89498383c825399ba2295440f73625b6d6c2affad889b1e1939d599c6719a1eae810d6245a9dabe3a99a398ab39382edac03cca47d3b9b0aeecf1379d384d3532291a5a8122b4f096103a5f5c06e6de510f735297d4399325379f9c5933cf17e356a7754adab7741bbd097a07d09007373225788de02a53f584a3a221c289be322720ff38c2b2beb7bf1b028e171800d509d83bfb36b9a7fe4f8e1a461d19bca7c75ce2e4c584e44d2d6ed129657a6244ccca3c9e68c715d7766ccb8567b746b10e6adba20e53dd502c381ef090fa6ddb8c67605390c5bb922864b56227fb3bc23e5b0cfc44be26dd19fa9e1d9cb5c21d82951e7a537ccf99c3b0c225900771cc056c5a9476a436922209532e52af39d23126c46d72c358f338310892b3dfc0d3813d33b9b1d17aaa0dba920b9cfb0fce09b5fe5cb245f02edb12ff6ec5c60666570b36a65dcb57a9ec9b1da4da6c9aa42bc8cbccf64b43f847d75f4f772307eb6b8d89a215eec8861b7a6af49f5a707aabd33a72d06199eafe519482be83bf6e63c9290db7fbf7d7f8fde68b9a2c78c7b94ab37777c34bd0e3d65fdfe681e988e3d97b1d525a6e98f9237a5741a4303c2c6f3687516b702a0bb6e418d996c2dabab5f7b4e831b75412cbcb27bd7f8ff97dbf961825ed285393fcb84d9f4e92bf326deecdae62c7ab6fcf74a12e5c2e2bd3eeae1f1b54e7134bdfacd745845f6e961c4a3454140d8e914f6008a25868a3d1f4087abb0c07bc1a3eca23ab68cb0f940c04d3055726918f33fc84e1960ceea9ff87524a87135a8a38626701b32dbc5fb9697a8cb6e8adbf28dffdca31df13572bce761bff5503f5d0418d14eb102923db0b107e5ca3e31cb7e28ae5e54bda1171d7e7c7d7b5ea3a5500ac3620f32ce413ff1cb626e21f64d5853e68756f18b4cb085682b74580157ac5c6caf4a83dbb6a7daf07e36b95ba6eb8dbd928c97f20c7d4f852abf0cd21cab020fa454134d54fd0e2ed30ac40876cb3537ea6be12ffc01881143204be2b66a3e96bc480980688361c1180d2c76766056ee32685880220bea466d2189f0844351c8ab321ca077ea76dfb4000271f1cfe27d9da32476f1833f4244cdbd2eae3caff54c6224fdac49696d959e0c85177eaeb1f3a3194d92b4a3ed56fc029f61e1076123ed1f457ef46f8c0ec750c87626df7cbf7932b99769489c9ebeb7eb1f835835312aea84ef197e8d0df2b59da4b8e3027d9f414650aa95097994e5e13b0a4ed25943828cd39cb8f7d8fea28ab4261dddd3f861ad80abd5d2403625860200aaefd3b4b19f302349f3ce1b2c48fd286a2250a2893ca1f35e5452834cf0486014a9e96b55cb2d8250b5b42f547d4591c1a17e2b01e7e209db0878736028d3012d179d85bcd3f1bd455b796feb89c6c535228e1f6e16ca76dede200dcfe6e7395ca1417f4848443e7b89913846d56cffc8f29dfbb7ab8f3c8bc56bc0e96ac5d3f7baf0e3156fd0113ebb075f9b1a2891541d537c893daa0a7b453eae06d37d636e9374cfc915054d1e19031a2398941cc93931f1b9520ade93e9da9624a0e1b40bb4d6845fd6f37bfee42663828c6ae6d307dc44abe0cc467e2be7fdefd654753bc3f1f51a7e00649efd12ca3981f16c28ca1c6054b2a8246bd3b1bc9a56d4bcfce585c3ef761a2f35c1d9518ce926f360db1e949a61199e066a754d64b3b10e8e930ff9f5bee153f8fd10b3c626ff410dfce05fb1fa62b4f425c1e4e09f62162dab28485458cb22dcbe71ee6ba4b44815633bb0ca2cb527944f6a3866c5fbce1a56958a79c1910f9cd5ecb2a07605606fcc5825c90d409e2711b9a11b79ae5455179c417b9a5164b740b0e74c4b5c34107112f7c448c0e6fd415928cf9b5f5e72d7947d92fc0c2b8b704964da21486d61d9cf7eb772268d7f3f504badc86d86c12d6cb6c9c361620d6fafac876060cff2dfec1c0d1290d7a1d1aa957e1d3411f9ac3ec11493e1ea5c9aee4d08114a7f0ee790e42be10508d9e2da3dafd38d52d73c32d9f1ecfc3cbc18a919448d535a08a5c13395033a6f768d36c791298ad6045f45184d51f971dcf750380a4511355958c772d92fef60378cec12ed90da99dc5ee0a5e3b081a0766cc3e830af4d553987e19dc0484fa8cc4652cbd52425ac0a25c8d4cf04c6e25b4acb02af6caf018c585ae2c83f24b31b7c85701079289533b793e949f890956c499f39c475090d0dd801f18941e1e75a7192119cc4b2e061e8791a37e10daec485808824132c7a69b1e88ea7c1b8f644dea0c184079b91616a22d46ac410b6ba9cca41d070334309cc4fa7c392fa9da856dfaa95a614b2874c4490a7cba3517c03989b58bb4689000edb675f31ecc5a84041daa5cdab2f71a57e5e96fe21ed4a624e177c454011c0d1d838df8319f4e89a69d9983ad4bd1b70ab2617f827dae852007edbbc4a06e1c8ef71cc046cd6b861978b5b05f52572f77774ef284e6d7107a695259cbf4ba4d772bb961e57421efc3d45530bbb27972ad8f2d90cc0c361c3ffafa96e4b7f832a0132d602c087070ac416f33cc5915d8e2f8130b4cd01b0652bb4580e7c3e0ddb1eacdee9f32d5f794bdd4e1a60afe8a21dfc8fb936500684cc7ee4ea9efea96a5fca68d3ace35dccd3f3865d476532dbb9913bbca339bb9e1365d6d0710dc94c527df3dbc4a3941d6d1309fb13f99959f9b1e9480dc879132b37ef63e0213161e5027ed5f5db69b941fcc00fbebc879130179400640ad2b55d4ff8202b43044507d5585bc21238ab30a2cc72d07a18d4e50a433885ac8ae641d47c25c07d75700e0a0f1bb256e2806434ad499c64d9e423aced60e5fd98fd2ff93d7a56f4b6a4b25b49a159845fd3a1dcfcbd93aeeb9d026a747f405fc9b3ab1dbfd37e4f5551eaafc105bcbad62d89c91023a41aecfab63d59a2aaa6696344467ae40385ad1511e08faa85ca45408db67b1731a21f48bf3661c2d3ec8cefa5bd3c3b8a0dfcaf78fe9e653af720d4ed6e44ae79972773e1718131405195a370ba48a63e6d84d611ba9e9eaa38fd1f53514c9e1a836bc8d2bd5c44a3787ff786f3d657454111e49bfc1be35a430f910e5f8b268400df0e40d3dd36cc0206ce957ebf4081367ef4dbe458425374b6883b9477fadb378c6e5a1fc91725119454322347f50f8ccb4c5ef1700425c96e0db17195b0ff5030b48ace989e7899ae26da3b8aa7ef408c0166b450ae0675afdb7023c28e2a142e0fe794535986391b13c32a6c82603b73bab13ed7c14880857431c85e530866aafa1e18ed696cc329924353e6509ca487da18678b2a677afaa4def8a3d94d0c4395496e102cd6058de0ea696513cf2b42053819aad285e1616aa30ffc755a49a8046f6ac535e8e5037a1cbd4f6754e6494004f068dfe3cd4a9a485ac2b8dc5f617aa11f373a89b1b94b3dbdf9a2f60bf395b2d8755b0d589373f5bba2b4bb4d345859305fc3a81cca6dd5f550c9cb701050e763e0a582540c5b37c6adf2c91e8db32553a88e1e6584b8b829883d67abc7b4901b08025fd458acc5f837d2f9adaf7d31de9bfcb9dbbc6f5d1543979f841c19fb42869990e8b3b14f764b34d01ef0976a5388752636aececb980c602ef78c600940deb89ba384bc670f38e4e7205a4e23f136c49379915913fb591210ed9eaa5e9808fa4d69fc57e0175935f1f32de0c6e73f5e4177f1b560084e7cbd4e4efea8b5939cc8e32332336f614e327b03458a87b4ae909d0f5fe93ae9c39497f15d9ee929fbcc5104ea653da7002b6455e72064e4d1b554f43c3d93de32dc391daff340ad5c7eb2854ec9d9676671ec0022fe93b86c56c5828198190e9f5f9678caea0f500ba3cf74579d1bd3c0332ba9eb9c071c594fb8c0bad9d7be78ef9c495c3a052afd7863c1d12ba694d5ff3ddb2d444e49b2bb417c58f93cbdd85a1d4eca428a7ca0939a7a7ae1aafd20f06c393b0033f1c59add73496ea76d9d947628dd48808358b461c52a2ef4af6faf243e129929bcf3ba34da2af3d179a5655aa007b83af3530c324e51ed22a2f567b79bdbefed5a9bd798168eb88d5efa5b378ec52f2172b8d4d590699349130c90bd2a906bb1f5d8e3302a234ec86172cbef0a122bc1201255c1bef87bdb178d600efbd0f1d9a238883f41dfc1460faeefb1198ca7fc9f5e79dfe1c75a66d10a36c0ce7dbc1ec7ad7895dd316f1debda1ea1cf2908ebd2b78b731f82c2c9e2abfbb331e03e45643a98997502e72e5cc3a22b89a752aa86103ad0b3d916fbde6420530a0d8dd20a8058375d560ad64abe4c5f826ef9bb529314a5d097c60e1762d8672b652aa8ea8dd10e356b74a87200f1671e6a2da446a3d0b4c26014b20ef930a855063b48a050e7ecb154778e666103c0254a04ba612bcdf82d614686453a05485374eb5262594996435429e2fc6135015354e070dd5176bcdfca6d557e86e82429e0a8d92d4c517d6cf1f64f96a7483584479ffdee6bdf39af7f97794894ba7f738fdcaf5a995b2b8d1a3754d3a0665e57b01cbfa003d02c06f20945cef161450343509d324d8ee17b53cfb0f720515611af3239c8291898ba7c220d4f2274111f65a40932befd337fa638c95f6c84dbf2901a79892c10a7cdb2543a48711f19d59c89ef78877735db6cdd58760368c2e2838ee4b5d2390c3595adc50a5a7c287dc21e4ca331b117879359af2c6a65032c846fece4723a5c18d590b1feaef2cb2080e981390f5728651b1c4ae3a301dbe8f44ad6de7fea5c60fe40d52e227875cb388c4b3b0d5caf357df4cde234c76ea159e92d87afa3998e30066593ccb4dff5c6f9ca74dd40f5e25d16f57b065650db9e9c4332d47f0d05d41d4319dea076201f8b2cde7256d2fffd7f2fd4cf1e532d5cf536fcf85a18e6a33fe8b9b9c902c0293ff9c956663450f7f8d86219a43be0a1ebbdced824731194d494e8219d6ea8028b545c3b18783a203982db5406ce55345246cff24a89fbce7134b3a7c4eddd7f065bdcab3b2bb973bd414cf693ea1c50b87318d80ea721cd4c40dce5e1daf1840e51c746a24f140a708bea9d7f28333568200e7c4df94feef51b81b09c1bdd54c70d45d366fe9bb37306a6ab4df48526f0a559780c70c57ad60458f00587d3ca57a4ed49e871176305faae3d7ac78b47b9482b13febedcb3e38ddc2883af788c9f031b2eb101b7311571ca79213f02930fdc09b1648d0def887d2dd5f785f75ce4fbfac7b81adce3617049d45210191c379291f0138469b2763f846281f4a33ec6ccb4261dbb204ec65fb4d92f4280da24123baf36a1f023c4a9998b6d6f0b55532f3eb2f20cffa1f24d3ab6cf54b96b6d0feafb8b0eb1fd64bcc2646c5131cc3b0111eb3dddeecfcfab8af36099862012d4738f5c65210f4c392504376f939a1423c967e4178eab5365c497218056bbb7dd57807aea88db0e810fb09327c6ba8f4005acc39096ccddaaeefb0e8c1c86a22b12161cc126def58e3c2bdf0d7c3ef256bb71e0f226d4d045b7115cf40f5a9513f7521aecde1981f30af61138fb2ba26aebc0519daaaec9e7ba3ddd301c15970e558335595766b2601ba0bcc4d55ef57ee2155a4df2720c25f0fcdac5d99fb4bc1583a994bcadd576e84b507f523c5b5af33a34483b05c8522d2154a325b24d8d8b929c2bda20a41d7df262dda0ae9946e6731aeaa164ee2ea9fd2abb2210cdb5ba06dfc91dbab1c86b8e9f872b97945c32f6c6e32bebb12c90de626fa544e8d3d20de0d8a237242b009b969bee9e6b669ca09f890eacc09d3104b7f7725aba81d8aa7bf8832969f3bd2c38948b54f7e798bc56da40be4ccc138ca12a4b92e78ed626da60ffe475c97cf5f0215320d2addb0524663ca6a009389c6f4a85397f01937c669140db9080ebd606daca6a5df9956a31e15c8e1630bda3c30863371ab795e9a2cf33e17aab5bbac80079d843adf2fc834c5d30787c0ae8e80a75e55208d3ee851e271caa99a981ffb45632fd38d4c74fac7d66b3ae96a0617b946d476d4fac63b9adf39ee00cc5bbcbd261e3ccb9fec2738ea30256b9de7a307413f11cd70cc0dd5b4053aa10cb6ec018f98bf005da839df0a482497569415884b176fc6965d77fdebde2838f5373248fd0bb5e792c7c25f9e7d014807aa730b076d680261453daf10f16168399ff771e9f7ca538d3ddd432f4b82b1a041afe40cfb89ffb8991865f82bd68e649548ed82bd8b13b8382f94dbc04cc4c5f86c3c24c74390cbe5e29ae95f27cdcad176e319b2c08d74d64161fc937ddda54cec3a62693806ca1e9f008e5e21108685d73c8bd260c913eaf76bc0b266a1426de1270d94f20b1ebb5726529187c3df5469e1580ddfad2f586ab70053b8e50cddac1e07d2bbd79a0cdbbf8e95501428b871dcf7f0518a6b931e39d1068cffbade0e7f5c52c6c1210e0e128481cb437152e0645103aa6709fe36b290afaf971a63abd4b6cfef31f445e25ac2885257cc7999e8d39cf19e99b791023fb2d40dbbe0448ec539c44699aa18b613b2bd4c09cb04f4a562f4feaa4b0e2e52afecaeb8e546d202e7334abce31f4051b65e69ccbe8e057ddeaac18d73929f344a4e19d7554e2659fbf1ebc6314634549e8f8c3f509259d9c4b2900656f940fefc31e3e85cd93e65cadfcf2358e14e8c9280b2194b95a68952e8fb7fa65feccb9d78228257c03dffb64ab535773c23a46112cfb4911a59168930794f6532d5933adc072c5dbaa8b2562d9b991c0107a7bd31f0b04a14e007d2443f33d38b63acac9bf7ba417309320fb8018df051cbb474f119039a2fb8890bcc7096e106c46ac85f354c172da2af99e626958bf7e7f45ec0c32f9bd73b5cd207a6b8ad541c23c73870507dcb6ba4bc6f9437399ccb7c4f485b72dfbf988146bf6943fca3ea8a64947d1b8e8af7f1a7c9a34d02e3509f6e40b7b3033393586530b6a2eeafd216c85b5a7afe38b48c557a8c57d4680b73f4e107811daa268af2575da5228129cd4b534dc80949c499807e5d9e648542d41c955cd20fde3dc9501993b058fbfc9b923577302649c5e3c78447e39d53906184c28576c49a2353aeea40282dd84d2d3d36c6fc301b327acef676a60f497a761cb5494f2c4dcff0460ce1b662ae8885b8eb5856cd795ef6b44968c70d60c32ca49552bed338d2c63886c11a848941b871415bc7216d9ee2c36306c63958523c483628c87cc12d3ff414112238ed0e3df0a6d147f11e84ec886064218fbd096198ef43931f59c0a70d4b82b93dda36b60c84f8f1c911884317ec34e3f3d0848a5188a6ab1ab39a23abd78dcae31ce020ad8d105d85079000b32cd32ba4b5a16aa105d88fd8edb74374fbc70a1bf4cf13a47a4f30ff61f71c629f25cccf23f9e3ed04d9f6d1df1785be596588cfaa290b27c329a2eac8a844554daa2bb54d9133940c77274aeddb5172031ea6bb1f1b2e7728a178724dcbef241307e1110ac3a314d2c31a7c143e113c1703369e1a96a0fe55f0e4f697de72fa5d5d1f4a442e6ce8551e23ead98efd34a0c2931954823a455255395e585d2d1390409110e6ce13f67bf625097bdc9a4a8f2ebb2eb23dd62b9faf4eb8b1455eee15af90dadcd796aad4f19d3e36d3b2713527b47dd8e58cb35edcf7d6421733a8a06e61e5f77cd739c6dc68a363793d8ea42a5cb27a0a1a754253b47a3ef7937dab3d26e9ff5624cb21190c91743abc979f30f7106eb13b8a2149b1a4cc093bfdbb20d987ceda1d1c9851306eff99c92923f7d2ae87ac6d1f66957a1721eeb86abf52b9f0828aa728d063965ed5a67300be76872d0c0b2c3863e53cf72313112926066cbf89f83d41714ea9c976fa01d75499d170f491fc71d28d66ec1ff934d7cbf1561f6e20f1812056a78e2d2e43094f137b19f51c2beca4875fdef964184bff85b255e3907bbac0deab0b283fa3a58410b2c752da9586f451776584b408546862596191e2c60ea16f9fe771998f588a31179bc9d86d2b8899006f845426516ad28c18667f51f237a196865af65779a832a3b9190fb8f630c3df7a6b25ea3f27dedf41cdc9cdc0e28986b307c60a2da4b9b92809aef62e9b07efd68a33136064539ae149d78346408d298714de8580051898b7b5bfe0726eb85b7b0c4865556f70118dc9e8ab8a150db48343d1446ea2040d37b29d3abda5fb215a3a479e2fdc54ebf1fe95daed10dbfda1ac2aedab7d44c658dd75e84a0e641e4c53997f9948d59ce69945d0a954668c53143e0b66fa27b161c5f0059191bc8192f3d718d9facfece04591e37c4e132a253ab16267fe0efc635aa3b08e445792b646b81aa71549d0a5dab83e16cca34d3abba1448d93132a7b4c5b3fd726eeee62fc426fbb065dd7807e7596b4b7f10570b6a0f521f6b6442e5a56143fb312e0bbb6d6537bf390153c63aa06edfae8d14a3638b6a6408276b3d662781a728e7c043e11f096a241ba15aa94aef13bef7112719bdc6db3ed2d22aaf2f886834c9e1616817e6e591c1d8027d0558ea9865aae45c425a6cf1bd188d0d9ed8539b87c19f6e42bf7920963e3521dff8e7ea4c48fad59c47768af328723cf5d2f101ae8036afb9f5dcc4931e8847c2d85fb4abcd655feaf591e9cd468b9659ce49073b4726efaa781be54693630571589d650387dd6811e77ad20c03f0472736061d95329e84ba26c87c3a3a74cbbfd0de3b5d6d7208bc15938ab06c74f85ab4eab7432fd906cad564135157feb0058edc564bd3a00007abeb5bec6c3e3d5c8647bce6eaccd1f4e6324f5788c730d78307c50905a718f8c245fa6d0d5d92b31ceb7e2db46104753c4a57e2a397043950bb39c2866a85b99eb6c835f2eda0f5f793a1284b541c20e0659b06a0c5ac9d1068bdc3032e2c7a354e6f7506f2c3ff6c7274fbf985c6ca3836e5d616fb28f96619abbdd7ac2821a223346a3e3d7b70bd471bbfe351706e35fc2c7aa6132ff637a456777407d9e46ae41af69c4c19c44cc675fa392ca7408ea8eff5c2e2db86b5e604099fe94d4d78e418bdf79156f69eebb991be918a98165dd849468c1d7c969cb69007fcd140014e8de1e0fd5b3dea1effa90cff8bd67006db411ea250d6a2150329702ec7e9651f3eac1e68d5d20caa7db9fa644e9ddfda4263a739cf031e0b4f3ee7c248a6272609d57ec6dafa57ccb2f4593fd184b7257adc0ac7eec69c5ffcb6694e221f9744360902036ffba0d1710a0bd9d74a1646e4fe9ac0ca6619f81ffd4388088aea243a030e5b730454b911b5d2d2b1885bae65be5632119fe4bc0ae47b4531c79104a571ced13acfac27b19203ab2d6ca2414be8c794312a8905851c5d38e8b46068398159a16393fce271c45556003b19dae74ffeadb0d29c631cba60bd5b216b35ca6ac6eba5c3ed2dbed6cefacc6af2d2900a520eb5db3b9c8fc82746de3d6c45d0bf9b15c93eea1ed39ae47572b2dfc43bbf9550d02875ef93619ddf42affa0a25b5aabf1adf231b92b0f48888bfaea09d7a8c9accd82af7cac2ab4a12aedd55ccb54763cb70dd6d14ff0ca4830666de37acd8f68ae8c7f76c223d199ad22f375b09455275df8b727da266706927f5d08106bb66e6644d965d3daeb0676a561d204b124fcb4b3f8d9310c98b0f3683332fe51bee76afd706a78fed680a6565da87e2ad81c30d17ef6a62b743ea53cb8d02d82a7fac80b5f5ce33471c7f9aa1aec37dc56fddef1eb419482f065a1d68bdaccc76f4ab7724470534eec12df0e9ada80223428ad7ca4b8dee10caf7c378237ec906f6633539ecc8a98567dc42ba01ad93b480d8e7dbc92cadc39542fb855e817b1f95db4296218a72cbc58a147b3be68c71ea89504213dda35f8cb912493684e0c5756dfe403f84ef6073a4e63649ec256c77051288039260ddb3157cc1d50148b3c194ea5461adeda58f7d6e16ba63e8a92326b4f83709ca713701f0d819560ba8dcfaf53b7503c6276e020f14700890fbfd24b497c972c78aee30f82ad435df63b072bfa6cd77b7394cb7e93e48580a5de6ea2cf6f8f081bb25c14d3e2923ddc0f3781f6ea404184760dd22e0f3aadc9abde1dd03efdf1a2bf79c1eef08c1c890d39737b0a2085241217682ed2511c44ab9a8a944e2b2ab9b1b951875ebd93e603b21e186b5a773aa602b783f93fdb0b9d960f5f97cbfac796db09fcd21816985e50f0aae65bd941871d0d513cd5f6db662d22808877683c4026f149e35e3706c29898b7482c161dd9c71f2813c75863ba19cef5fcde0cc9a40e6fd8665087d39b30a47e11958cc3245208f805394c846aa36c276c17e7cea0d666f45f440cf9dfd624f2545ca98bfb7437c25201e815b83258c8e8cb1d029a5adc7232880de30ae2b01c6a484df9b02e82dc9c8cc1fd3f81ed2a614812267a0326a1b819b787e2d1334e1c886b0ebe4cf434cb341d1b1c5afdf139b607abe492094485a3127acc6764776129539917404a238c6099d3f4c1e6c73a05b0f54a2a931103b75054c586ae279a72be2d56ac8436bac38c443b4f0bb6d544d7fa24e706068f39f161d87604b07b5e75c53ccd514cfb551226727822bbefa481d2f3ba58efbb0d2ef997368e26fcda834aef6b3888dc3fd09cfe3c93b06857e2a9c846a1e5af2b1bdf02cac2c2eb26eea030edd5cdc0be156ce47275640321342d62387ca7874ae9105c111f0d525d14423bb0080a68f6cc6f0442e60614f2349eb8ba216e6c6388d90d7fb65003b46a68b427e48944fc83899697ea5df74593021d0f7d36461415734f2e48dffd306cb753e4776abc14d2f5fb97fce32dc6face3b980352cf40dabb2f3a3f9e958e8d036de73de7027575649807cbe144dcc74073e433ef1a98d1e04599ad3b3da727a59e6ac2b57088a6a95b6d8226e61eb5f72b1f27512faa9738963b29da0f5cf47d83f1428d941834e79f2f280519f7b2300857fd0fea23f5426f138e8323ace1533447fe887d67fdcc038996b6f158afab4345f3126c2f77f2ce89548d9ecca72ec1c0ac3096c77d86d3972a34a7c25342eceac7960fa86065f8b3a8398e2edd935b59655f9bca00e2e7fd2a734f50ed8080d84c4ffecc8b792530d15cd2672397ba4df6dff4b280319167a956f8bf30bb0f0bd937c24497aef1b2293d863baf8b105858dfd698c5b6203318636998039100c6204ceb1851b55d30f6fbb8d799cf67bbba2e7b40e61c92ed861112053493ac40402d3013a25f6d8ba8398d256fc0172065c2ff2ecfed3d0aee67910eb0faaee43478e0fc47aa7cfcc3d85c0735eaf40abeaf42abe36725a3d48eafd0017f7717471d844a6f8a74ace0221bba68624a9e6fdf427aa2b195127d2c28a76b51264ed71c45ba2d911d425c03fe798904b7545c7ce4a24e228ba4a39b829254ac5811ed2f700567fa9b197f5d953685e99c610851df4fe4707aaff40dd76bd7a2b7c649a634b32b688eb84ed2b0c6690a594c25c862afa42ae6a78f450f71f1da9f6b7ecc998002607eae83406f73864bc6a97e58994cf363e9c813a43ce3d78d7a1d5d18d755caecf58a9edfe7897759b96bcf8408e9665d7cebb905e3aa7fd80bc2990da0d7b68547080c740aeab041a8d582450a6f06155e1e53f61090379e07fccdbd7f3f6c7cce6acbf7a2b4a32d002caff4f09fa680ba070ef71d6a0c0e3f70f726d2f6ee99c4a4e9b7cfe3c3daf78059c9baf81bf799187ee9c51ed95b9c2ef8d8f6f8fcb867217c25b2b2189d5dc4302b566c8123437a3ebaf3af959dae6cfcd96cb1a4760e7660399f4897e9a16eccdf7389f40bd3710195bca5c4ab7a254cc9abcf750dc82dcc76efe48d8761005c09a118da165f39215dde53f2facb5e4c6989f7ebcf740b96093233c390cef9f7596ff98e42fbd1fe265d6ac840ebda0d73f7247c3044901daa5e44070e50dc1d88372b96f2827e6d40155881f3e125c2d4a85beafc82fba6794ae46b4aa1504f6db77c44c618bc448aaeba59fcf4f70c12d5149eb3901f20a62808de24a88f1bbf5606613f51eb526c53fd230baa5ac411b62280489e91a57007a82ca73d93ee0d0bf5e2bbe5add850254da196c18d28de7d33b7090f659d81608d683d510fccac0326142f6a1c1ea93122aeb0792c3321e635960930d2405dad4bbce20077c72e2c9ed33406293b5571d49a0ab9cc6a125b16d5b3fcf94805b14c3d729d833501810339a4f307a67119dcb34ba2f77d876d2efbcc81236b612baf110039bec3d10411e974dafdd413236e1da960742d84c0160e2c62bdd1e60034e02b2ed5a26e8d6cd5150f939cb48d00bf149fa611ad7808155c875a3c2ebc3d4471269ce28eeb84e1476f0a6ea30865bc54e7158739cf672b569299233392242d36302fd22f75cca8c91de027c3767e18c6549634c13f97183080c9b60cb226c45e9a33b48de78d06a3c125f595d3d696cfc93c428acc65ed153d381fef5d1302a6f91a7bb3cde53d817fa8fe7b88938c00b0a4af4fb43f34762014a27a3648903af815d88bbbc0259e6e233f428d0e6da5023d03a98007b80df5f26dcb88d86ddabfe8b52d9ab776880c55986013e7047f9ac1af9f36fbcbaa2254938135c132b3e893544d731aaf98082ad04a5f0c2e3e2f46582de3b4c4b22b174a755cd3f89da9097f5993eb79064b1e355d9646e8b37ecb96ed4551a44c5efb27d8d933100e23d52a931bb347a439ed8886cfc0495635a6a7203be915b2a92012348fa04c226d4ef6caa064a358013a0223bd112f10a2919ec43f2e73df8d031ce08c09d4159a24a913482d94566971465c482e60c00d9aadbf64f848253c5968d1d87d9519babafe8f66532ad5712427a1c03d615ea097ec4e2aa78f17941e6b1583fd1667a2ca4d06688f64e80b43f8479242507382983fe38ef2fcbf7f0cbb41ad22e8efbd5714da536d28692d38649e7400da794d3d563c88d4849451c8bd9a29c2c1830a0d376377fea6a536dc000431f6dc745ce82d8ecf7b3a21848b95fdf2f9e4942d8c7c6d7cc9f7e2a6e34895ab024b5f3525adf79c20d27fc83320cba923fe06da5579c76fe049f02c87b0dc8b80f85a8327523e53159f72d99a8b72ea643b8d6fb15cf4ee3fd4b1c78ef53f4d948d28ad2460b2590678a83e98443d5049fc754efa4e7b700cb7f6a82336601121b487f059a0c3ceee375c6db6dc57b3618490c439e6e88d27d79bdeb28ef5b762be3cf4fa0900546718a71d7fb649f0576d05b35eba4577afb5e6bf2180667e1b3c00dc5a92d990db5db3624e72d9c9cbf2297022beb8f8e5565027e20bf97f0e6524b170ce79bffcf9b05e0212c4632d68de085d8a359db6af34044fe1ff50592b4d1f217790f89a68b1b23eb7dabbfbae1157dc30194f01b42340ddd3c718fda0814e7b21dd2d11e59aae1af310b4ffdcf36b0c928ed134fd06855e82f3e47c53a0cb00e6e9fcd7cb6d4ea476da0264c0a11eeb9618667fcf05dc90fb7bb3cf92d73d80fb3a4c3f2b68987b46d97f7168750a7bd0017e062dc38342cf9e7e8af9beedd4bef98711e31284c9a83b21f58968ccff349d53d84f30562b1f412607d9e206ab0fc12c8c5326585e0c8b3076130456d9f88ab8ed4ed2e6a7b3bbd070d99f74cd8ac5e5968468acfd9a7cb3b3e98d0e0e1746a2ea34a90b45a59d67f533bbecd89fec118f84db9927d73e600be6130a96968794346f4f70a7c14cb4ea3bc8012a80378ec78fe6b9aada5f363fa4a34bfc6e82b2439266aa561425176cea03e31db582c38167e9b7d337b74f20e1ca98d46414a982a5bd6d371ddd720f6f79e7363692202ae41ddb1f7b2d759ba2cd8fd0f0530800ee5d477169c20987b436523628f71ccbb69a4f2c578812233c1dafc65fea151b8d36b437c90a22bfea36a8d753a82b249d0410d730dffdca4bc417249ca0837b0075af788b0999be2ff6f19e6405a9dc600daf851bc84e3f426d09f4e57bd7d15fbfb1ba86eda2bd1a9326aca9b5cb7b7c30998753c429c6da7b08cb67a8a911cf903aabc700e43e92b24aa6eaecd5bdbd02c5c1e5fbe545e62d31a679402442ef854daed20e980a746d7710e63e5884f889e828fd1f5e001cbcc5f8d7287b7037636a6891239b13ac12169e85a749c11e79d11b3fda074b6dcfbb352c8b1c73940f0014a36ee6f365df04b01c757acb56672c1d79152059c320b9643bd768b627ffaa5474936d696848ef5d04f5370c110bbd8cae6f4c3e77f392147c8701c9dcb09da71c81e9bf5d0b9589dda6f77e3d53bbf64c2b6cdd4ae76d85d67c63b35cbdbb3c39b818f76a1283f0302f828e46324459e41dc5c7f166f4fdf41f9dae6da6b0e64c66bc496f74822ef77bd9421648e8eb871f59f31c29477d5af889e8f9d917ba741364d3871bd9a1bd6cdbb15e2f7ed10d55dc27e54f0db8e2c690c37c28266d7ec9e7904194f02c2f29760fce1213c871c66bc60536e3329634d24b19f7c599d10bf2aa6b56e902603d9fcb04fbe8b9f8550f6c1ee7040014b1bd4c917fd8fe19987a57d2f015874ee286e8ff0f7d8981ec75e11726d3c43fb1a40e6322cca79acbfc06368b6c17f17d001f04655a284dea7baa24ed536774cedf5f2bb5e043e5db29ab38dc96bfe4113f84c481546843ff35b659574eabe267f82e91575755f44172086579b2d6b0c72466fceea9adc5932c40ff663a8723538aba1acb61b2fc703bd83ed643c3341d71843cc489cb22b9c2bdc13db9c7628e4a83c001cce5e814662ff8b4e1383a03961b38052d69d212cb152bcf794a061eaa121da8c39e35b2871139cdb85770d12b8458e96cb51382d00e05c368b0ae8cb0cbd17a7498f6d8316c577501deea2425ef504772149efa47124f3d812e5630dcbdfe15c3c6acaba7c135d8c017070207b6756e9e37ba3b7515d369f42ab2c16ba2d5f11bd16f3a3821db4c767cdabdd68b97dbe2d56c8bf383b609e936fd0578f548955fd240836c50d3290ed7ffe4f21ceab2d5ca9764c3a58e8ee63a3741dd3dbbe47a6795fe2fc3025b26c96ff1949a30f35983c338d9e21b55312e2126d8b44c3de866785f824fb7a942463a5140cb4a7892411a1640b35cfe031fff108c04c01e22e99c69300c5e6968805ed2316262b7cf4a9f88dfcec280d350335cd4ae016e13c6827d1c8096c18b153a5dee6eaba55dec2ac86ffd4820cf617f1c93d7c4d1f616d4753a61d34eb6f91e48124a2eda366131b2d1952099004d2e3926e7f9d77cd0817c269550d36b290e309f77e0597c94f1386c4ac8faefc6920861d48d3d3e924f592b183a0cf0164079d49c5cda8be5b04cc7b549488bf897ec0a7a3f1ff6d30eaa3398e1d70dfbc73e43de66306d1420a7c4174b1aac6806eeab647efcc75a4d12c1a62315f636fabad80860a8851c2cae24efda89be54457586c66e1808689f37b7028862c5b766e1b85bd285a539b0e255d7ab26ac522397ca2ef70614734b21f1a72d1a2e52c196950e478c407327f24f719e9fbaf876a96d759021aedf2a68479621444f08a42ae1e41eb66931cb52759e545e696433a01aa16a336fc7aed4aa72884e88d3680c0339ac9bed1d5b2dfc4f840257a64fa5c187d91ab6e9933f166bc3e9a93a47c65476dd19f5f81f4b83620fbf4ca65ab10766f460587967bbd87d9b0ec3fc7ff86d2de847eca67fd8ac30147f11b768c7c51014519632c522d6ce50cf6c00937bef4dfabf0ec2c9adaa761c3384d1f2d404c394bfde2b6d2e0855d03e062401538a0835c33360a6850be2a8d8c87630dc57c9dfa1b8e5cdf7995cf0025fcf93e8732040d82e799a1cc4fd5e4fe1fe04427120d7900e1d791aae549e6de44c9e5c0941fcac1a7f702e7fab1fb4b2ab77c1054b922a74f6329f2b6ef2eba456c3174e6fe484ca0476d13be1ca410c05598e6ee334c8dd84942fd818b8dc54dd1e51aba1380b6f6f176b7500c4c6f71f25136a444820b63b5eba73974fbf46735d3d3424b6d55c692dcfada765aebc2ab3524e0f27a464cf2eace4ab70d6e821b0ce48c0042ace4f74eed16a8ee3fc756a717c560a7df7307ba5adbf35472c24c5528dde7b272639ed1db2ff55bab60cb3a23716ac7b6c17d60f5f27cd8417fcbdf9cfda7fe87ed7fe62348417e3bdb72ee593826a0f500c06398df79336f94a375b755872a32658717dd622078cc8c40bcf4857a64d8cbee7e23bb4e73a756fa4c057d7914433de45420e76072b9d66bd5a0029d64f4e5e0f385352dfde7b0841afb4a4e692a24fd3412fd45ecd33b0f769cfe8213c4599ded278a9d6ffc3d794624278b7451a12195f14e0bc3781011565475f7e3e3fe55cfe8cee343d06bfb427cd73b179d365a2a87d9e2bb8f5acfe266ce1ff06bf746459dcb1687f093e90544a4beb65eeacd7060165a4a4a28e659bef7ba3bce289e5200746fc3e6c871703448f74fe42a6d5bacbb00f17ac1062b5d5b075f4c3061b833d25150e3e7c96e451021b834bf06eb82a46b0ef400af66e3968ff818fad4fb713a36d0f508ddec50d22905210a6b73e953a68240dfceeb9eb219b560dadf26973fec2d5859b64134bd04c53bfe9a0ed6526f1f8ca43e2e2764cc4b05d3d39ce764dce45b8390a3d6dda35273620064b864ac56761999a71eb152da440bf1acbf80b3e27a8b1656cb4d3f580b0baaf8d2b4835fdb691be59cefa1248af1763d3bcfcb705c1b39c462b380dcf43200cbfc89e817319e0aa764487a5f690695ef0b975fdfa6b66c48140edafa32d29b669f0f188f4948b3123c2e5269d0d5eb101a35f6278ef3e70474b7f124c384fb72df1edb7d84352acd9e4bdf43f92d14c97c3a01297563bcfa6bc2595f85005b7b33f25aacbe0fc0d7d0860d70117a4b15d964953234f2ac44c2369ae1d3b476154e4c7af0405fbc2a8d42634c59f0783bc1483aad063fb35d7d6bd35477da7ad3210a704899b870ced33c03583ecd9c8c2892c5df66b6c1022577a17c0e3afb3c785123610930aedf78b596c06132dd6e5819d9698bec7c3ea2d75751c92973eb7196f5de8a39acdb9d7b98050301ca0e2e72999a0efde337a414b57a7adecca8cf9e2078b550c4f574a414dd2caf70e1a8992095d074a7244c04ae7ee6a791f041e94a4b247a955dd083aa81e63308ebdae19fc0eadcd5a9ba49ec1adc8062016a843f3168f59a1f9fcc639d9dd0cc2bc3b80dbd1d016c7bde0a828955af5215a5218e9c1af10bc79abd9bbc00008a7746dcaca5c31df4174605b79a5a1b83d44facd51f72d1faa845fdcf429e5fee023c8c5ee16ac7c37df6b056b446b82b46e3cdd0434953780f645a13c71b51f21d2ce56532af22c4c169d56fff4f5c88bd8735363ac709cf2992e49d512c9648877b60d0a4ffd072d22c32b03def70b7c9271a3f18c41ef9ac154d0081509059d6b23f14527e4686f7d1fff127c4924ab2ae6b4ff9b4cf20ef8b272a2437aa434d47ca271e3ae3614345735f607308df71948f8de25c5e0a760a420f9a3df16d99f956528e813a1f97be9d96042d70c159afa45b60c71ef4e0fd6d5a2341880028cf74a3c09051e840dacfb42a333eb13c53d3935a75d5d131e1cf6b014a819e99dfd1ee7f27eaedb7c55ee70c5f114828f4f004bdc6ec339f1449d6bea5a4b6a097d7afd5464339ce3de511b35addda222d5e930cab378521fcf745356d5ee11320e5b23c2ac205a1dedad23e84c0cbbfd8f9c00342dd7d2931cde8313c37b2a595b527c983288d27107e27120c0de2577e5c435036ac1669c16549608472304fbd90f5017e8d447c739a91ebf4a981a670f45537f5046ca76fedc834c174e7fd82728ab6e4ade50eda9db63227e9b90e3128664d7741a18c318b382f0539e56833063a96140ec40fadba310d2ddfbee90987f48b2e96ba2cca9b77e42b2d62b61f5aed53ad6042a799e8fffea2190470eb1850d6c60031bad24a30726294eaa3fc96210afd38d3a92a4a6ceb322dfbfb720a1bc2b8bfdda46aa761dfc99b35fe75dce0e01eac6a9e67c48dcd12d649f9454e8b36af20d9a92d40782a5f68b5411d40dca53ae7061f3442d7942f0b3d570ac26d259612577fb6cfa8a1a06e63d0cbda28419bed4a968c22f21cd4d0fd23b56508bacecb5a8e583291f8b7a729517929b2ae4423483755cf2ddfdf1aa963d112342bef965552ee06b53d8f9b4ce6b635e61569f5107073f0f1277c84bda7842a0cfc5e4c94a2a143c959f53989c86542df343ccd251998a4293e7c0af4b34e17bb5ef5e05d484741174dc4a5f14a6b2f8a97998e4b9c5bd0bd3e48e7275f7ee140092800366cbbffea60164818f13c4b3884d4f284217f70768b91dfa3a3735ead3550547fa1bc1e6d5c8eaacb10274a679f29b7ddc09ee7702e06c9f4037fa099fe1b2beca1589bf30616cc293f1b2dacfadb6574ad9af9c5f2c3a8be306a0ff05994cca2742ab807f27135346041e2c8ebba7d64d1bfedd96e38af064fc7891429268f935e82cd9c55c716c8acfc5c2b46b7affa041a22b99ec1be5289b9740f5876a1297c4977f646bb6ec72f159b0c6868fc7d6dd08d98de028dc196d277c136ce0e31b2a8dd719ba087d1b6f65ffdcce829587c6262fd1011f407531e9e23ea1773a4919ba1846e0f146d6ff22f2d069dc895c0ebe838be46e105d807710113fdc86ff1879a605b8571221cd81b7754c9d7bf6c35ead88a91601a29df4e6b64bc92ca900b4e28a02370fe1d383f45bb022b72e311233d3965f04b5c23ffd7ad2cbd50789956809387247b4e02be379bb8b35bfc838dbf5f57faeb7f2b9b8f20e1a074611a1f1c40c852a6695b4b87b5c632e4a6f6f3f057e120d18ba84ca5bc5d181d55e435aa7a31d1db8ec6edd9a0897438c8e27538052f4bc91b4f3c5f59299b3890d20c9df0d690e53299030d1213bb53d70098126b56a62dc123dc0500dc6c67c9b74ded16fc4027ebf7d21e3bc13926f920158f5437edc04435984cab54816c2527bf289400da6d3619507c53545f748afa638fdcc47002fed6ca657499ce0b9aa7e2679a6a72378436a8c32e1ef5ce3ce1bdd1ebcb2c99af4390b86bb266663ba3a5dd6296e4bbb6b5eb2c75c337c4d2ebd5c7513d0048750c5c2560c3e62a5fbd79e397ea80fbdd438efa3bd44d8fba56b7d5b4f29f11a48a93e32b1ed2bfab3ec6b4070263a97ea5746c19b3d1e47e393e61007f1d2da0ed18549fef52beb792394fc1b074fe5c8e66cbba2dd7af481562fa5c1d6a768bfce54c08af059db9aaaf60c55ddf008c695c5550efa4ff49e739a515aacab9a27d86240d868fa7cf1c5c17d625bd3fa3755f245562a69e471d3f7081d0d11376bbba124e697455b217071c7d77b845f884e0ce1bce57adc7d7098a9d91de1923b4a1c86f40c080475ffd0aa196eadc7e0c80176f9b27ea95d0228d86192e168c51c806d6ea7139f895a16cf0b771293afa1197df34983df79650391ced53ac60190882231d89651b6cdb394bc831ca4c796fee3137f89640dfb69d7c45be70cc6fa4ac7c4c2004651e0d8544eede6e198c5b3b2ae3e047155def647b921a8e572ac0924bc1ff26bfeafdd1957b12906d352265b559079d9802de54122f8c29794b41e7017ef2837abc9662076f30afcfb84a98347066f4ded388f37f0ed3bdc6fea2f139800b09604c0a601ceee8b5838ea73dc5ef5aedf731b95744596c5c8fefa66672e95dd8ce9874ed6c538fd2c80a5d6329a896db82a72ef3cfc6dd7a5811000b1577000e3a624ae2ec601562294c5bda43659f13b1923d4f04e1645fd01b15ad39a1175b9c59e727fa19c537675b47885b3ff57d4cfd9a32b13f1bf25cdf95e3c1d0555cd079d537683bec4f123c4f85af9cc81b9e146b28325173c3fbfeda01249e59bdfc2a6677b7f1fd501146417b2115ad25cffdbaf8140ab6f9cdb8fe4c03eb7b4ef8c10b411f4f2f2b60ee1e15c6dbdf972bd369c7697e31d7e2f019964cb21589323d0357c2217974cfdabe02947c329e09099748fd9ddf1cd5d970912f8d2ae5baa8efc0ce3fb67f8141bf55079df45df8017d3c3e92ba04332d8c1d0988abb6cf2d3436ffda0ff156dd8ea816d15430392c9d15613af6faab56eea01e7595c98d3808664a8265cd37d74b5cfad2458dc6b00fe4a845837a8f206a1c9a109a9dcda32fdabd46c86c317cad564d14e0875f82f9a239ef78bb774fb56657c049ddbfc0171917fbfce522a660b0b686584bc175070bfd2351e93da2438717aa28e74b2744984975d0f63780ec851ec76afca74613385bab352a3ab7c7ac77c4599ec468cbe1b7ec978b4ac708ff80660d000f5838c23cbe5bc109a9546deeee5f8c817787152ce68ff817a49f4f0bf395a2ebcde5e5eae0c1b5e992384b3058d7a30f1afc863466729d1c4816cb4697a638b5ed75210bbe978abd4d84525c8decf44e34c7407a4270957d3760d34fa94c3c8bfc6514ed6338c6c5b737bac060f919e711a93d49736eab3805cf67783267bd28902fd977e230dc6070f9478151ccfaab6fc09e71c5e57e1e42c0f2f5a59dcdb652fef7d7e0d0dd0f09a2cc155763b1b218b82a18e68d2cdadf9879186ebf393d874997d0d89102d411a264d161d3f66e45bd86ccbea6133c9a1a40b737c38a3e45e783dfd3cea2ab80ada7cae988e03af549781dc1b3a5f07e76612bd84146218982d44eb64f889eb1b08aef465d82a6bf1a32b3f4837023ebb85a9a1741c1ea166fbaa134d814784ac3a55d9f113c6efa71991e671e22ef8ae07a69cf728d2174e1851786839787c78a64b63a463e5bc6b181c499a555cac35bd5a3df7b7ad5bab55357122d03c2ea7be51b6d720fcd0db0e6c60d0f2bbde366b5696e5628b6a06adbc5d3cb8f3054797f2dfb5c306383f26a28f871123f318f74aab9097a437c8e40eb9fc209511cfeea47121e1577af2b1426e3f34b4c231f7c700067a55715979aaf5796a740555cdee55dcac867c7e3c02d6e8da455d0f4bef381e173634dece86c1b8ab750843fdddc00edfb3415de7e68c7212f2f16e5cf7e37fb5b8cfc34af86d3adfd0a55d4eb9b04c9bcf9a77c4e57e5a817e2af96beefc4db3469981806124a8239d63b2dee46f2b934fcfd2efa07fbc6a4631350923c58e836b61dfaeb02585314d7819577d7f5a11427d56106b6adb07c63d385cf0a71ca0de9c2e2a6f9e586f96d72ff146328b3a6709f0cb0a35acc38ac8cf7f4be3a1e16154badd298a85c0c834a12c0529d175bd0cae006ecec3de6e9213cefb5842c75eed39e300cd55c6fc72a34a8e04ce921909215fafc49309e78a2a857ab75776989f669d2df93486317b4511d834a0cd0890911899ee56d573292d96bddc447e710198d4c9efe23c1550ca67f2dfcedeb31dc53ebac0159a815e3c7d0f6ce31e2cf9fbabda86c2e3776b516ff0ef37959398e6257a7cd3b961287d0195a209a7520376df175c0d13030b4f4b06199a724d7813a9dc3ca4eb97d016ac91747f4030e9bb8f6c6e1cfbf08206f94f059fb726555c7058882dcdf07f833f25dbafc287a51e391142c0dc987b00f59695d98af12b768adb1651297500a533bfd47c9fc8aa7fd4657d1df17f50c635e59ce4c95203d8dd36aa304277c17546f3f3158784dfc3940d2b06e9cf9f82f3c986a56f1d68f80f091a89a14d582870e28456f248d2432f4a24619ba67ce34294ded1ff32b07a6a06f77fdaaf428c86ef68f6a9083197c16f543d012ed69747fa6b7ced7dbaea3d38ab8d408ba20bd1adb6bf3df16f5163759bf9dd0e633247037e27d14f7a4e233bd759b4c6a39ec0d3e6a5b7b908446b7b4069b061a0aa79cf923ed527f8fe1366f247ad52d4140efdb45e556f8fad493a8a8e0c5d8a788ce0b26f9734c3caff505626c9fd1b7803f2f61a7dc8d5774d74a09765fa434e35812d2af3aed096e382ec59c97d5b77b62d6652fb09699a5ff37e1e3409c27e4bf31c428cc1f7b93090a344bd51442b7d8b8df1e95e39fc540506e97a9781eef5eeded8da9eb9f5827dd0b10fb27460f7fb7c079ff88064bd6ae8cfc1b9e516fe3ce1e15b20c3750b8b6e286cad6924a3d65e5d177de8f9a59f18cc29338ac333dbcb2d89f552c34f245f1916be43e6a128cea133306bd8a707e60ccf98ba6f5459fada69f27bdcc3d7032a653d23cbef3da895e07ead4d9f5bc0a5e51c9209593423bc4dd2a88f081a9b2deb6166dc329ee8812b1f119ea8ffb026671a5dbe5c3fd31298d4f199dae49f405c81698e9e51cb5cb05d85bea712045089b492fa3b5ecf8a0a38dbfbe01053205bf2d0cafe47c8eefde7c0c5fe535f468a0a65bc097ed2fb3e5bdf985811bfea8f211d02be384a349638104cb374f7cb24e0f7c3461a45e29fba3e878c7ecd7e718ea33c3949833abd1bceae7841aad9c6b6d4c3a3565b7223af00d7d3aac43df48b9798d11b8bc59c07d5db499af00a52bc199deb7bb2adce5bf1c85d620a3bd4b55f449490be7cbb8bc011e243db72b6c2abc57ade620962dc32b049df89046b9c56d9c7b2a4aa1cbf6e473b408a4dc61563b454addf5dbc9a4c70a993a1bfb2a206e9b0872e07f7f3c584b07e0b1507cd54c8aa2631cc339e41e0ad473c1de6e0ca08a8593ed0f3bd68f23319932039e3f803044bb2e4e4e09e6f471c7bdf40f2b06ce38e99a909f6850ba194541abdfb08895f5fb4d806bfd6042f2c5d723ecd6ed6acfe0d0f2ec715a8e832bfe41c85cb7b1a8e45db9b8e460df25391e881b6c356dc14eb1e4e0d32c2e02ec24929a47ecc1ebe03c6dc97bda029311779b20a1cef39b8300e4e340850ddbf2bbd15c9fc5f58b73ef5dc93c351814c8e62a18779f86d237f8f07c1f2cf6a733af916b726678ec64b3042aa38099cf2872643ed33f0c404be1052f5ad77a42df5c8c7baf48bbe2ed6146fbcf322bfc944a4b6eff2ad108a1f7fabb9a999ccba47b08c2f6666ee410e9c6b45b67129c2a16c962b8f14c4d31627c830021fa68d52810a80248b05c735664235de6bc0e6b29d8f2bd75dafa678bf09a15d6039b9c01acf3a782cca4290a90391958e62e669c6d45501e03d99199f941b1988a4ca09cb07df9fc5b459b3bea50556f34e0be627199331333f302c920e49588d064c4043e46fe61610cb1fb39ed9b56d60c296195c368fa8a2fb61c31b348448428bffec56721e98ec2bf7977fef2c28116b72547bec0a9ce1e4ee1335512f09a738ea3e4f5f62afe103c1180028e9b9494f5f15688662ca63d4b02909a8378d2478e0a9c0e9903ad5705f441405605579ace1cc7c8bc303eb991cfb70d21442ce8ebd894cd09e739bdc378ffac000bcb9e4d999b14988faaa824c0dea9c87e90138422df3da481af718895494165a00c837cef55f6ea292ad030a2230796b3b89afd8197edee243d3f8b199a584667d5f82e576d8bba2d86f870a99b4e6317fdaf34972b1bab6b55ca078acd2361d989dc4bd90681ca758c80308724297f26bd43d19109bde569966931425213e7fb9b6b186ef766dfd626cfad0db82fd609989dddb4c14fa61a5c7991a3f9cd1721c7f8c6888010b99d7a4e9b3639c1ed538cad4daed06f21b314a6118087f4dde78f97908c375396859aa6df5a17ecabaa80eddb397fbc6075a1a2476f379b703b5459a184a68406bf76f2f7bdae7266e181324277ff56375f8f2d1457ed7a6c1bd429f76ee4a7559d166230383b79a06fe4dccfeeab38ce5c5a036a238bd4c7a8aa642d4a136b1ca5c8b9ae6b896797e5f672a407dae05264d7ce3951275cf29b9c1da6809d143bfc10546100256212d9dbd6f5896fa6266b8593dff1aae9305a469f1c2cac8c90ff48e4d6747d0ca3576a849962956d32af7ac49930a9621f943debd84d5111fc2bc877cec65a1859310b37e847e3b7d78d62daa7be590c46ff5acfb1a9a554218064bf59cce9a86f79167ec4d4e366911162bf6e815d1ea64694b30da1fc5ed2f5a14c9baf3b0b8f39a80add61f75ba49bdf7ec0f801df541fa683431066b45d54c6d8b620b5bcde595aef057079703f0451de03023ba933c27fe1726ff87ad54c3c9866b583abc31731e56643207ea94302ba972e5827612d24478347633778869c5b43ae430f391acc0f73be43b902936024ff5b63a9e95877cbb07759312a7d4c4702a694b82acb2f3c6b166f1df69f965a7a5a8a55bd127803e6fcba651e3b6bbe93e85a3b55cfa2a95ae1a837435ebbf6d74dc37569ece9bfc7872dd77dd66510e40c7fb0d3bd90e415a2b95fd7394f9c678e73039e27666939f7826260d5745f20f1c471dfe8934be4b67bcccb81530a27f80bdb75bbfbc5e89956694b694384c013bc32083b07045fa68e469d158c9ba26e20161da137858a9e0853a538eb063483d56b79c2f895dabff0abf1ee055eab0f76cb4ab6850df84230e3580e4f761695cfe799a502083e7132158177994e9cde32ecf2200f07f9d817e76b744f8e43fb4182db53769d21c74b5e4fae1dbb23fe65975b4ef55f0c0620363905b0ac05d6faefe8d43d1a7a5b1973491693ebf020082ab10117a6ce4eef86dac196e625441939ba8d2d54b393185ba2f6867af854b12e0f61d46a71d08a5483a2a03eef19f57d9eb8c44aed56928cd416ddcce8c7e2004aa7ba6c2b1d3687baef9b44f39650c0e865484cd69930298275a421d1ee9d5b47d0197549d4df9804d24055e8325aa3f4132d801a44b9184bcd3923f98f13e26444c5eb24f52ddaae352b0779b36a3fe559562b5803d3b46eccd1d6141201ddf8701bcce9f8e2e0a33cdecdf7e61a327f59fcf452ff640b63b44d67963e253bead38bfed2718ce220bf6962dc746ea552e9c1f2cf7f0f08ef63615f5ee3e2e5e6069523eb0a729ab050817632342cab43af92e08e50a6b7aac70d5e1eb72dbbfc29eeff23f58fcff4b8663d2a9584f8bdd751872ad814d262f57650fad2a7a5a7dab6ac149571611531834a9698586e4972c3703b57abc8e219e6698889f1bfa771c8dea165191d479eba9988291fab5a66e116a31eb23e508953be550cea9aecac205aa39fe42ce3c415190b74f7a480aa64cf48efc0906b6ffd6330653da9c92f35eefdf07bb40724a1113c13c44d0aa16eac2bb6fb4d356a2e92099749dfd88d2bb6b45c27ae8a492fac1df5491e5b1939048a203d19f5c64aa29ed838405df8e2f203b0cdfa9f358e8e49d62da4d07b663c8d883788e9fbaa01938084ac806156b1fd94ebf8babaa72209a1ece9a7533f368c279e8bb52fdf4ca50a141b16079bb77f68be877b083611df83e46c8c3e61c785020e15569ce4baa9620361ea612c9e3c084dad83bbe5d2a028579b066a20401868c3d450f2d101ab5abdf602c43843728a05bc38138905ddacfc8e300870342a6577eeb1d5405ff39b558daed27ef0a7404b34e161c3be0e2de5269c74a5bba65934c297d1272d9c69ac4fc207133a6930a25293478411d93c0ab180704e91b7b6ed5590d9c363d1e1d1514ef84401ceb49595ada81345283b3a90ec25df5df607898895676caed37479ca3d3b3c80beb630f00c1dd5c5147981a8556abd736fce570bb22f7996ef9e171831f1ff314c613d601fcde5bfef0d0a4b4e3878377caf4d5ab900b4eee19311efcc5e1f360dd60ddf6d3b35b6e0785a15f9d9096bc9fc36c4401ff7366851f2b0e615fed3fec5ca26102a882934d52147e764de9266bee6a5a0b7e4dbb3d1bce7bde98478f4d74cc91bcc29c2e9b5e6c76ee59ef2838d40a24666573390823806d534b3a13f38cc9a9a0ff6c37dc23b88a83c56a3345b31ffe8fd0f0e93c565660a1919295c92e34c62529d9d9e143d76c788bb8ec965d0c0fc76370c21a0225303bbefea9d7277e6dbbf00bca977a98cb0b989ebd2e801693257d782378fbb2eeb7773bc7d848a476b6c0512b383327c34968bd4811b87ea88404896d385b8797ec3390f4749552788c4fe2ed999a58bfebd1ea1b4b39e6f67834738dab62a4d147cacc1b4a921efbc208c4cc20e1d988e9213f55efca077c2e2346989ef456ad8a24bb1c928051da13ac7a75883fc3ba0afb846b1dfe01fea53cb8e4c50d69967825cbd0ab32bff26b1d829792ab176229f26d751a1c4a9e67d8cf13f2a864fbbce5a83199b10103a6c68ad6407689ed31a475e208531ecbef2443eeca1895a48c37b93c8458ab7c5e6dbe840920ff24089e6c29dbabc3aad63e820542288618ac441f5f7a58f0479094770a2083faeaddc033656d0aed96ef4503bab29a15948fb2be62d618f18d33100bb02a4b7549a40b85f2b9047a6667dd9868efa93d0c3eea9ba8b7c8b22c16796ab4e4b7c6e21c7b61b0470e7a6baa13810915c6395b9a4d8f918dee0498c7691364522648a10a5598a887142eea604dd14a1ecefb35a7c5b9e46fdd79eaf931dcd59d68645bfd89ce00c1da9a451ef76a093b959725475e6e5184794862bdad8352008bb3d5b3ba2895152ea1be55c7446c4636521c5fd4eba6c5fce0a724bfaf30811ecc94ce140d6e9c833f00237d319387fc1ec778df653f48ad2d95e70f6f88e0ba00c833329b0714d4ac925ebd92295061d18a0178c5a20e76206bf6b7124e9eaffb484b1a57118ce9c997a24128c9981fc82751a845bd11000e870a427ee1b5b89f0f87ce36d352e1a3c25b0f1738c738932260d0e8f437a7ab7d78fe039c874853a435c98254f33e8212ccb2e20c89972d2619274376b908b0684014066dc2f8fb90a06f0fd3e54745c41ebc9e9a7f6a15bd26ea0ce92c4ec054b8a52bb3c4c248767682cf8968c824d68451850e4bc083e354b900b9db08952e8e1b7ccd00829ced2ed78c4ec2bd3c7227457120d6a92066a3b03ba3513f47621d2727fe9239b658e22f93afde57ae84e2c89a01555faaf4547fb1a6a7850a2a28010db9db3e2ea24e9ac6c63e0641568b808dfb07f7b8b528e9dd37cffce6f74f5ef8bb4e99d17c7eceb4d21d1f6383681bba55ae6017446d8b0f392b9b2131f242bae6937242e908422844e2746299adf24095790273965151ebadbdd07662a7fafc2a813293200bb741bf4def2851971a7fda48533521c483af508e2850bc313ae8275eb45f72a494caa119f1b33124399044a59166629873f048e596846830f91fff4385e351c5c8fedda5f38eb1d3aa83b02d4b37db0affd0aa97a0b8f90f20ac1d069b49f0899a3c763008c022365f51bbefa3d6ec05a49820aa7aee2a1b19861a5390751b2258b1d40e0a75d2e1125de50477820353f80187e618f5f1606495debd770bc3dd6a2b2fab9d02e96dec67587d35010efedf0679481410bc324bca07b255bb02f45501cdc7a2f0c0a55ab75a4ba8bc489c9f1d9ec1b11cfdb7bc7b41f6818f80ad0017f264c1547af0949515ee215297faae5389f54007d608338deefce219ca1ef98c3ddb19c48a9097fbd64ad7cadf1806e11765054e90af1e7cb258e2be3ce26b47fe176aca9585821f4b6bc5dbf810aeca6f99c6585e81897762ddabc2022923fe0399ebafabc44641a3737942bfd2b5b35d68eaa21e66a4a4b2ba3f4024f57750d4ca708df45a474407948713219d4ec3cbd02a0de43f365cc9403ba9843c6e1b22f2f53e894bda1a43a13f006b3a349e26816fc16c47414166cb386ee71740a21ccddce0036e1d9f08d3803ab46fa078582fd1bc8f2747cc180bcb45a63533d51914528df3d68de70501e0e5d18928618e5cda33798e43fc7e886fb6ad736797507e57b29f185a9df647ddd2eecb0c07a2debbac9fd44ab3bcf1e7b567212e4a2e07f41e9ad2b17f9d3ca386c21d6a1fd327f7f49695188448cf327192de13dc1d02d1434bf55f816d984f0518c5c7e4f36dc371bbbb3db296f8a9c48e87f75fee8616e5338bc3b817ee0b19c8765cdc02baaa4a7d4eea4070c34a06eb83996a17aa01be2b5b241b3042dfed5d78249d7c0b291e0bba596921b0d54a69d56935ef3035a0d87c1c41120ceae981269c90b495c621485b1b248483938c0d22099cfc17cf693a92a71827d25a0511a1a054b3cf1407e90686e8c8f59f2c600184cc326d068fa9b0b34d153417084688b62a7de0fae6527e298de23a42b5a4d7ec625b65d5ab3985aa299d1fbec038ff12ab3ff4a159a6130265155c16184d4698fdbc76a39846a40ca15ec723db5f7190215ca7e1f8a140698f16687e86f5f04000dc0023a6335a16cacf1e78f91bee5ac8134ec1486ec2cb86c5668beff48905301cb5daf3fb31b08dfaa98e74ab0969cd9642e0d9defd1e631ec12fa4dbe0f6bdf2585fc0fc30cf225fb7687489a873d50fe6eb263cf66b009e7d27bc2d0e3c49b69ca415d9d30a290c6c4f3f89466102a800966f01e0fe67eb565b4498bd3351ab0184843ea66aab2c3f8d4fe83707797e3372d92ae4d81660ecc99a754b219e4be8e2a2f2bc0a767b5c88e7353db174175299091249acdd1084ce36704888683dcaacc15293784f70b8fc54d9a4a834400bac2cf6922c95132d361abde9c2221d661b892c994793abd3b100076211bfae0f65352153cb54f0c5e3aed4494dec2ed1609605fd76f35a6cc78be6b74110fefdd4b75298d3ab26d1e0748aa20f24fa7c8f8ecb3771ae76bb5ba1c65c14168d57683b734565e5d3fbd4db491aca9cc5bc4d4c240812826e767c33f3d5fce3e2eda3d9c7d185d8f206684cecaf1218a1bdd659c40f6be3b106694080de04df625a22f03dac875007adc48baa3e7d41dc91e61e49529eb9e59338db00742fd6ea397b634edfaab91421a78d1a1359460b3b8d7bcb515cd6470747e794663ae42c65f1e8bb90ec8fb207f675831feb2280ed610d47dcb23f7f6ac45b8f9fedf2058581f2bcda3a62060daadd0a241d374dc676390ede81d0d4869693ddb804e1436c5d421aaeb247f3f9e13d1c66f86221d9df3709c6c901343a84914e52957feb1200a81420abed6532c6292c742e9f54520188e52a303affdfe7aa0c4f289db86ab2a12f211669ae02ff0968b2dd076017314eff3ea21b95e190e2dacca90cc154ffc79a294267893963846b7a36db7ab6c6d493368b1fde02ededb35c266c489e8b025e97d839de81b7bec3a4cee350f486c9b4927a2159ea73b59e50882f2e257bbc148ab704056462cb028d6b5e5639ab027e6a72bfd083051612133c40816fe77036e0d1917781e2589fb8caef6f5c61796c26b535640cef7429734a8aa3d02098fd58df2796405560aeb1e9feec9f18f8a01f0bdc465e4fe3caa4e2d2af09712d5a1f5ad1dbd5e904ddc82d3f7705b8b0153df266fa98c6e7045b31bec69e13decaf911f57056bd5672d4d86f83a509dd9ebb193adf166925a9d8a55c2d9be324a02605b9fdc9c303f175a1868e85b82849a7eb73bfc7174d516091cb7da1def16b11af336f407c17197f004c2cc41c63b1ab84b6a057e3d8d1ad3ecf540c92b425d2ed85e6b4575843bbb6adc59c84a3054f4510b0a6659ab5039543d9890b1c0b9194343ea8901c1dc33a6431867edb6e318f11b437b41fda5a2b523d450785678242987d3bfcc4dd71a1ea414079c3bc4ec3b4a59d3ced0c21267b0555a209b40bb7d2cba68a0859a02b8872221f36502d3a42b2dcfba6cf4928697de1943aee25c93ab21f6fbc944ed17d4093272ea80f0641be98f7512946bd421985c20983d7e6e21a0e3b222471a6af7f4a2ac61dd1390e9e03b2750950d2240d1b2fc9ca8b4f9c972a79140224f084d405f277686bb635cf69cc39c8c6474847f9a3a45e039d81f218d13e0637151ba572b221ee6758dc4ebe68b390ac229096f6625ca171b89ecf7ccc575a31250ff70228b325d84e4ab6b75e148b16c49d1fd2bc752afd0f35cef868def5f300a1a79efc53507ec0a8437f84aecd7222c3ea9942761abfdf0484f09d24c8fb4972a90fb0b435d22e0692cf9204f385e42d17546b1df6120bb9716bad50b09c531a634bbfa165d81f63f7fcc1129253f1849f79215002a101c42df76c98c1e82040c9e4706dc722c9902cc45866add3f4376d0712a95cc64b8108c4db73faf7237cab6a74841a68aa6ff88064d63075bc497ebae40b24c88461145b8f33b96eab0978c273612cf7a9e8f1c5d0f86020df2d79bcccb3a291629c50e8d7658f1fc1b755579035005bdc37b254d34ca687a73410cafde357801dcc76b3af00b4977c93c8640af0695c925c45746293698c2c918d2311b0a9d2ab10ad2ec6e2f8b2c41f51515503b741ae06b9cf38fb0183d264cbe7d7d6eb7afb91a0e3ee0e77d4e15e8a67cc6d0f655fd3336471ee2ed21a0c0fde7cc99baabe1383f04cb40e5abf2fff865dd076bc32942ea3b519365d948eb1593f14ea3ca0987be641e220b56b58d7c4a8e03baf080b024763a7a87cefb125ab571343efbebd2843e07d54b8e04b17f2b6117d47d8a188e1d081cadff3cd04b9c2efbe4d7eec716f99bb63a29434da443fa36d4877000fc22dd770650f9ab205850c591710d367d573322edf0a8992aa7fb0b30185d3815853a4707a0beac5b089e9309b8617af8d4d052e3b22658570aab77795b376f07b440f64f870df9c56989e2d672800b7189348378e6e7d7b852f1b2de6f56eca6ed35108597e195cbb5bec38343130bcbf366f9f6449e36d4eaff8dfeb1d99a8b2b72bd6f0f8771a88ea9cdd990f9a2763699e750d2571d1ec65043e5943ff700ece5d9f950695e6d36c8147445f6c0ac7c9e0a514ee873f306096f48036c47599feb4059e5f494d89586379b4e8d6494863c6a2d46ced76a44fcaa7534b7700f70999ace30dff367bd6a5ca838a6f49e856cadf942d4f7578926d0e4a1da2a84945fef8daa3fb624562d4d442154fb45c6118afe683514f80d7a80fe44ee956a7f716b981ff96b9767f3f177ea7910498e9443d5ec714424f785a08bf317a3a0720cee7a7b1d2c4f26de4b3d3b9eb64831872278bc6b1cb15f53c34d914e4d65e24e7039addcd19269e5671f12ace078ebdd61514a3e76b94cad457cb47508dc695432b03bde74c3bfb9dd0ce1c4d1a9c7cc43806cf58886bd0c1e5ffe445ec68b717da9b76d11f6f4f31a68215f595d183b0fa8891f64e54d565b507f75e67b8784a8f6e1f442d8ea01e38cda7e01ca7276d68ffe2fbd170afcbff611281f36496d0b1536f01169300f3e8abc35f5e75805cb6c66508b2a899452e081542b93ef563ad972db88a5f774cf8049be823f7538baae64354c562c46bce4a10c09d9417df8a9a37afb7976c5d9a0e67736bc25095faba797d7aa50176ae132b1acbbc91a5d249e7e128edbb291a6a398bd4b41f858195abb4cd7de76423258dcc8745fc02db89e1cb5415f4ae7d0ee58fbecdfcad055672d8cd17e766e7ee7b5355f408279494ff4347c10d27b19ad3375342c11cb5bcbb0f187147237fdf3b59510cac24a1b356e7e3648b1c25c564e8b27f1269e3f669f9cf0232d19c7208565b399fb98c855d99e163778c08b7c51b2e3a63c17f8341e9ffacced70ff3042d54c0c773fb7e5e505e230c3cbe2ccb82a79dd7aef5aaf2b22d55ea87db41e8ad677693da933e172d179accf68021a76cbeacaa0c7f56936ecefa723b54da7ff8f396c013563d1e613f3478e981c7ec800e8809a3cb081a3717da7f2a51b05b72955aec2284763773d114861c457fefd9a260d96aca2279f3d4ec98cd72ed935da408d0a75b49cdea7938416b876f93aa29f3a09aa56b1fc53c0f24dc90231656fe9b046b93a17456c67e339fb15a09c86b507a34678be9aa7fa41eb473cdf4ac9d7c3cc864fff763a291178e321ba1b2f61c7f9ef2063b82c7ea23bb65e0f69017121d613ada9be5b388f435ab34f94bb0d88298cabe5c19c3c28ff17a4180aa6baa23263e32700e6821879ef62c1e75c0f36ff5b08b98b7350799854b8f957ed6d23a6379c2986ed7197740bfe0fe71733a4057274caccd5a958346ba0049259a6777b6607aea35045a2498abcd2f69e937346bb8ef0d25145b1d88b3395817b026db95231bbf31a76df57e883229e4ccec5bb379ee38215fd2f465caf4714815031ba00a1a7a0784342c2245b3dac4c4b30570dac44abb7d361d71ac5fbddd40a35129593e9f5b44052b8005b3ba25d9e36913dce715faf4053c4c2e9fa72e503a4875363bb4a1495f6bfc37ad9f656db5d4aa92b02db651eae47cca93e2ce73ce437c12104e35e6cbfc8bf18be333e26723fdd7d5c7fa8a731f4acf1c2ef0e75cced39eb147d9d59c57ba5653987a4d14db2bef431d7c77024c59fa65f8a959f045f98f9e1cb830d9e7372523893b2e0e756a2573da8bf3b62ed9595bc7977e00dec532acc96ce9764e436e8a8b42e403a525b4d3822a532ce6b9539e91f114dc268908a28d0e863fe5e822ac61299bcd1f85060950d6d0a84172ee049dbe80e7b2d719339066eb2a7b53b65f35b3fde6ffe793efa381d68ba0665d03a9fbe3c526290c865e345e8286ab6fbb9417ae3b60dc2c4fcdbc014d2e38bcbcb61044690e1bc4849f4cb4a44080ae2832289a4ff632bd5177e62e4c0ef084ea90d1baba0abb6f4c01db09d125bf86dafeaca4680fccdb56bd59222a8c12247853ccea00767c5136c40e22f73e902385fc975fd282c83d962448adb43a0e27ef02910c4b63598261b857fd64e3111ca7fcf4d751e387adb0fd7a15fac4dde77d830768474fa617f52a87dd38ffbc6c1f37270eec7cc7364b81af0971ec6315261657c85b5ecb7b4397a2163b972df9d6e066391dfab9b323052a59c6df8a892cd8b755a754debd45aca90e858c4e168d279bc0c63eff6b9027b414b9b634c195f1a7e6c12055edb1c721f132ce8dcc8a7b76954af035d31f8e7f80d25c302ce81ea3ec9576a082a74467ee14d88a882d8bbdf78fe5593e937485372ff191dce4ee8cbdc74fedb5a2f8fbe65586b9d6cd76cfe6ca2be48cac40ac16d8168d3dbf59acce5a177052a283609c31eaba344bac68fda7b2a8322984eb14ac996fd1117826a656d6c3417f60df03a1da0b2e73387b862ed0bf2f228d8da25e5fb7701e0d78027e8a07d0ee3f07122c5fe748081e99784bcb2e04c0825b1f22a0218cbe7e09a7dec4d0605acf0854446a4eebc805aa388ba9df1305ed94cf4300ef07609686b2bd2e2ee21b22bd9a42e7c305cfb7b1518e7f05c87282eab28694b72415ee558bfff1e386ab45910159b5eacb5c334793589d3080ea49decbeed03ac539051222ebdbe3c9e04f3d3cedb2d4133fc31c377b66b31d8f5b0e55a000b1b5a8f9bc5e8ff00e1dfe53e4cc0c2c5f7c11f4f0d52115ca95858946451cfab490a0903abbbe94882fc0ade2dc03b3637d1d32933a898a977921c14b9e11157f4aebde652e354f05791efbb6f3e8d22d366d033babe9de7fe4964a1cefbd4a74862683f33f41219258a1b3f6462d5ad35b55fad969f76799655c4783ab076981bade6b92ef380e1cfc23461d589b3878dd7255fd9229f2da312689b319eef969a610910634eb91a81ed41d0f411672acce81c69d28d8c07186be2da0ee614cfa9c87b3911a03988567473db90e3cb0212a9a86371c2bd51d36a447798a7f55ec27baff9422347cfe3aee0edf7286abbafe32df0b1ae20c3fc27ab280135f6bf3c85d5fa0d7dd665f330b7aa3b91259d4c52da9ff4d405dc0ecafda8e535dbdbeeaed3a5dd455c1bccf1da90a9c66f950910cc998fcec6955b7f40a96caf35a88bc961a5a5f37c29918642de86f0be1e2d05d52cc64567b9c55c02db36c5d042135196f924d91b1546e96aeb78d9666e518e9e1463754868f955e9b8e828587a6b45aeef25b9e5cff91455dcd918a8105a262efa1ea269f6a31c42ff18c8feeffd1c3caae9dcd54e1df45d5b97c67966d12ef9c13f5e1aaa605ef55e1b4c52ae3e98f3cd75e970e2f2aad6f790a9a3f2018abe8857d08ef96cc22a3f9911a7971004b6122219eaae16919496680312b141d6e14b89d821105d8225daa6eaf3a4afc957c1cca4e4d45ad2e989bb45b9c40e547c453cf7875356cf866517221da981a7b5d668d8776820aebce71f1b2405dad04c206b797dcab79fa0f770bccbe12a32d8e493cfe19aeaee94f31b5e1da4de9d011f08ac413e117fce2123170b3f823dff465f2d96c97439678ef7b8dcfd4652a14ffff3669079c39a8fcc58a3d348c0a3b4ccf64a5d2a116d5cbda3faa7a6156cec5bfa331800c9ca49e567a5407f3d67d6a80107437139c2bc4df133357484ad5e77c1fd3a4d3c4795a3ca2b1d62169af3e77dbb5f91a427afc93bfdf91842db461b0ce9fdca4c753b471cb6482e0f17100440d50e4fa0a9fa501c96cb6cc4c8eb43e6e174c9b8f553dc71fb349f862d29233e3c1d23ec3ec9d0188100eaacc22ad690e31249df02296e48ad64047eea2c7837686d1f5e7950a274c40f6222b50a02ff6cb54953a00168a90bb3e4540442534ddf280f4e4e8ecc5ff225294b1c5b31ebd20226107ac163d3f4c4ad9074110c772bdeb2ad660e47ac3daaffb990efeca8bfc93c7953a56a03824cd6d5dfd1fc6034f33674d2462e472b402678c256f0cca81a40dc502c583eb143cadb83fbd852121ff3af2624bc992aae71a5c7b05c80c26dbb5b2e236d4bc98339cfe8282d37e911b315396f91c79caaaf477ae6827dc5dc8d010ccc83bd295508f4fc0063731de4f78126d3415d46ff19432eb946ffcf0582e37bfa26f199cfdf1479cac1f273c259d6226864e24a2a76973db46618aa4dacb57a59a5d613d4a7e806ed5c5090c0a9bbafc98ac71da1b78ab4ab3ca57952f4ee414a063d4a3f47e0f465a09032dfe049c33767ca741453f478a1021882423af613a9e1be4891da27725a4d4f4e203b22b300a82dee3df319c01389868790db6f0c4e982cc18a9ac81e75ecb7d87be1b2acb821af986746844502eb80f4c40fc76df5dba3eed008763f589b273937f29057ef973e40e5fcf153c52595807c129d5f973b9bb9000713cd0e92bf2917f1c571170c0abbf64b35cffab368bfe4f9c698a974c806d1c2aa3b62037c87dc467572b18a09fd6fbdd4a43834eae1700f11f3be856cef8095f0bb17ddcda1b927b4ba65bc0ba4f5032da9ca507960803290771c2c259daebd2f54f0f0b0a12b3e6d1a12c84398aa439c80e5d545c0588c2c341e976673343b9707692d9abe3261127cf2699e99cd5f921978e13d84479b6c8ad59c9468638d14a7e41a3fc24ceaac40277dac33829a44a27418e11acab3db319a308a662be8de344550dfe87656d144dbad54989b811d9520df9f43c81a9eab0b929e0f83f026c9dfcb6d45aead52f11ff316160b9c4e4d9d4701320ea9d72bb811772ea13ed245c80f0e065eff37b014c1710b690600434e97af00e2b9090e84e2444135f4c4f3c4fe6a0f77680d054a8ffe97b6aa2c9d8cd87bde17b953d154a9f290a6c554867db260730106f5d4b512b0eabb98420c8917aeff8cfee184e8f74541bdddc7e7461887e117d8b513ac77fde3328f4c5ee2e73efeb97101ebee72b54853239771d29b26e45091dae266c429f6ffcd4cf2ce017aa1591da36e719d3036bad4cd7fd64ee8b736b0ca44c0834bebdf6c0c13294c642559439f6f47fdf90257ed9f0be4fdb009a8c84776b63f549fe3776b0fb339a69ed224a12b94c0e444c7ba9518e913f6059c0067cc933d1ba58a1542ec885b2c6dbfafb6f092ec432a098868434ca27d5c9603169a8dea9b60c9e3cabd3c80dba8452ebb3223e1b694d622b1b96fb76e920b640e759525276fbd9877661356182948480f53d0202439c1ba27abb1d7b4e89ccf94fc87f825c972547e05f59ea778b25460860a5386fb4d29e07eab287bd460cd8aaa54021932ae04c680004cb70adc9438936d3eb7b1ba7f3bc820a1a03b74bac7376e3fdd0417296ceb35ce58dbb4002a54b4ed7408c1434d8e51b6b84dfc5e13a11c2be838987168e82a548ee27fcd565b2ff16c263ffae01b65ef91e07d2b4842768353b4f321c412672a46b876684e1a1aaa1fd607aacc232c76d33c799079cb5ef1b58a2c24984dbd7b8f8e6e3d6d60f0176e89bdb0c3e790996e214e80137768c516a38b6e0f32c67936840176dd6e7aa2eb4858f1c75ae4062bc9dde99651a0b76f4185daeaa3a574ac7a2fc06c45676aa5ff689ef17cd413b6e7e239b334f0dfa7edff3e195392889b2cd1de26f6f0e127ef370d608732bef2c119b3475ca117f0d4edd4ac578b88bb40b5ff24ce1bc73506aee1312c4dad677a3d50d5137f6c8f9c09e818e129b06ec573a0ec3fbfde549f0090e813603016f468ea56d05e2eaef5ed181749aafbef24ec7d98bd8ee601cea9e2bbad2b86e754c35ec910aa575ec2ae46ea13cf11ef06caeb70e62539aace70aeffedac6c0623b0f5d5d75d64611a8db7492a7c56726a4f6fd0fb591c9694f565234a096fc8c54521531a63173cacc29762ee931d7637e68088b167e72150f7bb19c64f59947d0d014251f9a68f72070d4d6d5ef8d544c71e706291aad14740e39a44c828c275bd2442e7f96069f949e609c782664d50411f01e8828511d67641568175aabfe425a70f68cc670dcdfd84669d2ee9f6b62519a9fd607bacb9536eb56589ef35c58da7735559d45602f9c46170d8eb0a1cc94be630ccda314765ddc23b8471be24afdb08a3513f244b341851d4e24db1bf1d7b21ee15713e5624d6ed64219c45a00b3c7053603f5c8129e2c45b23cdab726e897016053bf32785a0c191b7d8a175828ff1d8e99390faa5923a82f303dc1597a176436f505eefcda50571d9c93dc7708a5bf4998ac4c6f42df01baf2e024da57d7aa206a407d050d13ad43103a8405f7986dc717279b5f42a8b748e656584a107559da0737e6f058ca730e15ce4b385a71bba04bc4fea48f9449cf9dd00a13a2079b1f719bfa8ded642f456cac0cb990ba2000037b8027f7d54db0ef495b081985f00edea68255fcee82ce235caa0e78dcb421e621deaff439bfe53387c94a6e253a942a88c2d2d0e5959c8c53404ab63059615ae901d6bce5d9a1338fd25a9ef0c10cbda90f339b27877f563f4941e7e5e26bb5dee42b3d70835d9980c3ac62bead77e1a9957baed2873dc1b24c516febd99a76f5f04383390e93fe950ab75231f1c3379ead254aa109d21fade2e905e11f6cb7c73d6c66b620a6fe6902e728c02850cdeffd939679ba1c355a155c5fe2e66a7407ea1c48e5d88528388d2a49a1a7b470144b254baf974eed00957a7f41b2057f26f62755988491fafaf5f2e27b063f3998b3aaea419658c23e66f3b0c6cd19a746f419d17426691cdf071def4c0d113942ba34b0acd730be1b6fcc9894887effc75af45a36795a09677438af48d2dbf06f5cc18d548be7f3aa657bf8cd70392843d06befd09f5d83da806a9f86ca316680787aeaaf2863ae5a172baa9b1a00dca464680bfaa903bded8048bd33a6a3491c5915bbc3af2be01d064cf4723a9229e0d69a192a7fe26908193e7d7ee6bd28e32efee2211083c49979d2c75673e018f51cf81a6174294cd896625e71c11367991b05b24f1803dba392413aea8a14265f531ad60567364792527870444ad8ab7508b38e1dd089c85242013b41903648ea15bdd8e9659e54801fa059b89ac5bf87c4cee90214229372fce3c59df53b45f7509bd1e27dc7a6172bde8a0941edda080d3e71af1671ea2296505fcbd225e14fead2c2fb948065b976638183fd605186b39aacdee56bcf8a815f0fbd1dee2d7c3a0adebebe6b3e4d96b80d864bb48b4c5c3b90d091a18113c275095010ac65b04626f0e42d0e8f2149e7164c5f633e4930f93c1cd1421266dbf9eb4487e00bc492685aeeb67dc0b3f323df6b937e38fad5603df4de2164b2b3d03dfc80911c1f6084157e0b6fe6a66a6f959a1601570355c6066e6065081ebdc826b7563eb54e79622f7212945ed8afb3352e29537b7a399512c68e9a3b7583480dd65f82bab1a87b0e2b25cb3ecec4a48b886a13b02aaf5a94c28cb9a17d61f45ec88fbefa19920f1beb4f7db093699dda021f6adac4c1ab68224d12c4ab8bdd58457bb2b1ea5f25ae8d4741aa7812b782517866fac354f5d0214775e08451a93845541a558ad55b37a12bb5c7423956f56db2639401d6e2409b02b21d4ca38cd28ae72a43bed2ab03083d10aaa226f987f77434addb9cc7c24f7a15366cad387c9e7cd48782d2e35e7e8392ff855166e0211d3304fb643db33c8f65bebfb4a5b63962c581c316e0595aed49fa89f21cbcddfa309b77143405e8f49d20dad7dcbccf73bde7144b75324d7f6713b02eb901e47d8a684a886275f108a47291712f8587fa0acfb3a627dc6823ccef6c344b4d7ed44f041007f7cc1d6c6dec32e08e6e4e836d27ea44c6c4de3f5b854832bd2281d7f3378bba9a12d8b83f2f361b160d570d777cdc8e403252c246c479b8fa6ceaa44cb8702fda055db93e1b11ae1877e965c62284cdbd15598a0ef9afc4c8ccfb62e5c9285995681cef5c7de4def96d8912fddb4836a90d36345990d6c18dcddf429766dea55d08a73b3ac56a97655697dd007d730d9cc92fd5b2d7878336482ac3b8ba5ffba190791631b981d885cc9325a30cd5ff2065fb3d2f15110229995b8323bdaab78ed703aa0d8988a9da6f21fc1c9ea2fd2632522df07bc9a40e1f12b600c82f5d64769bd7fea70c266208439259103862aa42379e982cc16528cb34999bfeb6e08ba9d006bfce5a4470e9d61e9105bc46026aa0bf4f92dae797ba0b8361e9de7ef4bb93f4f56f418952dbc2b3618a639ed4975abe19b2c0dbf2f461546565af5695da9978b2ac54484abae411cb534964336bf32f442f2525bbed8ba1df9a4bd381daa96749e1222fa56416954ea96d5e6ae266751cd292aed0b5c5be154f6dc335888116587b2d5abbd27405b67d1ebb24d41aff2b1759489facab65d7d52bddf438adb8daea66a6fdecc27a80727435c415bc395d1e3cf999bd9d0a632b7d56876d5baeeeb5448a925142f7a8127e2c2af533965fe58b0a01d493353ae3f0d705aedbdf921567740f3d928d1f510e78009dc43d8f403b07fd4903b0abb3635c8289eb76ffd4a64cabb828c2380e2b201c0fc1a1fc1014c237b93e311d84a9aa5a065adf50057fe7fb3e936728932cdca528ef8cf4a6cfde07de2df845db436cf4c738c1e0cbe8b61f3cfe9ba56cc53a34dca60f2c8e1759941e4c17fea185ffc152a7f7b531b883a03a5563c925c65558c3b16a37d11a8a0903205c9acf98a9e2be9e80314e6e749d79e9d00f4c8924786b0d7f192491db665e836496e90c5df3496667f9652614bafd5820835bac59a79bdf03761a7782228b1125eb8a30b38196a44aa609cd2b5fef9a4be144da917b4acb89a41774f4633c6e378823e1f97dc48b5ed8dd3de1685a1c00b0ffb0254dec6af722977bae1cee1e3fb9271183630065711fbc074f06e1f33f8fb005ef54090d0b63e567ae2565a30128fba0826f5673ef6e8d7c4749ac1313df59e75a10d7318178d8c62af11f27ab5016c0913b141f2ae3e67bec5d74e29a14f031fd5cda177e34c5c1a475a0f35565b469d77d725a3e79d6f602e809086b58576a11ce8bfee66c5b166a3a6e01abe2b64c05b6e0d3bbc9bec41ba100a3d858b933a4224ff84338e3d8de52d40d04f141541e38e4ca3d757137f7c39b94548ecf4ef44f5eb1c6d7c8530f1ba4352c8e124bdf80b8d3360dd5e4f7690d609b928f8f660427ef9b02934e750efc568a4e107bf8d24925f9d00fc850389a599e766c593a28dc37a5ad6920bfc9a6b8b0ad3b01b837c2148d5eb962a96506c74b05870f127d79109b8ea4bd97f87d4e5aef221f35c2dcceba6bd661b2c051cfdd93e4baa737873d7287151e8e8bfaf56d15db2cef8f9b711f20f3c3f6aaec294ed402e4f5427409adfaaa26797f168d6f80b35b9727f915deb9c27bbdf87b0529482b146706fecf0baaaf4fe33a7664f668aab32f0feaef0447086a43734c22b9e764636984d950e7eaaf0d6a30c6d82d6bb2e332817e5a9887d3a8d46411c842e775b812c9cd96c142a347b4a4bff22ab68a47d9f168a8ec4c534a01bb6cdc85bbec2e292a8e8c8b4548eec9ba6e1194a2f8e23705c8c4c1730ec4057ac2c6524a579e133d8c23e32986bfc9595677fb17d9454ea19237a232568a6905a121cb100138d97218c67bd3e913e81988846d41a0cba1ddf0152e61ff2a0a984ce9fcb4ec4e9247d4c6208b61be7bc458c9029301dbd2fd870bb391951520f6be2bfc5bc3f2a0f68901bd1ea5e2f963e9a5266474a20721928c43e1520e83e4535f95b90e0e725696e939e71a4543f13d4a51d133b0586d201974f052abf7b21dd1c804d4c20f2f69ce072e0ec15c5ba978907cdc04b9a11cf8f01ced01d33e12371469cbf0e009472ed31a34e7311f9e47abea68575d722a4aac8ed0641b790c8618e2a3653e0e13e051dae53db7700fda63d6abb18761aad556a18aecd612292bb841da82370acca050b64461a779b73c205ab67f697756765608e1c16642b10c461783417814402cf9355a819d3c3ec73618445d9e7c4aed51f80fa74dfde83fe16bb5d1accd44c31f72976052170f5703c1eae445dc10fd688df6f48dc3842772a2f3e2c2033473f1aea13ac4acce172082732d15008a74fe632b30fef56f86538a1ca5905a24daf9af0872c3308922bfd346e9c35ecb469901260eb556664255356b39e1cfadabadd961597c9489ebf9099407bd2b383f217d37004ba26b4f1ba86908cf7d328f22be09222696a0023463d076d31b6994729aa72a3f3d88f406972d812ccbe1c7a38363bbae2ec5ad7124def30e712fd0d1b800621a4155cbe0d738356f652ada9792dd1cc245b44eea11f977bf886fe37a02a6f48e7996166f7493775efe0f5bbfce11662ca272862d46c279ada9368f95a56ce8e1047c0c93638f36d973d61ca02df4ed71e97cdbfbc961fbf9a7830cc5caa5ff247ebe806ae14bb4a5f459c456da13e0143ea89fc43227a4cb97a312e681b845d73ba8c5a58925d6a484e38da7eb7dcdc03a7ce765e5ba79df552788ab7eb18904202056092260721a4a8aad280bc5f7a46095da23ff537fcf8b28d8fac82803dfb2c02f949fd1515ae59641d66fccf2087a3911948afcb37af74bb9a1074a19579b1fc5217a92cdb0b1707a6b0bf80b9229f17a9f1733811c41556bdfe3cd423609d5bfc0a22249b37ad51d90cb1128c7dfabbeb324b91ac819cb142b7f35e9be58ae0f75567c477c2e6ba71a7a322a96197ea9a05cb313d8346ba252cc6ed083d8b380b3535b80a79da2464bdbc212a1ca658c5a999b459af1c0c2d590ad85cf4ba5f249c1770f2459b87f3db0736b9bfe069427cede8c1ce56dcf257ffd5bcab2bef0b670c5fd56eb32437964f8db77cbbf926549c4c12e75a2e7bea36adc0b78a23835e528bbed7d5e014d9f3ceedbf2752c83fa8a005436db81d3b8060ea7cbadd2e5c4ddc703e8a40e4b935d136374c8d575a29c2d95dd34e2120276c539313ad77b52fe06c299d28070f0c200e81113d59a80cd0552ca449923e235aa6bb93e6df934fa47d9b48762b4b13a17c13b701015198572bb0782bdadd3cba94432b03e99b2f33b0a4859e552436c8d0af948f8e3d0f84522d0b133e53625d16d7520daebb41241769f9cde70c7caa39d991893a010add569ced076128b0dfabe406e5bad751aa641c14121133652a2292f9cfeed76d1db2e279d8581763030b0ce19a593c63afb60c9c50d78abb8f405e786cbe01d91f32da4573ab0fac663794b07ed25f73b98e5bf9d5e668b46a226f43ea455b2ee5c39312c3dd3c656615d8b11891f1748d3df4fcad05c189284d71d03e0254f67981c5384caf8a4ea0811ad9889fc15082cbf413520cab5410bd479f365968d6e7b77f3f1bae6b181b8941a427793e6dca5bf07c25241da0d1e467aa9bf4c8fda2fdee97cf67fc60bb09542bbe03f40f691470b10f8e2d44ed22ed210f463d7a777a98314f5354648a3c471805d997cc841c5ab1bc3f785055ef5291297bf98db3a7fcb300ea7bbd984aaddea8985e0fa99172744a149fceef681890e67f2ecce6185d4d06bec62e41b0a3425c4d9c9df9ddce153dfc41ef488060c7b4557a2f795fd30b89f81e68ceff13a59cbb620fadf2bd7b0a55feec5ffa6f3840527785a9979f8a75a12c770a6f22b775426772ead26c541b89b3914710e1ec473a9ab727a6a82bf3b7f65db86419a7a3d13e0158ccc574d25a58af67a0463ca5d817c18c5afb54c13609ffcea7638e402722fbec74037b05caeec3899747f83833be04e1b1cb9ec9e2ad1d3e030b7f0bdf0df123caecf6458dcb5552ae7e2d7a651dfa4360d00e46bd6f5ceaf827a9b37bc7416aad0b17976f9e99e7c91828f084c4fd96dc08829440ec33b3649500ff20816e6684453a286371aeb6c919f95dbb8a22e613c0e145f4168c4e66acd29a64cc9bf094c848dc39632302aa6d27c3392adc81d342e9b44e62cb1bdb8a6c1506a8b1fd4cef5ee881863bb6b60d54fc2dd493674318997a7946564fe8d0966a03589e58b202215b21e360741765c7ce22e76f7517152a0f94ee552b1973e2599bf5364c4ab24d0fb5f4c151b566e7c0c78a1a67f4a0964734facf7e25487ab528ed0a4a810372ba59cee5b8610f30ba1b514c65e4c0e849f7ee3f797f2d3ec18036c836a0c955d814683cfc2f1486b7b3e49cfaaa227a52ea7f510db385dabbbc4232550dde6b88355088d56e83c86cc562b4e0a3f44b786e273464af5404bf04ba121559cd2a0227ea4db25ba33386633284f22e10d0f62909d7afe8a0f76a903f5467055f42bc7c7fcfe192fa2728d9bc3c6b87fa0a3ed3b0e4b71e351dee29fb5a4d955fc487b93b3462404efa150e05d6141e27c8dff287ce47bacebc72cdad3726c8ce7606c4b08465485b0695dfb6bb1d5f1327af3a3397e6c23cf1c5a76c8537cb1c73a47d5e68c3cffd1302520e887e4565950382215f0663ee5d80e5f82ace3b2a6dc9f6191dbf32398dff39021471eb917e41453da908a98db18f5d122d32659aca393d43b7a91c2917172d4aa459b9a979101b7522053b61bbfb4d7c2e6b85e7a30775a1eb6b28a7cda0180b554aa0c8377854b4730b3ddd7649912eb4da4d37e19662fd0076af5d32a0bfb1f33a5c835938c0e31fa013b79d110e621b13fdd0374481d4e2ba6a7008435b0f61c9ffcd49f3aa9bf8f36daa5b2e47991a8e00b296d28c924eaa44a3872574ded913bf8628711bac812b2d8bae804c3950d83d65cd38fb67507f1c694c4c7fa77acdee2c17024670bf2fbe1d76f2602291531a88165acf1bd3c628356dabf28a53ab654d89bdbc89963267a0d1bd66b6d36622fb1016c5ba4f2ec81f75dee42915f851c4c436c4f31de4c40a79297971b866481ad7f8c04bf09825c8e421917b7f54710c98a0c30936ac9f2713e9d1cadd54cc8c5da30e8e4f7e2716292b77b1fb69dce3741d65da9e0ebeb61200ea7247d96488bb032a3540ab3f51572ccafab726950aa49f5fae5e376caa712e1354cfe92f30e344e0aec8beed76c35601ae2389c25c59d3e5b49c8f471ee9e0266c021d9adfce090bffa26c0871e0359000a71b693d2f3d95ae8e83757f86828b4f70dffcafece3877c9fc4e3a72790830fe90a5394f2b3db8ad6b26e23a7500a588b377ad5e72d528975a8321d3081ff0f0f2111760d8ec6d1d4d726e99f79c1229be22cd31655645ca42b83d48c51b9905a61cffae36d973c0eb4c41fa0b8ba3f9ed39ddc5c58194aaec7b0f9ec443eada41ce92a98965228b28c9fd50ea72ec3e6f5616df679a2806ae08ad9bec2c4fa7e9fa44ed0c2c46c5781141512c95580272f24a7110687e066820b25e48493045ae808867337094983855e01eea21fb0c7a038a156057997434864835c3201b7b354b6dc4996337567da7daf1082fd38fa4cbd7299a8c7602578ba482d82694a1ade542aac7ad45d6801f61e615c2aa4ca5f4d3a6d6faf050d564223724eea72c76dd2a30fd32d34c893d21fe3323d58cd3a8536d26ed3695edd7e5a3948c960c3053e27e61b0b7f105a04f21b2818498c6c4f6d7b328fbec694e951cf67c271342c304712c74ae346529fbc88d1bb79c2954dd18c0feedaef0e9ae3d840e24aca39fd9fc7d571d2373d073e5512fe81c8089ea91421fe22c5b2641330386831a4b75a7044d79c63c1450588aa7dee46dad4704fe4c60caf86ff4fea22512d8342501eafd959a0917a64521e165c843ec1ca4170ac4ae94043fce745384d91da1f23150eadf6ccc37ebfc9a32ad6693a1bebc9165e098ffef54cf3947cd834e35c310f7980ad24696a4395aba7bee6373971ab1dab13cd3dabda92a71812fbaba2f39e818949bd44ed8fb7bd65a34a4ba89cc7106aff813641d4e55bb996527939b6526c545e5993157846434dccccdc0bfed4f459be339fcf6393d877944bd6319cd9aaf4345652ed0daf9df4ced4e48167e4648f936f64eca6524f565e4c9eab71eb6c08ecc4f60388790a5ad753328a6c5e1a388a6027575018e21135ba08df89ed3ab7804271cdf62d92791dba9b45dbabb928a7a3796cc3ee1aecb8db97305a5654815f596c4d479a0d504b19b47372ef9a3d5067af93c09ec8814d73aed65b51d57f596a902625fdce079fb1c593012f9768cbfe6074dc5a720ee92c66a5e1aed94759078199236408da43417ec2e3cfa1aa0c212efaf326ff651479862acc3026a3e6708b403855b6ca4154e23ced46557a641dba9259f39d898fa3438d51c5316c32dde77ba4a358f6676498285b783b7f2f9ef2f1ec4b3b09fcaafed26dd1c48c59bb11185b1d3ad20d3a70d66ddd9c2b7d58a26bcce90fcc94096630afcfd96249ff9e12b3a3f7a8329a5837f81e1765a361e85804363d515a7ae416612f284a86918018997f77ff3464bd4d162699efd0422658473aa7958a94cb0dcc3dd6e5d4698541e57949eca5bc6a70db39fc081818aa154b8827f6a8ce55b0d43bffa2d2272520b9807b87ea8b81752e04db783c22f7a8b555fe2357bded3c665269ba531645478f11567d6a53469c37a64184bbcf92d6b490e402eaa28c12fd743761d4e3c6bb7a2bf96c5ddd4facdf8ccb0c6fd3de103bf4a50dceda3bd639264d81430590ef8573abf7cc041375bd9faf0b8700911745842c18adcaa541d9e72fee40f18cf7d2e22d9d81678a16c9b89fe8bd3a76604223336888ecfeee7af798dbd0cd9af930ac8fd71d2ce1caf3c4cab85e401510c58ed95006949360eb250e5e86ed2e91fa8466fdb81be0f62e9eaf80ac6b44169fca1cf9f37ef2cee83e5b28ba19723bf6f9f148fb820d90da025625bf70c548bb6c63e5224511cde2a8d381435ac2ea2d24f8d2ec612703ee4943b8efc2e04bb1cb0f5997381a666eb3e0d22b37db908ead71c5988f72281fe9e74ff316e86e7b16d880f0fd6cdf2c0fc4c587b6c88149a4d303fc506b8fc757cfe36ee92e9789f26a523d1b97375f0c2b922cb64e10a3b5211dc4525ee3c94f3d2668bfdd786a0129f1a3dffc903ec637501a2ce8b367be756b19e13c8ba9bbbefdcd3c202e719ab98ce44ba939fd227e2b40b7fbe202c146ac361674763f3f176474c45dc45927c016b7a7fc157cefe607a92e5d61130583d6701db9cc38dd41c39dc1074ef3ecbaf6d8aa2450b1cec3b216a0095936771b0406d7fa24f94ba982d71ee2df6b1a3ddbf90d9785d7412ffae787b1fd2335e341d85c69ccd2a1fa3fc6b22539c7d0339ad415f1aa51149fff48adff27a22cddd8f4a6d72ccf9b3f98cf02d65b0d533533fe88fc35703bc7972742534025a7f2639de9568f107a3b443ae8975d8b979304db24de41319ba335bc13508564bd8c24ba054ac4b2a507036e0361e9704f894fc8c61271796235c77f951aca20a59c8af726117d972738e75dddd009e860805f9999d35d27549dfef2ce9e680e3ab0af324cc4647e02ddfe574a16f07fe2dd7fadb42f6b99bd1827d310dbf625a5f6bb95ef6fed6f4de0dd26f032804fc297010699b26c7015554965b665b3539cbf082579a74525ad360ef2797d0767003a624759571133531a9a33d247646404b057dba74ecf3a89971af0a389bab9258ec464598f4890f58b9f454bd5f1f17db2b2eec22f2de503858d808ca1016947ecaa9c10cbe91455286de9251e26202fc1cab84e11492c34eb37bc7a6866b2f7dd4e3c9074b27c4876cd486f8c40c08732503e00099cfe83346e72b4cf508fa3e3b337520d771a4fbed2a5510de661337260e16dffce82121a44cf6f21a8da5210dd6a73061e49bda79ea05d9b465de105bc4e57e4a5266ba17c61278c16c0d5ba83eb68a543d4ba1f133b1db85553618ae4756e6ff288ac1225fceaa0ade017548ee05620218b83ff7ee5a3555634ae7adeb7f3ecdd4256868ee30d3c43228c4a68a99f759311448a76f338d7720ffd643f04fe4400dec583c1b73110338b170e38149cfeefc3ac985ff0329d63e49d35e83dfd191c59b423913398b8c00ee65b9a141505c7e9a51a3192839b60b52997d9fbf475b6537ab9fa6ac307069c03ad729c3eebef754a7c28eeed4f12b5bc9ce630a5ae3858f83d04a31787d498ab851e231283e69ecf7290d7a60fbfdfd5bece9fbf5d9cef5f7fe41dcfffc382fbec7d7184a33206a74fde9528e407cd801aebc848646e38b131f2c9562e9789098e504e4080f1ca023b459ad6b511f4b14cf0e217b971c209a08fb01bafe40a4634532c065c518e6ad42db38ba953e43bc2b4afd35437e153f07c698063c51a0287e7253445709fca963f001488771de458af411db7d6b6a47a5d1def99f4638a085db60046d0505a9e53fe92d69625c0bc9f6768b446290649ebfea981ecc6ff258367a70c86880d1ad057132e2f58f7576105d6629f40b8a7eda29267ecdc5b3611b5370942f6a2b8ba250239961a4e57deeaa59b56e48c00830d065009d8bbffb2b4af1b503756c15ed7a12c75c810eb2c7f2dae5bd41dc748ac32c5fbd41e26a7947d8d95c8e02598e22c560068c57f81ffca86f7d499b21c69976d1888303002218803e66543fee1e67a853c088680e0d260a84e6e1b673d4fbc04a4d44e7571be31a24af23e36a4a085b86f755bfb05d7dae4756e0ebd6d00eb493223c2826a066f85ad062029f4a7c4cd3b12877fdddb26c734b2b83d10d7951116ef7ee5f0e7fe2dbd8c62b6cb31d631763695209ed18bee7b46fd4b1b7e2121642f767864a883b799b2b57c87aff10e1a68ead6d91aac932d0305787f48081cfc083f2eb9c219d70b5a548639cd3aad901075572759c18c454399dd8780a5dd759f2414f64b26e539848acc98b42cd8dd09adf039e9cf0b79325bc5ec2409efd4e6cf4c26c14451279691275513f53b6ba9d5468941013abb8bb60e2ea8ba796ce19c269794838c33284ebfb4866234abeeeedc1bcf96730b5bd7f7fc83fd18d9b9b1a4d46a0bdf08f760a875f6094f3b3b9a1c486a44ee3f4be11cd1dcd6a5242d8c1a1ef32ed3ef6a177b22fdfc622932cc6742dc97a89937193486a4baca017467a5c64f09d8f7cccd4a1ff582eaae4fd6f3e8c9401b03ba80e9c0b9acf69c2528366c07da060c5101815be21905d71a8949d8213a974c3177870f09094d377e3374f38d841b8fb444ad2e7d3ce7725fd5dfc2b81141b53c7e54e890aa206b86eea66f70d4fdc9788122a1e5d6e34264d96ccccadce5757007a41e93658db3ccc18db2b468d0e982ab5ce7e7d4acc76ecc185a0b026b58d83df4bcb5b928f82ccb4f1b18527c8c549706263575ea77acf3d7f8c531efc9123e739ecc8e8cea4d7a59c72262d22d912dfff1ff3b2fbe1974e79020c4666ec2b8af242218bca240831ba10b5697da65955f20193cdb046010367e8258b9fa2a492d27853e99ccfefb9176cc68048b8db05359b8bd023fe30b0384f96b8a21ad199c4f01781b3b78cb86f0827052477988534f6b5c1fa56e46c769ace6e79ca228593715208ae5d03cb13b55191db40b98ec85ff167773b0a8fca149fb13db94d4d04d2c42c0034dd5860d45547c34bedb8622609debc1e0ad6ae8374b381d26089c7a84206794ca81ac7d62637484fb8ca838f75083536764dc74ae24be8be715a666ddb8165b5be0ecd18647220cd26e06bf0adc3330fdf328e1b92570bcfe5ecb4c0abe5fde3f7252873237e0a21b0726adddfbc5aeb0a80ce98883b563f8f7f7d8ca1ff04c52ce4514f1d4e266ece2867f3b45a70157796d3d12811e9019e9ee68a2cd8d72b40950dbaabd289ca4eb9dd3970088211e9d58c045ce86f0568c97e444a89c46e1684ca28d9b63aa728546b96d1363293ac0e1221a54780c1f0ec28ee48d764679acd314cb35296dc6a88cb8d43dd9e8213415ac9d17b0d53ff0b4b9f0da28430bc3a2968d387e59d9e54a5cdd5e28e8632777502051a2123297949ddcd141ed3d2387c0e41dffcd559c4cfeca0be5ec9faa48873028b664300f3add229f0b327cb47dddb8c9a9be6823f5da8acbd6f66589ed00a8afa98a50b549c587b38f6e14711cf7d00edb802b41d1a94f679d3edf4801f3c7d6fe74abf562d97243ddcbcb0d2513704bfebbb5a6bb17fdda9f401607c7e984771b388dccc3187a35ea1af29efd5e822852d2e34b4c9f2c50a92578f82c7e8184270711d626d488a63602a16e4839889b95e00cfcfcde671b36df67c2d5c612a3e738ba08825e33c922f5d2aca93dd273e0572a04a8967ce028bdad733c89ef1e083b73fe4eeecc3a40246b68231296d2a4d2c727edab3b3aba1e84f136b53960b0364bfbf6db48820e9d25649142b488c1c4b7896ec8d3fd8ea175ff777f5176c6a15002aedd745191a5316fcf5f37669421b44a179f8155044c39c41236b0050b6298dd065b115bc6644a1ccbbbff983655b174eb4d6db52b7cc5d9ea892b674bbd0b138ca08fc694f03dfdaa494a3fe2b2c26e7c292fcb98763539753d319f8ea28480749e4ba41ab204b265f26874314de79ac7e40582f090791856c4942304609bd0abd930b073f0eebdfa2f64c34f6a9d6029d63af5bbe64c700fae6affa46d07d5a72b834be42539c0f6d905245d362ac1fb68ae7ef208ecf3251dbe454ad7ad92245d66256ae0686002ba239f601f23f41550378db3167be00c312363a7b7c28803181dc009e229e5d78169e7e0c594a9e2eb53a4f77deb92e7082480d29f871d90aee8a92a47714ba31cbc17db1eb211621c646a1dfbfe03d9c9139038c731edd2cc8825f1de54b9b92cd9422fc51127600834cb5fc78b4e1adc3756806ac94bcddec35b66d086bfab5021f75816f23ba6833d5416f6f32a5b1057d4a0d61645823631d020be65e426dc6d30602a31bb9662cefed933cb71b816a97117c2a73d1746d1ab0669e889d61c6541f3b456c67c8ffb4628421c9575d7562e77877364145b97b70d7729bf59956fdf2c1508fc786623b0194a44e4821dfd89dcb8c0ec50a1f11d815023dd1b44c8f44764068e6d855aab9618da155e7a97adf1129f4d2690d7f8f77146500925a5f1f927265b75c5271552a48db473644d5a1de9ad73fedcb4ff18602c078864a381f54f3081078926f72127f8e52f88958cf11c656f2e0cd3238322f7acadf7ff515e5ce9ac4988cf21210cfc1871951a2179c8afafb366202ea0bba155d472b8c71a535d4d4b0bd1e602a6c152a00187b87ca3f9d71e0cb82681d5f7060eef230f2480f89ea9fb14f8c5c14451259a14456e8ef0538e51a78c8ca3a761127094043948dcfc445b5a4a19c6b7fb9e463614f4808d5b82289d55821631b54e8f32e6db8a7438ed7e04a545c0a6fd75df5019ef128cccfcfb369805dc0ab36f4a5f0872e14a358d86ead5d1be3336189082f970ff38005042262b9ce7dec5b3959ea7903f13c6e150d81c5e0c5c0532a048681af4f0129527379b80fd248edb208de2688427f7bccfc5a13a3735456b3e92d332ce09cd4d64eed26a92ab0fc8e8706eafb6df3c6d330238149d4981d80cbd9876dacaee835cb69df3da6cd0bc6f0fc4ae0db01db170bcfaf97e3297279a80552b26a57bcf686e3fc884bae2d6dd7371fb5e82d1dd491ee9e30a9b84e427fd22c1f1c1c936397ca864880d4602f7e80d31b17e8740fab9a91c5ff5f79b3c092241b08f5436c361b0cb99bc210ef3384b30d8ccd8bf9590fdf91233170927c9d9f8106a8d8f81e72af965b3b6f2f4d53d36eba1e0f72eea5357f56976e30df4cfcdfb149fd2194567194f91da901a1d010688d04dd7011760d97236800845d5f820bc508da14b8379e7d7dd8536aa055db5ab8e00f0a75893b0d2e3cb6483f0701c6bf0cefea8f80d2626aaf937797bf7d91ec812cfcbf8193e8e65a7db2f9fe191e2bfa881afa17866536232781334b05025b22e6b4ad9d7bfd61c4d07feff5f5fce2ed8e7df01d53925983d14ead0f7dbd697958ab3637c903bb6a1a1e8803da63c8ccbd7225cbaafc7d57d743bbe12ac37e2ca09243d90d03a15b2748d1fad782b2d0903121f8cde88396c4d7385effc2e37e83f5da016269e6a82ac82ce11427bf8749d2ac8d2f1a02ef83d9250469e8870aff95c76641ecc9328f9530375cfdc081d15d626653d2f6fb8b95b5ec7bdcf69330bd6007a77b8f7f0835602cf41dea42e1443aa9c4baa0aeea29cd81b7c3be3199b554a381f4b023d10b7ac72d544fe57685cf0ec3db6bc07604491c99bd53c90f0620db2f3c9ef234ad757a9fb6962d2cf41cb877227c65d035f458a27cfca94fdcb1cafd17565136a7781fdab4ee380a8a84c5aaac7054e480a53abcf4c711871f3e147b76cddd9b5f79946204f7063a5585ff1e0c5676a929d20504d631f57192ac167e5544f8a246915adb08955d1065682b284373da7f44ce7ce60f8fab54c64952c5915ba9b1eb025e6b69218417e9e00b53d0dd6a097311f15fa4a71c64387e5126dc306cddb321721a17333194f9433fc7d3252b1ca3d1d6f8d0274772e772718bf4fff6b86de48094f01f3d2ca490119ff1dcc30ca11eca20bbda22c8b9308a7c7e036b053fa715c92ada385ab17c943acbfccddca573f92f59b2820728c5653f2d35718b94b61a4ba3672a1a6915c676f733fb10c019a95eb82bda1bd754dd9fb46070c6b5f422027a27948a8826d7f51bef9682f631ab9cf412de1bdf509beb13f3694f576aece02fce3ad8990f823ae6fcad718e1a9a98b0140f2c2367882fb935cb7c9347ca7bf7fac7a1d94afff8efe3e0e4796ef75cd1bca76f7ac5cc2911f55ee0d13aa097a9bd10629afea53b8134327dcb3969ca46c6a687225c8a12a18e55f34ae3a910e12dc9627bac3b29b2a92e0635279f04081b9f823b3de339cceb559685b852ece6eb7dca4dac4351c1a7f493600098c3dd582dbf63c383c6432942261e84fceb05230b9ff413bbaa258d2e527857460bfc02a7d06b4dc9a603b1249dbd125667c08320e0c8def6464e4da09da3108c527d963bfad8590addbbf060e1eead74308b0427c6844466c611bd824526a1002b4325ad18390b36f6c3cff72dc23366fb82e3ceaa68e75634f89c21ed55bc5aac5938339def6b748709495a614accd7963edb944f62d908d9e755147df76e98f6bf64e436fb499e354aca9c26a08b06aa969047557e447a6a37b02039b6e7e8f4949e072ed123ca028f7ced0263d827f839a641c8f5ddeb2f9fd7a53a53afccad03a3f90c5b5818ff4e0ba030e579dbe19af74c8f65af4f109bc6cd31b40819345fb756d85ebcb70f2516365662e3f6e8fc33c536a7547575f4a883f22822f46ed91124f5ec12dfa8dac295ec81121fe17624fd86969cfb289bb7d56b0f193dbdd60efd8765f1b91825d212f3f714646d65036229bbd072125025e83c2a37f13d42f76dac659288a3deafbcd700ec1d663aa3d7a83cdd1c480f822f3ff1d4a50542da978794eb78eab36e6c3305de86519c79ce130dc70efebc41283b180194c5fa01968d6599e697384dec6c45aa74590d58ee0ba943d1515c6b21112df6659a4e7f459fb92a249d9cea67a769df5c954ee04b6b8265a894d4c5fa5cd1524a2408361e97ecf75338106bfc3f20f03cfa7299f055028bb428bdb3c1ba9ef4613b164580065f36ce76efca33887950d9d05f33f2cd05905a7dfd06eb7c2836bc774961153dc9e32ba887170fc259178c01fa5d8437267921683e84be6ecf9cf22d86d3253223812c5e7b6e5d267623c4ceeee840da1efcad0367085415693bae9c0205a925d1b80a031e0d94773bd3c1c5e9b4e05146ddf06912f0ce9d71546c6107aa49aba306240f3fcf64cac3ab8df76309099f21984f6b15abd89c9add1ad83ac400a22583629be3841cced299154588649ff29ead8e33b9fc5206d4cb1ce1da5a575677514bc7314cad5266b7bcb896936fd1f493312e1f9ccd565c6ac58d5673ecf5167d8802a582d7327911982b99b713f24d63b990e50f7828e109369c2a58256068a13ec674d1882c62a3ea41f60ae0b8f12bbb72b40ea7ff4e039e266bdc8af4351f33c78f49d60668379251b0b28e11d5ba57321be2ad5e6ee2cdfc84e3ac6949d1fe11623758b248aa8f4fbffc643c420c65d057a2a42f24d256f4bd56465d2f1646677beb77cef5dd288b98f662cd5a59fb501313d99374d4240dd2ffe7350592fb33b92b30c02d88854309914faca7ec3efc65ef2d9ee45fe4f88a060a2085a1de38b9d23fcca60cf7818e760deea235d067b68647155bec457d7f6e0c9feed236112f760390652847afc2ca8fb03dbd7a8ef5133cd8cfbb3e79e541f1892e9b4ed5538a451a20790558b37282ac3fd1391f6f50612db6f1e547d85bee3aecb98aaff31872e65fa143ee3cdf7e025ae610ca6ce806c91bcd2764b5199a373a68a524a2d36b45cbb26edc15423f322fda802b2893e469a38546e88888e082e440b1ac2ca01dc248eaab216896f8d32979dcb0c0917abcbc2d30a16285f028fc7425ace9941905865b802e5652421213c45b24551d29b793e0f4c4c98810b11d46fba0fd023c7edda3c8c2f132706cf7bb20cb3d494bd51ba915b03a0ec1774c40d1368eb997b945d98df50ee2100dce9022ea81ba2284cd6d5db3ec3f3acceb7361bbf97fdeaaf75ae2ead101e7327212c2a0f6568d88bdf1f13f3a19ca967ea25077268dfca8fb75ef981ab8874e175b1049bc420f0a3ff6f7a5237b97c1c0b9ee1c27514f84eecb32493182a1e6902a6218f641a945fd50c9cd2360916c4e4e246aa14bb4d2bcb76e454414960cae0f237e0f7f3bdd41cbfea357352f1c7b94ca205272864368b20bc3470240f715cb870b6ff31c224e10101a49a8e4097ba6040012fd16dd577f8a868b14d0922b164b1cc2c3a8b47294120b5fa883c93f3855a6bc2eaeee89fbe110d0768de4198994e60665a74bf1246b17927d3bc96702be8211d91e7566c085388e397b6d6124fcba125a590ba1790f7f715fc8196c3e399241895b59c07d9fff8243bce988937c4d86314980619237c3cdcedecbeaad97c2f9b8bdc89c34d7b026ba6ccbfc858946b32274a0a3409ee57f5e4325a98c0e9b0677fd1ec2fce40881af0090b989fba489c3465e0934d206a0bc61e271248c92687134daab143c8d116ea107f60eeb55d5c164c1862838aefcdea34e9b0ddfc786930558ef194190966277ab4e29d171e479e56056497251b6131fd984b9c877ad6813f28a46b827fcf1707ef717a0e069f0e633f60182bdae1fcbba9e5d51c3ac4cf93f21b5d5703ae607e30933df75c8d95df2639476aaba5c5a2f6a292294e69787df5b10a2bcf143a08cf3d7ac1c9066a7bb7da75bcec5de18989fc94d1714dfd63a6deefbae39eacf0099feaaa8fa47829214bdcabede3408f7e77db9c7d71fcc28ebbcfef387986f5e58181d58b0363707722432d3898e602ba6dfe98e0febeb6d2cada5bbb5367b995e0e4ca6790c0f5b0010fcc63a8fa019278440e278471385796c20e5f0cde46643c1c66703e97b73813c4ade793053060a4dc2065bec85218e58e5608ae1ab4b170a6903f8bd3b0aa44953b841a98ac7b8ad12fb4da0b68625d8fa13e45a6cc2e4652714053e85521f47f70f1a37300b778660ae086757f964cb5061821b1431b571f0c2c834f919ce417634d33c38c28e03ff1772d25c4f78a5dc6d6c0d74a16088bfd397b119b08bd25695439f6a6bf43aedc09d223809bb3002e86014c7ab25683a9e09792f7f002896195d21ae994ea2a9bc490852312a35a270bbcfd857417e29ac7e61bda78df9d3d194fadeddc1279f377b639c4ef77d70472e339af7cb603206ec32852245868abc2bb033032c46496e927a2dab5f9367d4e96820bafd26c8a804c76e5287b63ea91bdbec7138912e2664e804d427cebae527b2b56fa03587cf89a3558c1c15c0422ae02f2075cc47bd5e8e3a58330a0f75c3bb1f1dd6f2c9ff17acd2f72173b75b525ba46b4f69c70c670926a53d018e26faf5fcf1c4eed1cc6b27962a87285ea5b0ebfcb3d92f3ba7e353e347869f84a5ebcdc6bec6a0a0019ebcaa4ebfa6de8f3f14b4e8100ab0d45dda647afeb369cd0afa8e55168d45a8f94da0e507ae95c2fc9d217bf63d910a483151669822065d5ddf4af2c49eeaafff55a7b0a474afb905673d56d2f182c03cef9a84725361cf8246e434e76db09dcd803e0f4a00ee4ff5dd1d16cc619e6e367f65aca2b58654c823861de2f726018f8c530d3f033cd1405d5200333dbbf364fe241db19260003c3eecae1981dc15be3798b6f02fe6571e34714d50b60ea0ade00671fe06891fc44cf9492813411bbb5edba701dbe2ebc30e125df66a782f55568a5fb6a286d60f3a895f60a3e3841e20da1c432e43ea9fbc570cd73bdbd03013a04b52126cdc888eac53e2af7399b5a4166837b5ef181044bdfcc6d749510c3e8cb6f9cc4044cfd69ac2572ad5e7af3e8174ea4679e8aa9808bd016c859e773aa3020a74319fcc4c335b744b14b006573931361dc0e53ebd8e5383d4a9e0ad6ebdc5a8275b97d89b5a28a0d21d6e4ea1423d7d332b2490febb049622dd61f358a2f6c59fd6f4852f2c4bc971d05fffaddc44c5a58c68d2f9e6dc88d4bee7845ff812f1542e480bc6a0c4669dbbb9234e702094a8422293d4cb825117931cff229b13e2208846825af6b22a38228fdbc9b5d294919562b2e4db137bb61e00fedd536e8c63ce7336ed8d0873558ed3a13cbb5bec4cd475a82e24798444afa490a0fc0d0491e019ae161cba015cdbc5abcd2f19e95ecfe48a6d58e34a1625fa95aa0eddd6f87db49b35b8b077b572e92cc61ffd3f0461af597eee45659e744d0c793bfcb23868341ff84525d0544527a4f640b98860c540d90f7013ef1f5ce196a8e74bf5f4fd89e7692c258567baea2efcaaab7a476fd9225648454a05fcd8d6fcd59964e1aab002525b09213933e49366eaddaebd4322268906339fb638416ed595f2a4490e22fda9df50eb53962bf5936d018fd502d56c7c892ba4973a2557e10231f13a00be1dee306c346c47270855fc2fb7e06aeefa23e1c32f3f732edcc8525b6134df7ef6b5652dbc1aade805d1289829548e8e082f9891e7b8c2505bd54f97e941273e404f20ee06514741716ea32690139b339f0a270e6d1ea873739f0903dd1e58c4309dd589e7d9533c1b53257e61cca567fe1b6e38959ab23eacf1e4b8e8a3db1cc14e6ac67425482a7ebb614b6d64304505b61360c858696037e451033b76934d80f25f31459ae67cfaeff1bfa1ccfe16525dfb9570ebed6da11d2ab6af97afc8ab59df4fb734a5551bce9f70e5b6af3bb65ff7a19ab6f4928082fa0295079856675c1736f9fdc46b7b26a0b4384619abd5f253aaf394130fe06161d3712d31e8cc041beff81d916e16cfbcccbc0186a2f846c9b8ea49f563e3466fc9030f5606c323063ba15753fef270ee860871c53ce114cb36496f844dd9ab7d1419bb0b0552f6c38db68a165bedd88fd2469add21be5a2243df23ba24cb392e4d6979c2d12b1895dac1f142ed8f4839a7b9bdf6081c8dbec858aad17fdedca5b9f06267d7b1c15c2b5c1a29bea72401642df5adebfcc98920aee8e3afc89917a0c40fb263071bd522407c95393f31b29cb53b10954ea736b56f05958135419497fa8edb68ff07ce7e7be867d1ac449930b347a470f49b7eec7460e4d211f1451f0cc851e5e6e99bc19af24aec964cca07fb83f50ac1ba9b150d6d1711db848ff8074a13bdf2f5a15a2fb895f5be560988ec9d9c0b7f037ee5e8056e30e7343bace69ab4aa06487d0435255b18337bb3492f70df0fd8c5cef25c8f947b174f57380f4c752a029b1d836f373aaf58e06c26b81060910a8637af82c64069983101c954718155c1fa7919dde389b8790cde3832ec731fd2affcc58b6b6c3ae59b5ba1cfc3fabb1f0e5fa372a0bbaefa935ae4b3c7509cdf0d28c8cfeb94f3f9f7ad62fcc7cb1ab330e2afb3d2437f8130d571f8a7080be4583e121f1e2b8b4d5cfaa86cae2802615977d042acad904feaa9ce65d61f99160963ff86c6ca1680253b2d1b1d6be3c004004e784dec912913b767f7bda58dca88a14340a7c4d8f8a1fbc289aef50aaed73fbb24ddb1169744f1632193354c57cbc1365592e444795914d64ee305e85e9b7007584d84912b6895456b2f36885dd4fefd720aa14e23e281a5c234670bbb45ad332e2d448d8fb5b0725fede94c8d76d926b36114235041a20539b0df1c054793b7ae10418a93ac628a5441bed10fafe2a354982cf4e7502b8e97d1d18ad556122175040ed793583f33bf2ebf1a445c9060cfb6f386c82afdbc352b1711d94124e0b51790ff65d72ac8ffa6a2ecd87f944427ff2c7b5397861d13a08b8547ff830c1f8c29ad1660f6f2ff633ebeb98f4cb1b494fce997e5ee79609c9bacb252df6264236e643ad4fe8e95ca7a42c5b5177522a8aec3c8646f9a6f357b27690ec14045dffb50636cf9771163b2a03b2ceda0d4813130abc1e0e46d09f44fa31a78ca6723fbfb0d8e9eb372b3b48566721cbeb9119f5965856a3e41f22dbb7523091726837f631222c65163861fd9f64605d6d6165707b29add6a5c745976150c1890c124ceb77f9a2edeb26947bad787064d1d561b5751a98d658852ac96c75a38fd66bdc8ab60466819a77d262a55d619ad6cd99706d9898bd28c506457a8f2bd1412ea4ecaf4cbf1267c4a52f5fb2c96b33b9424d842b6656d7d88404f045e28a71e32d7328709fd0b41c12759b3169fd86f762eca8c29f576bb0e88102c2cf4dfa1c5e173105bbb840b0364bfcd835f3c2ec8b4d80344ab6bb979190851386e9178c1d88cca9bd59de47c1442d455c64d098dab823d26768aef24e03b33e7ab3293598e1e7c7139e6f799b107db675a140c48dcf3e0e2e789d7210fc8146a09a4747759358d97c57873e3a0e2364769cb339c06bfd955ef8bdba2e3d16691e0a150d98f3dc00902bd848d5c02691092294e78a1ec72dab2f6a1799ecead0b0b8282590ae5b977ec5d7bd05fe7e484c824516a4cf3a340e05dac01c32049736767baa81822391cb4f492cc85841ab86ab21d44c862c97e146a8a8d1d54255c06facc99aec4a9f259b4cd605abba13581d20620323bf1461289aee428a1a3c28b2c2b40f2b029e9be45522d32646e783f2955ce41f1acc2b1a468dfb6a7b742471f325943c00d0c384633c447c8c03003d7ea032299ce9ea397653c2107b9895e01dc58aeaf04780bcf5b83034253ca47e71a82dac0dea0d3484ff85918c0cae10cefb4521166c83ffd366da60057c0e74ea2684e20bc7280bcb373f3e96433f47be5e566a61aee6a21bf790ecd01787fef0c0fb104b5b8df76f7f85b1ddc51a6379595d950d3c0a86d518017ab4d87e7c9291369519ca1f36a8a0e890f40a81a28e930bcfad5348cccd9f756afc1a863873226ddc0095b74dfd6d716827090f0c5ad00df7d5af5a0617f898d3feda7457fd03ec9896c3519cc7b25884a3879f88d9a458e3a43359457d310c1b628677b6831ebfea0799cc39f8af03f8612f0a3c09156fbdf9224b3ed84502dfab623436bb0902eba2a60c4b94b1ec8fd94478d882a843244492aafcc62fed78ec3e360aa5d5e8afcc3cedeb1bd47544b31aa7f8828c8ee2be7d9e5ad2affe41c136273b1cb5053f38b8eae3d30797db7ac2ae323fa877b0c62de85674208a079de381329b8adf23441588b939efbeef86f5c3b874bf6c9d779c261763c5003e889ab99d099692213d40f2cdb25a2e93a6c0892095ba50e09aa988196b096d9cc509171600774a69c905432290fa7cdbd8ca1b5acf3b05595cacef789007a28130430160a4a14aa41d219d0119ed7ca670eb872bea8ea4b49985d01cfd4fe2497435a372e7865af6d6d25241a0aa547abfa35bba213633e918747d0c67799ac097542c94bc85bd4b8fdb79ba5efe5ec8d7afd666da10f642059e9778ef6fb384153b199e67f4f2035c2a64a7062a118836c233669c2b7420e38de5851b5f74deb43b65c7efc52c27ae8832a8a6ceebbaaf838cee48e4d6cccf1ef506d1e4a8da9d3256bb665a41c2a6ae9164ba6bb68af93da12298842522ac79fb2817df6e5cb56267392cd5879b03361db5023d86c64c3aaecd7bb0a4299a7fd21fb4abd232fbfec71c3ca93f0d3a04a62284eee139b3f0032d5faa69e9943443c8e27bb9694dd1405f3eaa5dc7af8bbfdfccd70bc2565c0ca8af06b0fd821655b9e224a892f3552412157b2cdcf9a329d4dc5e2beb7161ed29a9a390ac4ef8e3cfd94772aa3c54fe7fe0005852c975cb1bf4dc157da453b9c6983723182e4d4c25cadf055c17bbecbe7ff40b41953cae0dd9393105b78658a6042a63623d9021f5adbf7a226e57776fa1cff8cbfa711ed5b82f311cdd2193fadc4c7c3b9db2d9de1d059b17b9e33195d411f085a0b461dd5ce26d951e5777c9064e919734399d660eff7e4442082c84fc6babcbbfd40f6beaa9a680aabd25bcfa6e03b05fc3a97829e21761601ba4e997a546d04b7d2c218ccd0771da0f09e124eb6ffd797422f9c7d2dc3eb632aabac6d529893cb7734e3010556109740a755a6d26172cc302ea4502ecf7ba5142bf7525ec6a01d9d64cdb1db67563f1e8454e2d3b0e8dca7225ac55c3f9aa77277b03dddbe4a5f69915cf41d4fb219bb3c6c96bacb6605a304bc8540bdcc63ff5164327169c60fdfefbb4a374d875bc83ce96afd1f6db7b97ecb2dca7fc03554bd14565b6329760faf989fe0bcca0c3bb63c6f558714751f5e491e64fa53a8746b32a191654883f5a8fbe8641bcc914d8c7ec6178c27fb91463451c38c754da0495d78294c2c2a6545b9ff542f7c242c1c0ea2fc5b9bde6b099755f8e5e50e0106fd9db355c2f894088873efab802a6fcbb9c9ca9c796eb3e443d43e56b1a203283ef11ba17ed7650081079486f9d744f8b6b7d2660dc9c7e3cef55e540b59b57a575ff9a6527358272841bc268ccb79842d35078111a6d7dbf2094327fd3a943de6d57e1b750035f73dee2ac18e864bd2ffd80d42dd5421456a4aa239e5c8183d3360ec7e42e8bc9e400e499067df577433521f75aac62c72887b7cdecc5185698100dc8c8aa25261e778b4878f9e24117f6c29342cf6ee407e008f5250c9ccd5a75375ea7598aa2de3aa589604637ae0a0bf30ddf328c983090642f8215d2bae88fd753e335cee232901216642809c4b6ab7e5d6b21b92cb237499ea00308e27dce71670b6d54f66fd5c06e6ed45f0318c83f49e1e43a8c310c1ab23335457508dd5933d683bcaf654063dbe9cdf5acb768935d48fe721860e95ecfaab4783c190af8c3d57b943742d48cae2c48ddda84704df7589f9cbae37e88f346354197ab46e936ce7c79441cac9757b29697179f9e7d6c46a217934f0fedbea8749065aa50d314e6069c0d61eae955770675bc8edf79b26086564d7611aae949509d698ab4bbceca9dbe379c47395b3c2bd5be7f247730202e84cd8fb90907c26971c8745987a80b9cf7ecdeae547054194c4e38c904b356622499dea4d2ece751e9bf734b82729b63b102f2a0e44cea892d8612911241bcbb2f60a202abffc1e1517c7daaad97a5e15fd58b32ce7df58bb7f11a325f634e350a82895daf2fb5c57f4fca61c36d839a7ebe81cce96e447019635229d2dd1186df8c1420a1e37c3806d4e083b3a6f8d23280b107a0e7eee9d3f16d46f52223b1caf6a3032202f6ab02e3630e80699fdb9f2accedd18f7429d0127115d0a299ff7391b8e102d55ab9f1289933068f7b7b120b12e6037d7573702c4b6585ebaab802cdb0919d174631e1b3a25d0c4829d2f262e0624311cccb74f957e60fe3719679befea476c35d68c6d01c07b9148eadb017a3b40cf5864af3670f6808b504f228335c6bdeb944ef7a52d360869ed6f8b0cc001fc64851fd56c0f9c41bd635c7d4edcbb25c53558cce3634bdb72250b1b6750eb6edf3e654b0179c8350a9dfbd0438e89a1a1de8df8c5b6a0e9221257a82a9923e7c2ea8c1f606b9466465d329766325558221b2e59be6df294061b0f2dcca659ba380512d808146a699628226b057b8898921e21f380000556db84e60e993a28fbda452e153ed59996e27f67a7554836c7ea55bbaa979f9aa92c0ba6a79349f1cac782a2925786dad8ee1311afd20062127be8a031fa1eecdb15266889db74433cbceeb1cf609336d80c43408a6b8cdb2b4344cadea466d597b3867d749368ef219b083e0aae1f9da718f448e8f91be253faaa76196d110a557f95f89d95ea68dc4eb85fe55d223e5450ab6aa963b359f6bf0c39dbe08964f459c0b1460967b40aefa1224ced81a82a25aeb1b330aac15eada48f103bd6b7233f87d680fd22f1063c68b123d599f56ff1b4ba0cadd84d7cbaf0b9675010c741f45c6340ffae392f8e1221620d8082279e59df0cc325dccf37a94035e404d99e46df32a1bc4033542859d5d9e5133f4f82dc7836c533366161893c81bfe2eeb20396ce2a8e7ff09dc792e0586a65eb695acd7ae9083f93b6e2017030fc73f4e86569c36c55516e065c0d1c3048e297b3902a35e28a783f7aa0c6f54e80ed34793f42f03de2404fda0b29f85fff60b81205a670fb20a9f77f1d69ed2a36805555ff2b496b7b7078ea5949d61d46c8e21b694f78760bc9561a6b489782834d8452541ec593b56e15910cd993eb2e293cb3c3cb4085f9afcce9a273b6705db61c0d6cb926d47ffa730ad8f2f4db5519ff3539453b5ed93a90895d0724d2e524d32f13adb84cb11689efc0094faf499290bee946ac6f05ecb685fb6230683fcdc094b518229ecf36a861c4395f126730f53a1c7eaf9b14d416854b014b7fb833a6e1d3b8f4139175e38fcd6297d5c5e28ef71085338e997f3442a9c9d4900778b4467a9274a58e05aaccbf8ffa0bfde73e911d89ae79dea7080c5252b92dfce60fe7a36bbf060a3c95788e0e12f7fdb3c85645f2f0466c266b2104061937944b31d89f66c25d7af0ca9702154c5033d1bd26c67541f5311c37c5e7c97f0865372aef17a336a5bbe958b0c1cabc8e466b5743604371ae2f43df79c9e339b2126b25f64c13b4a768d15741c4e2b5666aa26bcbdf1807b4ef0abea08c98f16ad0567f8c0cc49917c840eb0a45162714c6ab7b97958c641e76ccd47f460676675e0b4fd6dbb4521818daab41ff15f6c6c8755a9c420d0c7dd27c9992dc554dd06de3b2628294295ccc52443108733512b26902c1cc2cca450d5675a57133127f9a6baff153805e52bc8102bf3db2c3be00a206bbf47aad87349bebc504055cf37b7f7b97efc3396ae1dcbf5d778e6305293eaa5c6f04bba1a00711eeacbd5f4a64f9dd94aa1917ec7aa65239660d5b7ac531231ae3d7377c8436f78749d8d2de59e9fab565a855d48f3a51198dd1bfcc3e528d61acb868cc9c0603a4c556dc0522890a13e434a2568e00876a6b1c941f110bb03dfc16bf8da5941b2fa486d16a85c38d59eeb5fa6fce218ae82a313b844a7e886cc530443e58a7070ab5e2778b6fc6ca8d90d61bce26fd2e025fdee82e4f39c85fce6e7a097c6489ba7e8d1420dd0e2ce65310824215895e8f41e4f1d4c1621e253c5d097747349ad8b3a4ecb50a74e7cbc7f5bcfaad364f925afbd95494328b4e8836143268defba967554761d44683e3a3505f340dd8e8e3d4a14d8883842fae2a14a8577650f72646f35518635c18561cccbaab0617c8692ac0e5703d62517708fcd173a9da529d1b199f1f52bd65aadfe59f1446453a17359923a37370f7fdacc9d385869bce67e354af94267df73c133c169b237f1f20ca8a552ce47bb3cd3844908c0e54cd686c5684d7bec33ece49b1066f05d18d13f88da2dd7a911c25658a9812dcbc023bbdf894cf5a3f0110dcd00b21cfc17cf710b8adc8a17a1206a646f639ce74269c7d3d634a81f0128fb94f5fc64701d3a26f30c430ba5fc1abf8e4af3ae4b5944f600b9ebd6af4c391358de96fd976a91aaecf786afe2c20797ddb198cd453b0675efc3274771d3db82d3ce1073bcec0ff761dc2f9d49d929e777364833b90c7fb568a25b26a26a94cfb718726ee99ade9d1addbb6440b8e9d1bd2cde96eb706b8da6188758fd3227fd63a8e2625b11f48780bcc3c2f7bafc2f27c2f8bd18b70e7bd29148cfb2e91985b796a4451df8d134242450da30360cec94563ca78829d0e6f81e31c0b2b3fd4538e3ddc0528891b2d14641ed8577fb4b2847a1a888d75ec5ab0c624da164a88bc00060fe829f4281174ba48be59d10f49d0e73a2514424fde30ce1b86ce765e48d0e6979c0081cb74a595a701853cf97448176879a0f089c0b0576d7362f35af7ceb5fd3ba3738c0bdfe740b5397b556040b912e2f92dd1af481f51fbebdc77d7f2bf96e568992ebc836d1755b055cf0aed13f27a8d0f31fa5113e87a43bf9ff84dfe7ff4efe03d774d33941e1b9997e1b7c353f556123115657ef61fe7a54ad13ea7d41f5f19810e0f2b7516313812da12b7677624f750e973556fc3e01b43c3010ac6b48d7cbfefbfdd4c6580421318c10c313078b91f947427f57d893cfa5d3062f894d2f9bd6fd4c3e207380cbc6728bd7fed8e0f5e716ef97c90edbdadc0d423b0c63ed9eb9fdef87b2a95c707fb9c680f0e3d8895c153ea50dc5a8dc669ecd7dd5d15b2141f29e71d6b72049cd05958b317b8d9faff224c78279110bb58ed33417c6dbc5653eba53267a3565ac641787c99b6bac0204c06d0b848ccce0ca611b1d969e4ab47a60484a529898b3b0e5923c95703c075a3f4455bbd2d2aea94188fc7a42e90cdf44dcc3f5988623df5f1ff25fa573ff96c22cf158930674e8bbe0676a3156df533a08afefe98e238d983ad9717a92c88676b5275960c1cfeb2a659ec79c5441f4cc11c636ce8403e636f54c61d7d0ba0ff01c321f86d30959495790203d1c565c1ab5b642ececba3119c673c430b4ad218e1aa917251dda5aa8e83ecb8782d90c085ab9300e56f70b44cd3698f9a05aec0a4443afa783dd9370225e6c767cddf559528cfcb1494d0eb0c3da702ca49fdaedffc24d8c800f30ccf21ae443c3132ec08f677a60c73963e4d5678da974e484a42ea3cb9d8073fdce5335a701ac9e6754567d91b04e2713ee492413ecbb757f4a45709fa03bbd0d5268f7f790f58e53b7d672fb28d4e4e3fbe8821cd3832b2c265e8eb96b515b0df6353da18b7e2b88456506b5859a49f0cde947ab7f9b4550ade9f0d565cb6295c1c004e4b00d497c987e17f60c3e717912f3877e14dad2322fb9c6f7245d5aa4fb3a38d81a513256117320093a8a4d977872dabffab6d863ff39a69d12f3b18c7330425a0e36470cfcef290a907458ebb8355a2ae07c775bdb45648896bf0c4e702e462e6521e7c145b76002b80546e37b1b76d89d8fb2ddca6d44287bd514620f1fc14380b5da4fc9f11f74085e3c96d51fa43c9ef4a74167b7a37fd77a272330a42b41a92569fed701cdf814b97cebbfde33b838e52783088c85128e110115b6e573a66561988d56a0d9dd73a126f50e5e0f1f524ef3ebacb38076c19d329525d2a23b8c74955ffe2ba1064e442027de451c474c014358cc0e056c1b8e092eb5c32d26add4bf9dc9523a0dfd8fea2c514ab93d352122fa2d0084c3740f23d7d5f7bcda5f6ae579ba7347b1a81e1033a29b818ff9d8bd2d381d3f8e3f19bcc0051a61aeecb9dab9e4a9c0d45b5b0b6812d4660849c13cec0df759b48ad9167efe2fda95749a0275ebdcb95cc724c70d96bbc52c5a9567d16838f56a1f2f0a778256d1250d4ec97cd174c98d4e011a58fbcac090a134bfd6d7f623bc869bf376396f9b4ecf4cbd361e8f0c66b7528b969d0303bbc9f8585ee061aaa38b0a66928b1aee957ce53a1ed91c691c36a0232bbaf98313769c9f89ef30ef9dc8e1fc517c104d0369df56c4e57270352138f52a644892dbc15d4fdd923709cfc28dc5a51673084061d20015846db03f709c7f3faeaad39ddd330777225736208430f5e601b19107e5f246a9e87255c6fbf3a80584c3620d20a922afbaffa09c90a64eeca13e2ebc1280952b4d743b9ad13dec6b973e61f8acf756f88c3ef738eb3625d5fa0af38674ef326b7d9fa3e1a9288b7e4467ef5316ed98177227f95001c3d56f6b81ce1ab9f7019b3712d13524008fccfc46c0efd31e635670ebcad74340331af49b47d9e7f163b1ae235e0555b17e4df90ee0833d7ae5e8efab6983771e8ad454c50b459ff945f4b8fa706d0944d6c2c8b64cf0a0f1d9f812c03b5271042dc0130957ab854fcf50892d037ae9531f6c0ade3873dd1a1099097b6af1f92fdbc84700b5c7feeebda9045500c970268c9f3fc4504c3240ffa3694db6155b0e95443e4670fc9e1bc1f1be737ac0829fb238279e672152982f9d0675e66e3acf07c382eea1ece3ff0b18a34c95c90f2671c904426d559c825919504f5cf0582a6dd6a0d32c21a4185c2345127ad4b516aace11e1cf9d4da5d14eddfbf06af2d6e776bff46393c09bd8bb1719bdcdd37cb2473af2fc900452315d060b4604990c72f1f47719cbcb83848c1b5e076c8dae816803aa2a59980a6d543a5fbce0d4246c40006efc4dcd293371f689f355a6fe5ac06fcf6fe4d93890d343df787c3d58d286424d10b178f3df9e3557d0cc6a844b3e33fc2ea3b0acfae0be5f76a8d9a51f85b2d7197bb714fe423c39231ab8cd7bd377fc033c6e29414bc38093cf5901ce4601bc17dd2203e6e866602c222b208a8ee85556cb02d9445f28117015fd5e4244eee7352980a403df65a28d334b9418ba943948d403a82f1411b6a657151805e338cdb808a6983aebe739c1637c107a3c4201bed33252ea8840beff6fdffaa41bdf57379e724ed4ff53f2b8a13edfd3b529726547bd8245656b91324cdf85928f260aae99cee67fe4569dee199fff02c8f6dd8dc3a180532016c732ada47a95b73fe830bb12173a97574173db6d86d6262d871a14474ada067616bbdc1e6168596ed74575d326e38ed9268a63802c80a8da4cdf53f0595661c1a3444b4c2dfbefbaaec6802a73b7b06dfbe202caba122b8633cfb0355fd7e1acf749b44ecd10cd04daabdaf7cd13e0a446bb7a21016954a5270d5b5726ea6dc914b27969d675037f792252f3add84f012e81bc3c7b816a5f7fae97ebad5b0acd5af54fde72e16cb8d8b2808509f1d82de35609abbf3a94f2aba2f650de7da04406a6839db6d0cb019d8f51fdd7fb42ab27c09ec1bd26baae16bf242f454d8cd500a52d71e0d0965e4b03fc7fb39672cf2a98b78db153955e032068f0b302e287bbc7460cfeee694e71ca33fa64dcd13f53ef06cd0197bda417aec3327c11aa294ac495fe37b9012979350fb8ea49b52635ce96613a780da8389be61ea67c685cd3124750a39dd8eb5f41fe34ce0dddd0da97a1a58d6db522bf0672231cd3c6ba60ca853d79f965997cd4ad001df55c7618af21a9583782dfff08d0422606cdd185e469886cd5e342747f6292e8f76281a2199ab2d2c8e095f9ea35da0be04d99eaae0a0da3acb892b2c2a38af4b46fcf8916ab7dc03cc31886ccd758247162979616387b7b7429b48f2556c6a8ad3771b933d69d37bc0bce4ba210dea9d876b983b5d06f2deaf66d5fd5c495e7ff1ff74fb80286aed23c22437e9e5dcb1833bed282566d165b95449cdef9c0a387203f47cf9849d816574584691a23256bc83321ed394943a5106aeb996ea93337254bb8e8412cc083e13acff5c3b93782ac7d97a03e47234275f032b312f6dc6a57e8d205fb22402f65925c9b86eb0d7003a3bae0421580f56e8dac4e4ca0bd1d9d793380aca267bcc4e277a6327e45941dbccbfef306d289a9a2c8ae3db513589317f432cebdbd49670ce6d639a6bdcff616b7b53ce34966abb6940705a3b7b9e351486d3de498625df32169ebb5b0780936c6c9047f434b57727815800456c659c488cff69a55bbde83367fe7a9a9a7d3dabf477dc8f1455b1df6eb960dfb4ac18fb8e9d9bb71592367867cbd127f2d8f45c9211bbc62fabd64a6da759beba0e085c169152c6e41edfec44575012e9fe080e97bc2189e1e524281c5344aad21ffd94d08cf753ecac6b044246cec899da3d593648c72c6942b5bf6c4537a9dec6b9f33d729263c5c37d7806ebea3eabbba284e8dd29d1c6db094c1064a0317cf637889afa7176d05d41ea50283a9246afe71f92fed87e8f313be846ad2667891fc11d51cfc2739cd9bb2c58552bfd70b3deed5bb1d0c63198ec2c7f4b310fb332a05b2afec63fda1aa76bacac190a54786ab5e2401abea2c0dd87d51427e60825a672df848512a5f9ad656e0c8f0406600848312abd0862049f0f83460e74ca3dd63d5cf54de9167c8d1f28c9cb0841c1822a6176cae4129b02891616b8b300950be119532b367f915e824b06743dbbd832df96e12e23667450374cedd867c5f358cb40e3d36cdb392c41e9fb034e7dbcb03901723cdc82f9f36e06d66fe4119ed309ba80350900701242edf9bcbe30c603771d5f94f70eb71c9d62cf03fed85d699d89cd6b7125dcd3c0e31535be9eab8b00984c3bc0394400426182cb98f96f1698a8515ade83a75582c63d841dbd9f66efc1e4f8608797eed047ce7bcc8f83301d43355b0144bfe16b6b10c330492ae4baba0d0284a0e20663bdc65fb2ff02a1b8534d383fede3b234c5037434f70eedbf6d142abfb4c72af981d7b3ed59ff89de8f827c5cccb4df344afe066772ed2918283786b8289811e8d1b74e4bc34f2b2d8118ae01dec624382fc2d3a7451edf0f6f29be2fafcaa59e933556a0a66be92c7cc7b1eb7dcdc7e480ebe223fb5457a687270fc7aab1a756df2e9bfebe9573071e866ffb496900d79a451cb63eaea460a2f640f4d0ecd72082888090ad005025bb64f516612e934bc81b428e1639bcc1881d37d51b0607d3aeacd0b024d06aad7bd3f736e2088577f3e6271fe62c1c17f21bd201c2a20358e1e94a79eacfce0d31b337b35d592c6882d2b47683c5772200c0fa473083cbc5a529ad1f2fdcb0ca9325f11e03d27e68ca2b05ce76cfee4d6fd2e5d7e7ade4a4707b782f9a4813b30890f691323f51abbded37c2d2e38cb215787a62ceae363cc08be4f56a53273810d164e1e93daa402a2fccd6e04dfa5efeb7ca05d1bd7eafe750565e2e8e9a7d3f39513fc451fb91d7336fa21024d819865057f7924aa66bbb46df6c1b9267f7ea8c47fb0e2726af7392178b67deecff280adf95e0be89d9f93e8f1c16ca756ab2f2e69ba55c43fed1cdfdf6a29adfa155f823dddba7d8e7722ba7244b8679fe982dda2583e847c41bb579b9989d2c6f6dabf3c29fc2d817ce236ffc65672cadb93ded365434493ba1cb13b37e27d2f8481e32a82576d5b134dba6c4ee1fdb557123c43369a1c37de0da018b8fde6d862a5b14c67c7078f758b229cb548fcfa83bdcd7e40c5df80d242fec64797d55d8422d6ace3114c10f7082a7544b86413faff7d63675a768d2905135cb274d7feb4eb3b483c62785f503c890ed1c13ac726ad4f80b1e7a7f2661a2ce49c7ffdf173cd7c251709374668460957dfb6a869ffd38030a061f97b3123ada475735f1055dddd5021fb8eada892dae520ae836b0a6f311427da6352665517f408ce84a67350a6c02044f13450644874e0476a0d39284fd2279d662c832c6ae416ec18cce62a3740e993bac70fced498743253792511c946f456faea8fdd3339c0718d67a7e318d4e77271ccf40de0af433fabb0af92e3b86e43c9a7c9d5d0fdb5d8a37f01ba5cbcae8fdcd24c1332b861ae32f327052a181a77db6f45d3c5864ad1382fea122151362c0c78ff2e882cf4308f8d4297786d1da9eb87bcc6e56e955c992ad4538498b26963db14ba3b8ead7bd59ba1c8548226b6ba9ff4c929715214b1a671f4c20b29b4af23c76ca7c3ccd82596b1821db153c7bff03c8407be5d4a5bf1555793389434ad6498d8a8d2e1b205f80a24e9f9e46a90d0b8428791ca44ce0e4dc981a7e6224a1de342942e0cec51f0df7bdfd9680b02e6f826b676122f4d15c6be836423e56c9a50c862dc4f2c021f730ca9a64e00a3d22073018e1e9a4141355cd455f1e11eccf51eed66f2a74aa21de98f46c0936d8517f66a04352d3153057633d3e8fec3390d743424bbe64a7269381a7aedcc2372ad6960b47599955a189e018c28d9a995e02875fa9a8f45402985a4da2658e6674ca5dc470d45386eaed69c719a1980ab7d4f93c8b125a545c5e3b63d2750ec0f5ba6bcb106e697caa0aa206b73f8d99da9b46681f2269286422829aa1bbb2d6fb0619b1b6a2aef5643447f41bf29f5d466b1ffe47d3fab3550d1b1a4f6eaa708c23013440a772085268cfd25a1bdd09b43e486e44b4bdd9fcc8509849bbff8666a31b9126c8a79f40379ec9df40bbe9cd15c17d031b755d7fba4c5e190eb374f0817bc13e8b414f08eefa1ba1e6437f17b444434da5d87613fdb7c0bd796693cdd07c7f64405fbf51d3cb3a3c32b11098ba85b563d8a9610decce45c934f97558b97cb3df8d0a069e75b64b09c7a43981742aa2c99af66f1213be41d77beae833b80821d79c913581245581859336b91371d25f1b705296e0768bb7025ad26fe5cc2f882095de88f7e1793481d83bd9c4ef1559b940901bfd0bfb6a8401ccb17ecc2f966615ec980f2d446da92729a81237de13fc6904d4b222b34f72266dee68367d714c08fa365dc9e38befc25f44b6f10c56ddabbf9c5f89b08034dd467d270177f5f1ba7ae02ab403db1f8a17cdd25714924320f378fb2858ee9c335fdc08ed997968cfb9e7210b6a68ff4be4600f217866b287d60a56ab4c2f1def8569df383115339f43bb44f34e39f36bb6056088bf25eb1bb93367266e202fe3e0252fa7bcf6c648e11f265670bc38238465c3dc21c74c60d9d80c9ecaee8dd9c53e0c043a4a6e54ca3b861517ebb1988d17a0534dac5f040f03e2fcea9dc625379cc4bd48b914a897e8fc18d8ed33d0eceffb1a17f7b019703908b8b520f6d75dc73566339902bba281ce2d36ef7f39be5c1037b4ca45765e83ea809b3d2851354e0c239d1e778c23d967c792f244f4b6954099a471c918333c0bcd9aafe2242f0c9554f7f3de219cc3a17d841203096254884a01317a6728327b3080ce27590ec5a88f6b074ea7341479e5b11f2077505d86d425d6b65c58365b7b6720b38dfd5502a999a487861ae3be5e9fa33d20e7e48dafb85af3c8e07bcddd962664b2c8f47a69cda7a7744d5ca04c19540ab64e120fb07259090b8918330d93912264ada8a405e8cdce40ed621de4fc247b72cebbbf1a5d2f8ead45009c4a3c55b98506477ae5de9a3748a2e4b814130293034a04ae7d178c48bd3c609372ce35bea652eac820aef1b34d92ad2813d43e940227d0f56abd159e9bdc96424c3d0a71c53a6048927e1708ccce8b6965df5c224c0fb5e1aae06e13d97d397ab7dddb48952887f202dab33cb122863e4b397ab6c2dbc97e6e237fb5aed445b817834be0379ae9d70bf3c40167a2b3220997fba641828ad3d76155bfc7448676f0f76b8886c6cbb311ecfc02d68a1b7f55c3f1d11dcfd162ae8246459e8c42ee1939cdb03a8ff0d04917497dad26ef939e58490a9ee55b6809aa73422f7c7651cb95f827f408d7cffcf7c7a189fb64ae534efa4800ee460af9f1c0010c900b61e59c171803328601c872ce1b024e39fee20ddc4310dede909d6ec57dfbec6354e8d5714401b7df8680556e50296f79163cf1c7933bde4ee1851207bf734909b274d04845e643acb5e2425c6de9186a785e5b540ffcac3004ba53509835d560e346fdc66ade57767c7682ff6e2ea461cdd78d6db1b330638a226b0c133a88def1bec8a2ff086e97c54c3bda1b1ea716cee93f08335406f8f31ce3c8d172c7e67345097c91b7cc42a03a79906d57a4a15c752fce9d8977e7547865db15439c5d0b2d7a75f8b8d6f51dd7d3c0eaf2ab16f55802ede0aef3bdbfb2eb305e2f9bbc2c4dad841639eb26e9a91480ccbbc0a1da92bf115b1de65dba6e361380e5c194dca1ad64e48745bf46b626938e74b7759c8bafe15344de57d07644646c6b5cf8887490750562356b81978faa4b9554a334ce0f7d48c4ffc8f181f642cfaeb497f121b91de209b924c73529d42a2ae5196c3c646c3ca5174eedafe02c3fb5ecb433cda1588561c4ccc95d06759a300b1f959364ce1546296cf50a0fe3312c203df20369f03ea31b91371d9460650793d75ecb70e0bf3b24076ce6f8c49a21b784887d1897dd0b93f1ba69f15fb521b85460af4401dee56f38b07960fddbb64f506123102cfd8199e36bcb65c8c58cc8ea5ef6bd950d946c0a4e85a6901819abf5ba2972bd39ee42d21bdaae870478acc5a696ef1fb5f8768d5093c40b2bfc3e9163b4361587b38036f0310eb862f7761232567d680911fb33c1234afe5e1128cafed0d982b2683c465e0304152cba77b8ecdb01578b74e2d24e8cfe70dc24a6614d5c30cbb096fb17e65f33c3f6239db2b912aaa07a418b883fe635269b0d82c65f09a3f5b9f0266832a2d5bb117dec149f5cf49ec1ce41c0dea72c473527c90112f2532b6426866daeb3c78554e063db1dc701eb9070d1f2118599b139ca88739e065b721f72a39a6a399ba72cdfc7a1606de3b238a86cfd42e9b4dc48a3245cc17d2de473d2b57f53629657db220c8f9c1f6484b301c20143a0491f6da9f871f7bdcecefd6075ff54d0d54401127a25a088b7fcf7d27c7240d7d540f7541dd9fd79ef5a5a4ce386fb3502b5f70c4e2f6446439704fd1500dd1aa304a6bc3af4b21651ef202eec512727dcd0a39009a3440ed3e72ab67769a62e11336dc1faed3a0a4d3840158ad19a7cc2e159f954bebb691ceb279eeac9a72ead0a16531861e83551872afd19be88c6c0bd0c0c5fefc1812da3f3a9c442b70a53e94bf3564b8e79e4303ac7817dac990be11fe5d16e01802e0f39d1cdda653e5687d5511602c30a34ec9b398516aec57328e87f8546b9e9d06e4492183cdf69f062e26c531245177768e03d5728c35c75c988c2e88b75e923cd164cc1a78d2af4fb3682bb5cfb451dc80f88bcbc6e1ee3b772ac61e6abb4bfe1285780c7ab2ff958c0fe5793017b3cb3356faa85678dcab3b6b18e5d3eb047f4b024a4ef74a23a8e47f3acbb02a98822e5d514eb1787804b4b2788f551a4da4a5e1bac6ad7837222beaa4ee65eaff25e8c9f43d87bfef5d351add3e82b393d9d5c2f90a89d9d4d2424fa7882bf9f11fc0e481b998c2d2e900cba290a390b265214e125bb9c4b41faa11fdf8d27d770e4ff7a15271615f79d1456c2cb57ef66de258e6f25aa9d8688047fbfccbe844fe8e59e701ed606bcf79730979d9e4a58cd5aa4b59ca10d69faf8e91c67a2727230161ae4235be7d521d27ece326621b16552d9cfbcd89989ed0cb285b3279b0af48c98744d28cb9aa092f9abc1a672d275ee66b8a37fea830e64dfd0eeaa9a182150b54da19ca91c2e26603e3c2e31b8d08cbc587c8ff77794ad7ea70c831c375f51dfc540ffc19106a090f9e2d86675f43dfc2a56a5e84c843cb0a6b20faf78f54d2f243dd1cc576944cb105a7691395442ee9bfe7ee554721edae0f2fdb581e878ac8d850cd5f9be25f54fb9860c05df6c38c11b8e0c687879de74a0aab7e91e08ab0b9d7455ef35a26484a74467f51b4d875642366472a0c621a48d4f230be2401709e983f6ec928ede46fd72ba49b92f2772e0bd0a4f800dc83277645e60d5ce0324d8e56f17e27edcaefb2d531efbe0fb1901f4957c8b8f80fd26de00980c35210f33ffeabdfc4a453579bbc782559085c23564996ccbb25e752cebc490d3f1d16e15d35e97929012990c480078e7ecfea6d73b914d8db191cfbcc26024b4efb5c06e6ad2bccc98de8fa163cf895714670b87d6c725e853fa5d0c0962a1713c3ed03c09967a47970c5897a0edfe8699226bb862203bf14e8732cfb777319894cf1e53048e37755c717bbe22aeee4b83fa57ea5054694a19d102e3b3db09f1215e52b2fd3c79ee0889ff1ea6006fddec15002252a6922a64284732d0bd433d0b9195521f302856a2db543e723c010d2f0bc66fb26e333571e622bdfa2bb499216235de88d032a6100f1de0a0d322c7b4bcf88f05c4853595fe5c9bb0afae4e14c166e96f2d1cdbc1b5c5b5895e089a62c6d87178a019b812d16bae793294c810bff8229edd31a92df697641768fa8ea0208975f6a0b48b3351a6c9c47fdf54763d52b1c04e04dbf7bd4d1cefe08f192485ecdb305e9e1eada866a097533125a70925f14d9d7b3359beeaaf4b75c9433732e4d6f8a8307a898cc0682ebb5967e24e75f5406f5d313ffaa25966d60660c86543f2a1871c3f6ac15f56dae10bff64eaa1d313a6a2565579b5f85f8bd753654ea1d1f653c3dfb7de668ec48da9e2e851a9e103d40251ac160a11b644369e410db6ff3ed599b374a8d9e4be997e3a67ffc6ea5aa92848fc5f19866df2efba99f9b5df509d751db97bc76d4b3ad98bdca5955f30d8727f82c961aabcc97d103308158f508ed435483f1d5c4b2d77aee039a0e5c08c1fcf1606a5ec6ef8c0d12adc837e49fe6d51093b79d544e9d6996ecb0ba2b914f699f4637ce26d88795f09ff814e4d2b7daf9e466201dade45f37c1b12c0ab0c3f74042509915ed7cd723fc92e6e61fe8fcccebdd5cdd917e5e373ea8a9f079ee4b394dc47bfcfc3053fd590ea1c4afacfab6277b5399754b483861dac8d6dccfa8c4cefff2da93a14faf537d1d9f0018748b9459d2fd5206c1fc710a412c907b22e4d0813345bf019a6a4957c2ef5279b8663ec0f91d430fa780a8f1ccdefd088e18f3fd9e79b0f8efdb0a131bbc047f2ebd5779ebe8b5932163af6a746599639ce6cd64becf671f42c99c0e853ad5baac0bbff5a826b057372549705003de8b22192b3a10ad01ea300ca375d38514f708e905c8c193b8ebe820da2ab80f1241d327506faf7e8206e48a185f08fc501501359351c7422a8b73e0e828bc76d40544c21731e7292fa6e85b7fb8c29e536aad736e56b5a5806d9586edbb1aeb998cb4e099d70081c06bfa1236410544cebdf24548928316a8b2cb945f7054e59ffd710ddee6e41895f72298c9ea97449ef84187bbbdd55a229d12e92e3386a5ae7f27dcd22a2ccb2ff12285342ba72c79efcc9b6e704ab3c15aaf2cfb85016e219343c3c1c9af171e357ef71923c26187d59862b4bda2343a18ae1c9e7521c232b3eb7619163d71a7965c4f9a023b5f30ea022c6d483901b7c3b52b8485d3bd6a9430812e03ee9d8585570f99666bb4027f4c7e468e8373c32d0453b46046d002f923323cb995174e7d5c78daed15aef32a1d2a530092a4b252301e825c7638de9ad87facd585718876547530e54e5a54e05957031659c829f9d1347462c5b6a158b94a30c983b712522eaa09e448637f3c341ba76bc6437f60243ae7b1c0fed78ce23fc3a9e54072638624641cdad2361edd9cfdd42e1b4a578c7fa56301675c9b3825e0fd8e2978a401647b7094302ad46f67c8fe6e9497949e983e5aadfca49a01c7c77d168108a65cd504dd346cadd1a274ff3232fb3066cd874467341aa0724dd3c298e5ac155c030d824f5e099bdd3c46067f522f320dcf12b8051c3c29c6d9e786b3fe7517a92326c6676bd3fce06a376b2fb71220a0ba0206c640335258501c49bbab69139b8d0658df4ad73e665e212fbab0a5322c7e6330752ee1d0e949edf64a5f355b32147ccbf75f5b7c7487587e016c3b62892d9ff0c8d074732e4e253011035d73168525f97152e7175aa05f43c86bc782e27b719f608931d05310b6e27d95276d1b1d61d1110f59a152b5097008fea28f3732b3d496e45023206c061eb7fac8f1de36e7d576644a069cbf4720540df8bd1eb1c64f8dd8c523938924779a9c9662c532d0371344a9e1dedea20ad55c8c2d65c58b0c507170e37895dea17c0aeccc1cae94474643a65c27e5b7ce5ef7f4fd91ba2f4d03ec9b247f87f7766e7045bce71b0f81fb97556df03b9c67d54d6c097184b155c6573bdcf52320cb0609746414d8932c3188b13f96a7072786b52bb4b2e1d6ee3ecfee893efeb606750e607fa634cea029cd5c93ade99e2f592b68110a323b8f2ed20217be01082acfa30c77c45b30d2a6550cb9a71c0169c358c1ddf6672d780ad03550ce674d2ce019eafb14eee59c6a107113b2e19544974c8dff3f81acd2d7dabc1cbf02293e49c363601640e730ce75df7ec321af3bf0039280bd076597b54c9026b4f4a31f0e91de0030a32117a3b6251b747975528547ca2bd54654e75b8cc5e73c205d15a95336c5abbf6d1f6097a80f4bec757674058f08b87db54186739a5d6f135ea60d0844e6134c30abb8f58db80c5089081b7219ca179c3143f45f8dde22d5fc70173ae78177aaaf369251d616f1e538812bad2faae517e3e9a69994fe0d465eac7f573df5ffe8ec995dc625afb4d61953f95ce222ccd3327fec0fd96de329fcb22e5bde2650b983f6fd5471429b33710b29efada1c6ffc3121809f66899ed425caee2035f66f34f19211763e646d445c4f3b064488af6b99fe0f93951ee247e90eb6dc95fa9bf7394d66ba70b49e212edf2ddcef7619c116659422201fd7c619334dd1d6e7cb80311aeedbe4a74cac43d3c9242142282ff3c106bcf177389d648aceb7e354419df2dd1288081a7e317ab0971d058693ed3e346300f6f2f50ad36f775a1ae14279934a24963e3ebf97a4feb9522e49cbed24621adcf5c3b3dae1757ba9d1d8589987de598bd8331c08357fc49dfde1bd2e5719197a1c683cb59f1696bfdc957dd419602ee9eee265a01c412ed4108d68723aaa4cd4a85916f484a8152ee27c7907dd7eb93e35989d2a36e4f3c6fec8eb8bb5b217a2b30d1ea1cbd11d33c4367f0fe5b7841f03b0c048fb953b9b1aee13deed1a0d65942e0f013d879ff51292c136653f5b81fbabdcf3a6bc239a0679867f0746dc937d46c6d6aa5770576606a0eba9797b23c61e866632ac8bd898f0a64877024d945468e2a4107569d071554d827cb8960fbf761569ec901108be95f7fb61ac3f626a6c7a10349386f39367edcd89e873f8cfde0b26ad88681311c8993bed37152600939efce95d4d438c7a037352c1642bdea7f9c63034e2bff02800c81506b44ec916458ee5c855ff2dad5c8db583db460fa22170ed4ca9b09f1adaf62562723063ce628626c92f0cb548e218e9de506181600f34f736d9eb0ef22feeb44024df0709b60d3ee919a54e092dd554c2bebf494c53d70b182f6fd36711f7498513cf37a3f7fd9795a35273f128b143859142ee22e66f3d557363a2c45832f7aa497326e314be948d43878d1f311510fe4f3a6281638c48884b0284d428efe8c6b001e1bb4448b2b6fdfdcfa670f8860a587952c2fa3379f030ff494ec0cff022177e86fb0b98becb4ab00b123a3b20abb3e456d9085465a37cb5f41b327386150c3944c8e6634400a2527717432335197ec9e7c95c6e765e00d8aaa4a8547c2d0162e59844b506abfe7d5b37f96998cb8aaa6a611d166f76be97bde3d2ccae03256f227486024ce5c22b2a927c03084103ca8b98b2a7bcfb30d0366762461162f7237fcfc37db0526eea7e88c09b8a556bedcb0f33257466c526a551fda85eb3addea6910c96618be5dae10716ac873396814be137c3fd77de992c295e1a3736895e0322fce10b7aacb4eb604b65b5b4c58f527ab48a3df7e37f9e3cbe199953b21a2e230cc62f3cbcd1c7d6b9e8184753865210da2270db0eefca4b2e5d360b58a1cf94f84b25a1feb0b561b23a968933fac15af07b3650f19e46e96f827a73994eabe6cddeeb3d4897178f83b391613ba0af67e0abbfce26bd9cbf141f0e1de3eea356179b3a56959a295ef1a25aea6da197498235baa046eb31b33bcd349bb2772d33d55488c7c1e68b94308078b37a9a4dcf598549f2d234058d1a6441bc9648dd5328069c8d45f656ecac09814f85321b466df1e5bc42f76d8c3378f60f535298aaae7661bd4898fdd4bc117a6f30b2e4e49b0aa83fce265ee3bc97fd082a2dd10bb433c068d7661641c55c355e13361302f6d6f9fb3819bf214507556f5fbc082bea8f0528187302806e8dc22fade4e72e242e8b5b360b18f77188a1eeb8fb87fb8ad8dc083582f86baa00e4c7985e9b0bde9dbdd8853e7b2ccd0b1359f30a0160ab02133d644da979d6c0de33c538c5c950fc38ed63a711ccd73bc9f7b68e3edb6c12b14c5515fd648d54d1a8550b525da5be4bd10e59cd6e5ac58d3f24777ecc7f54829327242bafbde630a5cc7df50409beb22fe048d84b90b0e14f29cae4e34a1f112374160405cd31ee5e3610597e145d03edda2f54940aff162903da432006fabe85c6096a6b5fea20a4889986555bbed8008d30555384975ab03b1fff89aa3a20518a8cbdff83fea9ffb36d4d4c67652d1992968a0d766e916da1b0bd908f7bad9aee7008869b1ae5d98895acb68f4fe6bf2a5fed80bcc914f589c8984c71179cec8a49fa0c8a80fafab31165981266e00c3c26212c7b46ad9ddde020ecc57af823d901c5387c3d064600f9cd779f8c1dda0abbc06cf02ed95d332adaf17afc1ada657dad4e5f53e09f17b41505abdeb8f52339ec0e3a838217030cc2a36861d380d38140f5981e7d7227c57610147d11675b79dc8a1205c27f9ea2f8cf484dd2dad65fd73196c9223d14a3c53d19ce38826af08acefb4f44fe698dcde15cf8d02abb78f64f3afddb1545043ddc874a29843f51cdf594eac4964136e8ff01f38562808fefe44f42362f97014c07ef831c7fa89de228bedb3b2fa5c64afb3e5042c13920cce934c24bb96df1d73df58759e759e75e1d7c407351e68e030d6153f693a96c3ad2f8c62a40beccedef95f601b0ecd7064bd696f9196f22046f0cf0863c089e8b3eda1cb18d2f46ff0247c2f12d2cd4edb90e2c0ee8af20cf79b868d26e497ebb0f9bf0f0889b457fd77d57f4f523fe5048b8df669d7a422bdbb6b2fb8daf407e23d299d11c8c3271e4cc443b37c774508f1ced3cca32d16961daa7dc697de4402f069a9fd90c8e2f835cb16ae3d145779bac2d7dafe387145e8ecc33fc0f11d729306af944319a7ee57d7c78dc63cc74bc66dd154c5522381a8a06d34e5288489bb2f4fd805269b6e8c809334ae29147ed5040afa80acd9fc676979d064d8104c1249ac053787fa067c6293dd4049599ec647de441754ebba50a0e0dae038f26539edb17226ab22dc058121769744d46ea917c9821c3cfb6592db84ee35f0ee8f384607d3bc19e1e587ab3a83182a48315a1f7e5a32f50e6d8433c70cc3a7324d46070f80887a7a78260609a9902d85b0c83ce17393c0e5c093cdde0101cf0cf9cf17cff04156690b1a2a71d74e77c7912f95acaa28576e3de008ec910dc31ce0d24a49904b6700ff6da7939367c6a56ee34cddc51c94eb3fd51018b65163331add69e6b50be01335b29ebd4ede1703c28cf4558066ec22910a8b340b52bfbe28ee604f27973966e9dd8432ff87f6f50e1ed31db4b90a693a06710443bf6183ecac4835d693f7f3a9e1d5dcf4dbbc8db8709380c87c2e1c1bec044344a5c8c496b97df1e195c59e52dda0588391623714470a10aae77c56065b9e0f350dcf2e18f8eb5729de27ad2d8e29c6a926fb30e485dca5cde59d55534de6ab50b1f8e5676ea217beb1968dd8c5976f8151b16552b797c9d860b1066f6e5eaea01f3f20aa89708c90b1be4fbad1de92045412f0f4bf967692f725e390525bb53d6d10aac3f74ce29ab90d5d476187c435fb85d8c2c56f3257a2d5183e39dfb05d1128b3b3157c3a41567272d462f61c302b705adc97de4a5127e1769a16fc66ef0cafba1f2223f8b0c597eed5f4557b300e06f5d0a67d6dee1f9e9d01d8bb76bbae49c632991be74d6bc39607ab62f40b7c384e5d3b89c21daaa70d00b873df3994473e49bc8a437023ad1688b27310e947881d60d16742d976c77172b2d353be5a80ed3cc005e015342643504d755cfaacf8a43794deda31e4634c93eae9d08330228999d0b5c3a02ea971857afcc0f7544e7b766c5ef3a044aada623a4740bcabcb0378368f31a3a767c026e9d3a9cfd8bc1fc6a013c21e06fa0797c15e253bdf815f818c8f89054baef5cc661386faa613964e33ebf8c1a52bfed087a636a4079b8277205a3590b802860bf0c7ffbcefcd23452e8a1679596e9327afeeb02a69cb1eb6e93d571a24adbb58750eaaf21fc9e4dfc4c1d227178f645f023f88a01d1f794e20d88919918837ccde86619a6a96542b222daae52c6e180356146eed5a6e4f6d1586616a32d020506eaa06501299c40bc361403df37eb53dedc2f302d6a4e65c74930e848125767611f637b2d1d7d61a7ce1bcff0d14f076d57b94e719d936d87808a12c447bd0eb3904de95db11c21bf06cef750324af4aa1cb6ece7f8f0bb6ee8b464eb4d52474403433ae01d5fd8c7c1e6a8c354142d0317e760f1e9f0e1b680bee7e584a9c07d58793ed46ca69beec70e5fbbc06d937658a53096552f53319ce71800982574fa550c1bf8d291674a6f957d97ee940d2adc67ed2ec42726b5491ad81e34afaaf4a12d2a510b1bbca6252ead2e0cb9b67d00ae4a425f0c8cb9d6d0a039a1a2c797488144fa5ae5618a027784b292ae278be711860bde321aa0a857759071d6bd835d0853aeb8fd63a89aea16a1c5f6fa15a69212dfe18ab5e6911c29eded396d6a529cabdcb0e34e9613c4ae58b49d7293763f9cc70aeacefb8b542d4e8e5ccd1bb423e970380fdb152f6ea8604ff8ab04ce3f7e55e0dc48de0db9dcc179e05dfd02933b3179383f8c969fe07586be85a073fe55b24f570493e776a81131419a5827110807f36f5d769fb0b6fb17f8bc81df84d5d4a17fc11489f08b7bc350134326f96fc15aab871886e155b9555f5d64285d21b1a077a409d8608c1e48536a7850796d2aa68fe146e072ccf2ef551a2a8ddf2f7a380def5eb1bc7969226663984de3e22c588b173ff6692118120eebfe3e1d6970120980d2b554da9449b75a480c864be0cc12008b223542b5c009bbfbdcad14cf310ba6d848e6d349d12b126db1b7550f30d40cc130dbe2bd81c6e9d54838de10870d6eeda8020b9db0a2158995079590eecf1cbbbd8ee59310decda056f5ed322e91198907601df5309c0289933bbaf778236f217064d67d2e744be86ee6c0f74db3a6666da143ba641db9a58bece2d95579c18796f091756a6b4493e9c323ec4b1419f84bdd02ee78276759071eb58f719e971f0edc05829b69220be6b594f213027444d0ac89021c5691c10312466a23063882c9d3f0d1f72e4ede538c5001d8a5dbffefcac496e140379dfa46b1412aff0f28fa035852625442a69d735c18dba19615571733d988d4b6191083185b070f3614076bc3747f64d2ad940f8d707c3b909a05a0eacc6bbc6332df538ba19f2300f571c39eb80134b9cd497fd6916d267d5b1d832d9bb47e13bae83ca82cb87c2895a5e4c0e28a7bf47e8e87755b9447416d31ebe8d1d255d783daeff6ef6a14257658abce21c0d8f31fe77702a2776631d8442123eaf6064c46944407603c1be17e88492a8e5cab42a293023a5308a044320339fa270fcf8bc038d3dfaab961a5aa7ee6159561619f791cedff9257e38de5dcd9ce5db968915999e64e8f00ff1f78a4607a1047dc14d12677b6d3cd3bbfcf6e2e0473425fae707d605b240d44834d731fe5e3047bfb17fa9b75ab1aaa0ed63d7abaaacb499e3b8753661297e7f9de7485b81baa5da76ccfddfa8131f4224383a84e9e1cb5612e6f4076fd3c7bcdc953c0dd75b726c604c2be62a8395c82e37002ce2ad37fcf0e057e1894182e3932d328f56918291621e449c25795b3fadd2e35c2b83b2dbd62f029a69faee6e1ae6a3f6fab2ada8266b452977da68fd86827225986e4c13d4e1aefcd5617aa3878ade115e74539c47764bdcf601d904a09408690b5cae0708c9e6560db26abfa80707b19653e5c93646565c3af6df7034664683061a10f5e35c201fff4d10bb0bd3859372aa188772b5c07cceb0de8e70969a5175f872c1ac1825d194c2988bed01107368a1909c3780ebe2a3f0d4e2e6c30d86f8a78c7f3c0c9e8bcfc59cf15ad86c6bdac7854003f82e783d6ec6fc220cf79b99febf34a31a428492640a13656cc90e71d3365b0440433b7dcce46f63e1592f1805fe9bbcef5a8349701b7189926366161e47e42c5ed45fc5b9c5fef1f950384390e817419ceea272cf7f939043025a4ed2b40baa6690c5742c65864c1f982d1b74ab61505d81fee40c3781f2ff2ee7c8e43922ab0b40a83ce1a64f90f274122726636f9800b8ee4ecbdd5adabd7ef9981f598dfbc047ddb0025d77091e3059a76985e3787a3b2190277b40272551ec18761ab90cca082ff44d4841a4de31c64be031751bec3c48bf106046e36e30b62317836c0594b98e60b4c8eed7282aa4497ac9fbfd90a2d3ce47e61ecebb0099182d3ad600d9bd62df4771e1ff61adf45e4c344a11db9842391e6f2b8198b326cfc5e20aef76144762308aecb3a1b97d0ff2ebd3f1f23135b82feeb16013941791f6002cce99381bcbf37474bf44145fcf7e494f46d35c4c6f4d43ade4576f42767a734c4a60d96f4b8a17861a0348978e257366191d5971d166ca3d5de47198a019feafaa05a2a69e173579b1d26403b8f80901742bc867e825c65d7b03439717caf58c036de1ae97a8801a7ad98309509f15888422c32ea9977391cb2d10a2e2bd26d36f2aa1b85246353cd67ff9ce396a4c44b2300de1778381ad3dcb9bd305752b17b324b9c42ae2ba8b2593e44f1b7b85beab16849cc2c0ed32b282c19d6aa82dae36b88f02fe72cd12daac2c193ff0b99bf6528a73aaef6431f9acbb86d77ac8f8b0eb024ef2b81a6a7c735750ee894cfbbbb45f0d258455a024b3d8d0c48fdb17b7514a528f8695063628be03b90553d5210c020ed72526c6dc47c31128573b072c29c5c051e6b2726df0ee8b69bf1faabe17cd468160b858b109889b6c01c2b5bdec2e21fce62863a81c9152bbf7ade74d20b30e7d195e375443b993f60c11910496c69fc7a8f1b22390845eb9f5386d832a0d10d9632510e5170af770b26064fa6dbb5c7a2b7e388eb39ce67806b298aa52addf804b7b838eeea6388306b041c9f4eede593b0451b176be3ac6126df57877708da98b361883e470cc9ce0fb821a69a4edbb75fbb469a052e922678bc09a24e8663eaf6a20f2f76857fc958ff86f348e4d2503bf577885f0de5c9ef0848da8991b1e3654c03d6fc12927e3bf7dfe6c5a88c88e0e76076c87b8e1bae501d3387e8433024570a82fef18deb4e637ebef56f4e89a6c83e4a42c8155ea88449221005024bdb087b7bef4be275ff71066562b4bf9d399fd6797f35a4f2b97116a258a2b33e53a8df7612ec5324693367037e90bbeee6819dc81c3034031a56e829e4ed168658fbc078bf8e71474ee87bdf9953b8cf3dbbc43a135dfc3b3984c6bdce366c2c808008b62ad3f823d5c89115e95f2dc031bf54df8f59f94fc32ae8afe7d2fac7d49fcec78e60b91a2d5f9f37613d5ee56754584de85ad595a65d25fe17d81c466afbebeec4151690c83ef9459337e8978059f6c7d5da25289ab1c9eb86bef7e0287e2f6e0119ef10e2869b6ab0a889aa143560d2748d02363436b2b75672fefb1232c484546b4f1f23453fb1ec7548fe7227142d315b375ab5b1c7ab33c10f0bd72555c5d6c901d0654bd300e188c826f4fca24a0b1db2526f3a7569fab95395ff5fdb6066c0d571e975dbf72f70ac58fd167d907885073314e58de3f07fd5e340d16b312ae565aa3971a108d7eed132ebcce330fcc1006bda9d9e3a90449003682364f4ab0d94bc4aaf95c709d8c35e3b2658b0afe806d274cdf4c38d05477628b465ab54738e778145f7a4005079cb1df5d9e9d8640332db0c672a7ddb06b55f037c6ba4fb6ad46a87f4dda5aed9744add3329ba2ba7e346ce9a595ff410946d44f7ad05cfa1e27a78c6d6c367d410b20052f49158e04ebba06b6efb9425a0f1bd45275aee99f9476c7d1f1774ca83423f3ec10034669d12d201410f6ab6f031a8f289378a5f44aea0374b5a9151141554d0bcbca4b893bb7a7fb4699986b2740ee76b5bcf6eb371a6c2fc6b87d63d46961422d544d1f9498ffdc3934e8e5b900671fc3926fe07d0c1108977027bd58114374538bacec02843038b493e2710e681e8b9f36a712f13b8df38356bda4c85449b0b91169595bbb42600f62b9643d4681a328ed3586fb452677089e3a6aa9aca22ce31e0f01dbbb7ec5f3eb22b4e4a0840e2660e664deac916629a4fda59ad1267e0790da175ff2b5b279a553478ce65461ea008913bda8a3db6cdb6146c77417b20a51a2bdc8a6fc7125c5c97c717303609bf11c8ba62f66220ea7621a70a87a617c15076a4e6d8963e81848f997799ab580edabaed591188877dceda6ae91a96c20f870e32346a869972549f5a12c7c85e95be19e01676dcd91afc362e6ab2e2a9bb484efb0a6c45a2f80895630cfd94d18d46b81500242c46d21617453d477042e9371af00bab2956d9fecd43a21d712a99f940e29f9093b04acb909b20cf101c4af485ce1405d3f1529714ba9814ee0dc8d0500e6e48d6b6cb1b9a87c80b727fc49a3543870807a2e830fd68bc9e8aa2ed991a29fa2742ccb7b3491529a9c5144cff05e46ed76e40155f8cee98583bf2eb3a1e4e80cdbec62e5e4b5feed976e72e31eccfc7cc18396269559013f8b1fd359eb8e52c71eb6675e37458c87f2fbc79054eac7f852c9d7a5549b1230fcba58650e27e8d66d04c6427b1f080b605df2a9b46bb6553fcdce3fad7d09a537c215e34f8789d3f4a05c3d297f8caa5707168288749481bbcce51a051ea005cc6438b8b50751a9703bb6611f48c82183a39606fae24901e374daa9ab528ae2a2105dbb82c208195f92a7614732d25d67c9589f82da0129c55e369bb2d4cf50c5af50b4a3b66685d557bccc2b8cece9e5dfba77220a995d4aa01c48be6dda9d63c73e701881dc3c3564f5fc6353be8c12b6a403aba6f3aff9604c0d4ff4d51af196c96a651f83d05120fba89174fbccea6a1d910802aafee3fe7ba94d6ba2443bb07b124364c5365ac8c8bd43a9bdbfefcbbd4bf0e65bf0287863746d95ebf24f86a96ee17d2a3d9e5ce6f0339d7e4e6a1de66347ab5f6cbbba867dac86d5e86bcf5c80fb7057b9a84f8ffab75dc2b8589124a741dfbfffb788182dfb5768461c3c865446734fa7fd81818a92c20a442cdce7ff0d9dd51ab80d451ab42b5f4e1d937b9393fbe0d5ca56995922950f7ce6e3717f7fb78b7a0c8ccda0913dd69c51c9a293949f0a1a91ac0742012f9df0d7c543d1b46a51040bf4ae158df7c2eec9efa5c50a150cf5d218fbf80196d51a4771a05c014e8d96f48619c309c9e795cb094497e141a57ff65b197f7234012ec4de0c8818547d5c30e4d6bd5adacfa1339cb56d1f0c0d191ba040e9fa7fc5f2c10594de6a8e945ba9344bdd4b7bcb58080b2bde6d090bc46ce64b10488f654d1f3910fd1f3d48c6c23ee738af774fc32e8abaf2e0cd0493e2c2726fcb4eef80c65902d057715cae9c59222939aa113f4adf1b1ac19580624dbe625ca4ca22980e4e807360e3859164401a866c0a2668367c2a6f0433f05442a388a6f4dfccf8ade44fdaa300434280bb58c61f382afd51e410c7859b986ab5c362b3bea58480f70a180fd925e3f19eb98fba005d9adb70a72473f035834d4bb63fd67be5d26269611240a9a4f7c37c48807144ac5b03d38e1fa6ecbd73a0773f25f16274a326f5516d2df09d57d098880372ff9c688517cf76fce85ab235796a115e6a9d22884ac166bddd52eafe5d358803c72f17895087c8992231d72a456aadb9406e1cd80ee7b4b874fc961d48e48f2d0b8321681f4f594e1bcfdc50838c6e14689fd33d2fb43dc5a7436f4c975ce2fe364384d235161d741927007f91817c7c2dcb40923446d08f4130086d0c285d55891deab3ecb3eca776bd62575510f51d0876c1f66a608e99c584266112d4f5d627eb1a7c6a2cef03496cae202f65fed47eeb530b41c8b5560e2f4c06ce30593bde9463999b0468d4a90f36ddf7764d19923a2c201547c143de76f251dfcbb169af2536dac21dbf110102b028fb94873a0b419a6556277359cc6b95f362ffef99e7277ebcf8356cffb9c9ce4aa8d2a2bf2ed3c1d4ca29e37d9e62780e4b9b38d3318bf2b53e0367222f18a80233632f481e666229fc45d2e8a2dd37408854a120b6bb852685d0889ebea90aaf6266ab0172f3b4e173c08f671f4c6000314b6196ac326ff3ca390e819596b126b17c018f182dbf74bbfdc15088fbb7fec0873954244ab2da04382d8fd28fb7b145134d28178142ba5d5e6353b19d0648c9d53399f896e09e9b6ad6d4233e58d200646cc150a9fd70e1a5387fd85680a9dc50d77bbf24c3ba27e16c96977834f0ee8a24b771c105acfd9d67a335a362d56b92b741e41bb8d697be0aea8ad442397f4f478b229219333565e4fb43fcead2e4a0ad9b9092d985b22fb282d84422f3beff96bcd30566d872f64fde77aa537d59d88efe2ddcf4f2b37e98c67447924652c41ac27154c7ec2bf48c9a6ce46c57baeed5b4f6ec6bed800c1f938c094a8ea793684a059b9677a7e696eba1a5c8010e8cf044bf55d20368b282d2b0fae3619f9d18bd5a08dbf1ce5042acb54e7d1d0d2362b0ab3b36b54093f41bc803d67fd4f4d99d5d2ba17891a6a995aa01b1b2ae203d65b443413de6111c2e4621a2af5dcf3a2c120f2f547105fceb86528fae656c761db7b2ef2dc3fabbf1fa3ecf5a7f396bc94189c2232a02f36921ed07e1a3f64ce8ea6efcddae169d6b066f04c687604ee7e79a03e8fb1ada09b0031818d7462b5a46b6fc65c7645ed449145399c44c4cfdb17edba5d25f29e0a0112b8fc4d38a6d1d0b6721ebbb9aaf9ecba9c1f92278b9e06971072ab11621c2ee7c15e5c35306e606e9b9e6cbd70748cbd657e8bf6ca06a13cd5c46a130e4f15d70c21fb5afc31f618c7b1e32c948528fd7b72d4b31cba90cc940bf0b3e157166ee59d3c60dd485464398b554e1735b0115250d026f1ba9a924eda3ae04c4c5a5c47fc41164f4120e52f6d4c460892ebeda4ee8ab2c37ba6e19712c06ca912b906b5394bf946620ccb27e72c9bfb8224d83346ce36ada45911ec789d2da0414998daeb790b92c125314a4f76f0227c225bceaca411634e3faac2c79482c15256802ae3de485ce5871186e1213d89b56192d785c1d24bdb06a8b5199e16980579c78cdd0d90ad04dd2b77ce1ae8d0a12aee6222704d52d28590daa11c776fbd59a42a4d2969f51f115c4f05993d660500d2ac3efb4648fa5257434f5e8d884deba47fc8b84ad7275eb4d5dbefb6a34df82c2a7c2cebabf690eb76d976773043d4fc96bbf4a9dbecc88bbdb3f3d54d4aeec1bf8705d59d134fb0ff8e91c69832f1444579cfdbb6752a4aaa11ec3ac4859d6dd245cc5a7ff09692e53b4dd1cd665dd730e1e2228479fe37edcdd32abdbf3f18c11138ab1c9b7c73e4d4b856faa4b8c4fdfefaff1d0eccf70e6b1e2eadbef6496cd2679349f99fa51e08477ea6adea084e2916ce2ea83116202fe3a5b02c7df37e9a455109ed9f8a4654443ddd282864b527813adc8cedea8f</script> <div class="hbe hbe-content"> <div class="hbe hbe-input hbe-input-default"> <input class="hbe hbe-input-field hbe-input-field-default" type="password" id="hbePass"> <label class="hbe hbe-input-label hbe-input-label-default" for="hbePass"> <span class="hbe hbe-input-label-content hbe-input-label-content-default">您好, 这里需要密码</span> </label> </div> </div></div><script data-pjax src="/lib/hbe.js"></script><link href="/css/hbe.style.css" rel="stylesheet" type="text/css">]]></content>
<categories>
<category>private-page</category>
</categories>
<tags>
<tag>私密</tag>
</tags>
</entry>
<entry>
<title>gin学习记录-自定义错误信息</title>
<link href="/2023/08/05/gin%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-%E8%87%AA%E5%AE%9A%E4%B9%89%E9%94%99%E8%AF%AF%E4%BF%A1%E6%81%AF/"/>
<url>/2023/08/05/gin%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-%E8%87%AA%E5%AE%9A%E4%B9%89%E9%94%99%E8%AF%AF%E4%BF%A1%E6%81%AF/</url>
<content type="html"><![CDATA[<h2 id="自定义错误信息"><a href="#自定义错误信息" class="headerlink" title="自定义错误信息"></a>自定义错误信息</h2><p>当校验错误时,根据返回的错误信息自定义一个错误提示返回给前端页面,方便处理。</p><span id="more"></span><hr><h3 id="定义需要用到的结构体"><a href="#定义需要用到的结构体" class="headerlink" title="定义需要用到的结构体"></a>定义需要用到的结构体</h3><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> SignUserInfo <span class="hljs-keyword">struct</span> {<br><span class="hljs-comment">// 添加验证器 常用的</span><br>Name <span class="hljs-type">string</span> <span class="hljs-string">`json:"name" binding:"required" msg:"昵称不能为空"`</span> <span class="hljs-comment">// 用户名</span><br>Age <span class="hljs-type">int</span> <span class="hljs-string">`json:"age" binding:"lt=100,gt=0" msg:"年龄不符合要求"`</span> <span class="hljs-comment">// 年龄</span><br>} <br></code></pre></td></tr></table></figure><hr><h3 id="封装成独立的函数"><a href="#封装成独立的函数" class="headerlink" title="封装成独立的函数"></a>封装成独立的函数</h3><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">GetValidMsg</span><span class="hljs-params">(err <span class="hljs-type">error</span>, user SignUserInfo)</span></span> <span class="hljs-type">string</span> {<br><span class="hljs-comment">// 将err接口断言为具体类型</span><br><span class="hljs-keyword">if</span> errs, ok := err.(validator.ValidationErrors); ok {<br>getObj := reflect.TypeOf(&user)<br>fmt.Println(<span class="hljs-string">"类型为:"</span>, getObj)<br><br><span class="hljs-comment">// 断言成功</span><br><span class="hljs-keyword">for</span> _, e := <span class="hljs-keyword">range</span> errs { <span class="hljs-comment">// 遍历每一个错误信息 报错信息可能有多个</span><br><span class="hljs-comment">// 根据报错字段名,获取结构体的具体字段</span><br><span class="hljs-keyword">if</span> f, exits := getObj.Elem().FieldByName(e.Field()); exits {<br>msg := f.Tag.Get(<span class="hljs-string">"msg"</span>)<br>fmt.Println(msg)<br><span class="hljs-keyword">return</span> msg<br>} f f, exits := getObj.Elem().FieldByName(e.Field()); exits {<br>msg := f.Tag.Get(<span class="hljs-string">"msg"</span>)<br>fmt.Println(msg)<br><span class="hljs-keyword">return</span> msg<br>}<br>}<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-string">""</span> <span class="hljs-comment">// 没有检查到验证器错误则返回空</span><br>}<br></code></pre></td></tr></table></figure><p><code>validator.ValidationErrors</code> 是一个错误类型,用于存储验证器验证失败的错误信息 <code>err.(validator.ValidationErrors)</code> 表示<br>将 <code>err</code> 转换为 <code>validator.ValidationErrors</code> 类型。如果 <code>err</code> 是 <code>validator.ValidationErrors</code> 类型或者它的指针类型,则类型断言会返回转换后的 <code>validator.ValidationErrors</code>类型的值和 <code>true</code>。如果 <code>err</code> 不是 <code>validator.ValidationErrors</code>类型或者它的指针类型,则类型断言会返回 <code>validator.ValidationErrors</code>类型的零值和 <code>false</code>。 </p><p>通过 <code>getObj.Elem()</code> 获取结构体的元素类型,因为 <code>getObj</code> 是结构体指针类型的反射对象,<br>使用 <code>Elem()</code> 方法可以获取指针指向的实际结构体类型。<br>然后,使用 <code>FieldByName()</code> 方法根据错误字段名 <code>e.Field()</code> 查找结构体中对应的字段。<br>如果字段存在, <code>f</code> 就是一个包含该字段信息的反射对象,并且 <code>exits</code> 为 <code>true</code> 。如果字段不存在,<br><code>f</code> 将是零值的反射对象,并且 <code>exits</code> 为 <code>false</code> 。</p><hr><h3 id="main函数"><a href="#main函数" class="headerlink" title="main函数"></a>main函数</h3><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {<br>router := gin.Default()<br><br>router.POST(<span class="hljs-string">"/check"</span>, <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(c *gin.Context)</span></span> {<br>fmt.Println(<span class="hljs-string">"访问..."</span>)<br><span class="hljs-keyword">var</span> user SignUserInfo<br>err := c.ShouldBindJSON(&user) <span class="hljs-comment">// 返回error信息,不报错则返回空</span><br><span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {<br><br>customErr := GetValidMsg(err, user) <span class="hljs-comment">// 自定义的错误信息</span><br><br>c.JSON(http.StatusBadRequest, gin.H{<span class="hljs-string">"msg"</span>: customErr})<br><br><span class="hljs-keyword">return</span><br>}<br><br>c.JSON(http.StatusOK, gin.H{<span class="hljs-string">"data"</span>: user})<br>})<br><br>err := router.Run(<span class="hljs-string">":80"</span>)<br><span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {<br><span class="hljs-keyword">return</span><br>}<br>}<br></code></pre></td></tr></table></figure><p>截图如下:<br><img src="https://s2.loli.net/2023/08/05/RMEKjNrvoHPy1kf.png" alt="校验失败返回自定义的错误信息"></p><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p>学习这一节的时候看不懂,看源码也看不明白,这个时候最可靠的就是chatGPT了,全部代码复制粘贴发给他,然后让他一个函数一个函数解释,真是太棒了。</p>]]></content>
<tags>
<tag>go</tag>
<tag>gin</tag>
<tag>学习记录</tag>
</tags>
</entry>
<entry>
<title>gin学习记录-四大请求方式</title>
<link href="/2023/08/04/gin-%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-%E5%9B%9B%E5%A4%A7%E8%AF%B7%E6%B1%82%E6%96%B9%E5%BC%8F/"/>
<url>/2023/08/04/gin-%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95-%E5%9B%9B%E5%A4%A7%E8%AF%B7%E6%B1%82%E6%96%B9%E5%BC%8F/</url>
<content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><p><img src="https://s2.loli.net/2023/08/04/8BK3UqZutdebsgR.png" alt="辉夜酱"></p><h1 id="以文字资源为例学习四大请求方式"><a href="#以文字资源为例学习四大请求方式" class="headerlink" title="以文字资源为例学习四大请求方式"></a>以文字资源为例学习四大请求方式</h1><span id="more"></span><p>GET:从服务器取出资源(一项或多项)<br>POST:在服务器新建一个资源<br>PUT:在服务器更新资源(客户端提供完整资源数据)<br>PATCH:在服务器更新资源(客户端提供需要修改的资源数据)<br>DELETE:从服务器删除资源</p><blockquote><p>好像是五大请求方式… 不过没有用到PATCH</p></blockquote><ul><li>以文字资源为例 分别<strong>对应增删改查</strong></li></ul><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs text">请求方式 请求内容 说明<br>GET/articles 文章列表<br>GET /articles/:id 文章详情<br>POST /articles 添加文章<br>PUT /articles/:id 修改某一篇文章<br>DELETE /articles/:id删除某一篇文章<br></code></pre></td></tr></table></figure><hr><h2 id="导入相应的包"><a href="#导入相应的包" class="headerlink" title="导入相应的包"></a>导入相应的包</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">package</span> main<br><br><span class="hljs-keyword">import</span> (<br><span class="hljs-string">"encoding/json"</span><br><span class="hljs-string">"fmt"</span><br><span class="hljs-string">"github.com/gin-gonic/gin"</span><br><span class="hljs-string">"net/http"</span><br>)<br></code></pre></td></tr></table></figure><hr><h2 id="自定义需要的结构体"><a href="#自定义需要的结构体" class="headerlink" title="自定义需要的结构体"></a>自定义需要的结构体</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// ArticleModel 文章格式 简单写</span><br><span class="hljs-keyword">type</span> ArticleModel <span class="hljs-keyword">struct</span> {<br>Title <span class="hljs-type">string</span> <span class="hljs-string">`json:"title"`</span><br>Content <span class="hljs-type">string</span> <span class="hljs-string">`json:"content"`</span><br>}<br><br><span class="hljs-comment">// 封装响应格式</span><br><span class="hljs-keyword">type</span> Response <span class="hljs-keyword">struct</span> {<br>Code <span class="hljs-type">int</span> <span class="hljs-string">`json:"code"`</span><br>Date any <span class="hljs-string">`json:"date"`</span><br>Message <span class="hljs-type">string</span> <span class="hljs-string">`json:"msg"`</span><br>}<br></code></pre></td></tr></table></figure><hr><h2 id="文章列表"><a href="#文章列表" class="headerlink" title="文章列表"></a>文章列表</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">getList</span><span class="hljs-params">(arg *gin.Context)</span></span> {<br>list := []ArticleModel{<br>{<span class="hljs-string">"go语言入门"</span>, <span class="hljs-string">"本书是go语言入门基础"</span>},<br>{<span class="hljs-string">"c语言入门到入土"</span>, <span class="hljs-string">"本书是c语言入门教程,面向入土"</span>},<br>{<span class="hljs-string">"数据库从删库到跑路"</span>, <span class="hljs-string">"本书教你如何从删库到跑路"</span>},<br>}<br><span class="hljs-comment">// 返回的Response的code是随便写的,实际应该定义一些有意义的响应码</span><br>arg.JSON(<span class="hljs-number">200</span>, Response{http.StatusOK, list, <span class="hljs-string">"响应成功"</span>})<br>}<br></code></pre></td></tr></table></figure><ul><li>postman响应截图:<br><img src="https://s2.loli.net/2023/08/03/dRHYulPCcNWgEs7.png" alt="文章列表"></li></ul><hr><h2 id="文章详情"><a href="#文章详情" class="headerlink" title="文章详情"></a>文章详情</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">getDetails</span><span class="hljs-params">(arg *gin.Context)</span></span> {<br><span class="hljs-comment">// 简写 实际应根据获取的id到数据库中查询</span><br>book_id := arg.Param(<span class="hljs-string">"id"</span>)<br>fmt.Printf(<span class="hljs-string">"获取到id: %v\n"</span>, book_id)<br><span class="hljs-comment">// 此处直接得到查询数据库的结果</span><br>article := ArticleModel{<br><span class="hljs-string">"c语言入门到入土"</span>, <span class="hljs-string">"本书是c语言入门教程,面向入土"</span>,<br>}<br><br>arg.JSON(http.StatusOK, gin.H{<span class="hljs-string">"id"</span>: book_id, <span class="hljs-string">"response"</span>: Response{http.StatusOK, article, <span class="hljs-string">"响应成功"</span>}})<br>}<br></code></pre></td></tr></table></figure><ul><li>postman响应截图:<br><img src="https://s2.loli.net/2023/08/03/dRHYulPCcNWgEs7.png" alt="文章详情"></li></ul><hr><h2 id="创建文章-和-修改文章"><a href="#创建文章-和-修改文章" class="headerlink" title="创建文章 和 修改文章"></a>创建文章 和 修改文章</h2><blockquote><p>这俩放一起了,因为用到同一个函数</p></blockquote><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// 封装的一个处理json数据的函数</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">bindJson</span><span class="hljs-params">(arg *gin.Context, obj any)</span></span> (err <span class="hljs-type">error</span>) {<br>body, _ := arg.GetRawData() <span class="hljs-comment">// 获取到post传的数据</span><br><br>contentType := arg.GetHeader(<span class="hljs-string">"Content-Type"</span>)<br><br>fmt.Println(<span class="hljs-type">string</span>(contentType)) <span class="hljs-comment">// 内容类型</span><br><span class="hljs-comment">// 类型 对应的结果</span><br><span class="hljs-comment">// json:application/json</span><br><span class="hljs-comment">// from-data: multipart/form-data; boundary=--------------------------629880651178044255286053</span><br><span class="hljs-comment">// x-www-form-urlencoded:application/x-www-form-urlencoded</span><br><br><span class="hljs-comment">// 根据以上可以这也判断并解析json数据 不同类型的数据用不同的处理方式</span><br><span class="hljs-keyword">switch</span> contentType {<br><span class="hljs-keyword">case</span> <span class="hljs-string">"application/json"</span>: <span class="hljs-comment">// 简写,这里就只解析json数据</span><br><br><span class="hljs-comment">// 将post的数据反序列化解析成结构体</span><br>err := json.Unmarshal(body, &obj)<br><span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {<br>fmt.Println(err)<br><span class="hljs-keyword">return</span> err<br>}<br><span class="hljs-keyword">default</span>:<br>fmt.Println(<span class="hljs-string">":D"</span>)<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span><br>}<br><br><span class="hljs-comment">// 创建文章</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">post</span><span class="hljs-params">(arg *gin.Context)</span></span> {<br><span class="hljs-keyword">var</span> article ArticleModel<br><br>err := _bindJson(arg, &article)<br><span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {<br><span class="hljs-built_in">panic</span>(err)<br>}<br><br>arg.JSON(http.StatusOK, Response{http.StatusOK, article, <span class="hljs-string">"创建成功"</span>})<br>}<br><br><span class="hljs-comment">// 修改文章</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">put</span><span class="hljs-params">(arg *gin.Context)</span></span> {<br><span class="hljs-comment">// 拿到id</span><br>fmt.Printf(<span class="hljs-string">"获取到id: %v\n"</span>, arg.Param(<span class="hljs-string">"id"</span>))<br><br><span class="hljs-keyword">var</span> article ArticleModel<br><span class="hljs-comment">// 拿到修改后的文章内容</span><br>err := _bindJson(arg, &article)<br><span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {<br><span class="hljs-built_in">panic</span>(err)<br>}<br><br>arg.JSON(<span class="hljs-number">200</span>, Response{http.StatusOK, article, <span class="hljs-string">"修改成功"</span>})<br>}<br></code></pre></td></tr></table></figure><ul><li><p>postman响应截图:</p></li><li><p>创建文章<br><img src="https://s2.loli.net/2023/08/03/s8zIogb6QUX7Cy4.png" alt="创建文章"></p></li><li><p>修改文章</p></li><li><p><img src="https://s2.loli.net/2023/08/03/qhCy6NfoR2KBDGJ.png" alt="修改文章"></p></li></ul><hr><h2 id="删除文章"><a href="#删除文章" class="headerlink" title="删除文章"></a>删除文章</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> _<span class="hljs-title">delete</span><span class="hljs-params">(arg *gin.Context)</span></span> {<br><span class="hljs-comment">// 拿到id</span><br>fmt.Printf(<span class="hljs-string">"获取到id: %v\n"</span>, arg.Param(<span class="hljs-string">"id"</span>))<br><span class="hljs-comment">// 实际中 拿到id然后去数据库中查找、删除 ...</span><br><br>arg.JSON(<span class="hljs-number">200</span>, Response{http.StatusOK, <span class="hljs-string">""</span>, <span class="hljs-string">"删除成功"</span>})<br><br>}<br></code></pre></td></tr></table></figure><ul><li>postman响应截图:</li><li>删除文章<br><img src="https://s2.loli.net/2023/08/03/K9gy6LCsJivmb4N.png" alt="删除文章"></li></ul><blockquote><p>删除后只需要返回一个删除成功的提示,没别的东西,所以很空,==实际开发还需要对数据库进行操作…==</p></blockquote><hr><h2 id="main函数"><a href="#main函数" class="headerlink" title="main函数"></a>main函数</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {<br>router := gin.Default()<br>router.GET(<span class="hljs-string">"/articles/"</span>, _getList)<br>router.GET(<span class="hljs-string">"/articles/:id"</span>, _getDetails)<br>router.POST(<span class="hljs-string">"/articles/"</span>, _post)<br>router.PUT(<span class="hljs-string">"/articles/:id"</span>, _put)<br>router.DELETE(<span class="hljs-string">"/articles/:id"</span>, _delete)<br><br>err := router.Run(<span class="hljs-string">":80"</span>)<br><span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {<br><span class="hljs-keyword">return</span><br>}<br>}<br></code></pre></td></tr></table></figure><hr><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p>在写这篇博客的时候很晚了,我听到楼下几个少年大声唱着《海阔天空》。暑假里,几个好朋友一起喝,喝到很晚回家路上一路高歌,放肆的享受着年轻的自己…… </p><p>我应该也有这样放飞自我的时候,但是已经记不太清了。我把这事告诉朋友。他说,给他一笔钱他也海阔天空🤣🤣 </p><p><strong>over~</strong> </p>]]></content>
<tags>
<tag>go</tag>
<tag>gin</tag>
<tag>学习记录</tag>
</tags>
</entry>
<entry>
<title>此页作为测试页</title>
<link href="/2023/07/26/test/"/>
<url>/2023/07/26/test/</url>
<content type="html"><![CDATA[<p>碎碎念…</p><span id="more"></span><p>现在好多地方还比较简陋,先记下来:</p><ul><li><del>首页的文字设为显示封面更好,显示一大段文字看着难受</del></li><li><del>代码框的样式得换掉,太丑了,想换成mac主题的</del></li><li><del>我需要一个临时的,私密的发布页…</del></li><li>一些封面图还没有改,因为没有合适的图了…</li><li>gitalk 原来也不能让未登录用户评论啊,还以为可以呢… 😩</li><li><del>要给一些文章加上锁,可是在文章前面添加字段也没用</del>😥</li></ul><p>先这样,等我慢慢改吧</p>]]></content>
<tags>
<tag>test</tag>
</tags>
</entry>
<entry>
<title>Hello World</title>
<link href="/2023/07/19/hello-world/"/>
<url>/2023/07/19/hello-world/</url>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ hexo new <span class="hljs-string">"My New Post"</span><br></code></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ hexo server<br></code></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ hexo generate<br></code></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">$ hexo deploy<br></code></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html">Deployment</a></p>]]></content>
</entry>
</search>