<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Gumeng’s blog</title>
  
  
  <link href="https://blog.jishuqin.cn/atom.xml" rel="self"/>
  
  <link href="https://blog.jishuqin.cn/"/>
  <updated>2024-07-07T10:17:01.661Z</updated>
  <id>https://blog.jishuqin.cn/</id>
  
  <author>
    <name>顾梦</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>程序员做饭</title>
    <link href="https://blog.jishuqin.cn/posts/41888/"/>
    <id>https://blog.jishuqin.cn/posts/41888/</id>
    <published>2024-07-07T09:44:15.130Z</published>
    <updated>2024-07-07T10:17:01.661Z</updated>
    
    <content type="html"><![CDATA[<h1>程序员做饭</h1>    <div id="aplayer-okdkcQUC" class="aplayer aplayer-tag-marker meting-tag-marker"         data-id="2158973221" data-server="netease" data-type="song" data-mode="circulation" data-autoplay="true" data-mutex="false" data-listmaxheight="340px" data-preload="none" data-theme="#ad7a86"    ></div><h2 id="1-前言">1. 前言</h2><p>因为点外卖又贵又不好吃，所以上周买了电磁炉，平底锅等，开始了周末做饭的日子啦，一个人也要按时吃饭~</p><p>推荐程序做饭指南：<a href="https://cook.aiursoft.cn/">https://cook.aiursoft.cn/</a> ，周末做了里面的两道菜 干煸仔鸡 和 可乐鸡翅。</p><h2 id="2-做饭">2. 做饭</h2><p>做饭感觉就是准备工作比较麻烦哈哈，煮起来是一下子就好了</p><p><img src="https://cdn.gumengyo.top/Qexo/24/7/5913eb5f5f90c184a34d541192b10caa.jpg" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top/Qexo/24/7/e1b41166fbb1b6bdd68c9823216b4d17.jpg" srcset="/img/loading.gif" lazyload alt=""></p><h2 id="3-干饭">3. 干饭</h2><p>做完后是这样子，看着还是很香的，还有晚上煮的面条，面条煮起来就是简单快速哈哈~</p><p><img src="https://cdn.gumengyo.top/Qexo/24/7/574a5f442c741261d39245522e250b9d.jpg" srcset="/img/loading.gif" lazyload alt="干煸仔鸡"></p><p><img src="https://cdn.gumengyo.top/Qexo/24/7/9b4296a1c536ec39a0a5968341d1f53c.jpg" srcset="/img/loading.gif" lazyload alt="可乐鸡翅和耗油生菜"></p><p><img src="https://cdn.gumengyo.top/Qexo/24/7/70f25d0e67bb1097f5baa81ec6ff4b0d.jpg" srcset="/img/loading.gif" lazyload alt="简易汤面"></p><p>做完就是嘎嘎炫了，自己做的就是香，直接光盘，做饭干饭都很快乐，痛苦的就是得洗碗啦。</p><p>说到这 现在就去洗碗了 中午的还没洗呢~ 🥲</p><p><img src="https://cdn.gumengyo.top/Qexo/24/7/12195baaa142ff3763d6fcfa7369d936.jpg" srcset="/img/loading.gif" lazyload alt="干饭"></p><p>END</p>]]></content>
    
    
    <summary type="html">这篇文章主要介绍了一位程序员购买电磁炉和平底锅后开始自己做饭的经历和感受。作者认为外卖贵且不好吃，因此决定自己动手做饭，尤其是在周末。文章中推荐了一个做饭指南链接，分享了作者周末尝试的两道菜：干煸仔鸡和可乐鸡翅，以及晚上煮的面条。图文并茂地展示了做饭的过程和最终成果，包括美味的菜肴和简易的汤面。最后，作者提到了做饭的乐趣，但也意识到了洗碗的繁琐工作。</summary>
    
    
    
    <category term="做饭" scheme="https://blog.jishuqin.cn/categories/%E5%81%9A%E9%A5%AD/"/>
    
    
    <category term="日常" scheme="https://blog.jishuqin.cn/tags/%E6%97%A5%E5%B8%B8/"/>
    
  </entry>
  
  <entry>
    <title>Kafka Stream 基本使用</title>
    <link href="https://blog.jishuqin.cn/posts/23156/"/>
    <id>https://blog.jishuqin.cn/posts/23156/</id>
    <published>2024-05-29T08:36:10.397Z</published>
    <updated>2024-06-28T11:36:15.541Z</updated>
    
    <content type="html"><![CDATA[<h1>Kafka Stream 基本使用</h1><blockquote><p><a href="https://kafka.apache.org/37/documentation/streams/">Apache Kafka Streams</a> 是一款强大的实时流处理库，为构建实时数据处理应用提供了灵活且高性能的解决方案。</p><p>Kafka Streams 是 Apache Kafka 生态系统中的一部分，它不仅简化了流处理应用的构建，还提供了强大的功能，如事件时间处理、状态管理、交互式查询等。其核心理念是将流处理与事件日志结合，使应用程序能够实时处理数据流。</p></blockquote><h2 id="1-前言">1. 前言</h2><p>由于公司需开发数据清洗服务，而且需要实时性高的数据处理，结合线上数据是输出到kafka，故采用 Kafka Streams 来作为数据清洗服务开发，本编结合一个demo，讲述 Kafka Streams 的基本使用。</p><p>Kafka Streams的特点：</p><ul><li>设计为<strong>一个简单而轻量级的客户端库</strong>，可以很容易地嵌入到任何 Java 应用程序中，并与用户为其流应用程序提供的任何现有打包、部署和操作工具集成。</li></ul><ul><li><strong>除了 Apache Kafka 本身作为内部消息传递层之外，对系统没有外部依赖</strong>关系;值得注意的是，它使用 Kafka 的分区模型来水平扩展处理，同时保持强大的排序保证。</li><li>支持容<strong>错本地状态</strong>，从而实现非常快速高效的有状态操作，如窗口联接和聚合。</li><li>支持 <strong>exact-once</strong> 处理语义，以保证每条记录将只处理一次，即使 Streams 客户端或 Kafka 代理在处理过程中出现故障也是如此。</li><li>采用<strong>一次一条记录的处理</strong>来实现毫秒级处理延迟，并支持<strong>基于事件时间的窗口化操作</strong>，以及记录的无序到达。</li><li>提供必要的流处理基元，以及<strong>高级流 DSL</strong> 和<strong>低级处理器 API</strong>。</li></ul><h2 id="2-核心概念">2. 核心概念</h2><ol><li><strong>Stream</strong>: 一个无限的、有序的、可重放的、并且可失败的数据记录序列。在Kafka中，一个流可以看作是一个或多个Kafka主题的消息记录。</li><li><strong>Stream Processor</strong>: 流处理器是对流数据进行处理的逻辑单元。它可以是一个简单的消息转换（例如，增加数据的时间戳），也可以是一个复杂的，如聚合或连接多个流。</li><li><strong>Topologies</strong>: 流处理拓扑是构成流处理程序的逻辑流程。一个拓扑是由多个处理器节点（处理器和转换器）和源节点（用于读取流数据）和汇节点（用于输出处理后的数据）组成的。</li><li><strong>KStream</strong>: 主要代表一种记录流，其中每个数据记录代表一个独立的数据实体。</li><li><strong>KTable</strong>: 表示一个更新流，每个数据记录表示一个表中的行。在更新流中，具有相同键的数据记录会覆盖先前的记录，类似于传统数据库的更新操作。</li><li><strong>Global KTable</strong>: 与KTable类似，但在所有应用程序实例中都全局可用，并且是只读的。</li><li><strong>State Stores</strong>: 本地存储，用于存储中间处理状态。状态存储可以是持久化的也可以是非持久化的。它们使得流处理器可以提供有状态的操作。</li><li><strong>Windowing</strong>: 用于将无限的数据流分成有限的块进行处理。窗口可以是时间驱动的（如固定时间窗口、滑动时间窗口）或基于数据记录数的。</li><li><strong>Processor API</strong>: 一个低级别的，允许开发人员定义和连接自定义处理器的API。使用该API，开发人员可以控制数据的流动和事件处理的精细细节。</li><li><strong>DSL (Domain Specific Language)</strong>: 高级流DSL是一个构建流处理拓扑的表达式式的API。它提供了一套简单的操作符用于过滤、映射、聚合等操作。</li></ol><p>详细介绍请查看官方文档：<a href="https://kafka.apache.org/37/documentation/streams/core-concepts">https://kafka.apache.org/37/documentation/streams/core-concepts</a></p><h2 id="3-基本用法">3. 基本用法</h2><blockquote><p>本例结合官方文档中的示例，输入文本计算单词，用于处理<strong>无限的数据流</strong>，统计出单词数量输出。</p><p>Demo 仓库地址：<a href="https://github.com/Gumengyo/kafka-stream-demo">https://github.com/Gumengyo/kafka-stream-demo</a></p></blockquote><p><img src="https://cdn.gumengyo.top/Qexo/24/5/46ee198abe46df4142f01939892a27ae.png" srcset="/img/loading.gif" lazyload alt=""></p><p><strong>引入依赖：</strong></p><figure class="highlight xml"><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 xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.kafka<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>kafka-streams<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.kafka<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-kafka<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.projectlombok<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>lombok<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">optional</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">optional</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br></code></pre></td></tr></table></figure><p><strong>创建Topic：</strong></p><figure class="highlight shell"><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 shell">./kafka-topics.sh --create --bootstrap-server localhost:9092 --topic streams-plaintext-input --replication-factor 1 --partitions 1<br><br>./kafka-topics.sh --create --bootstrap-server localhost:9092 --topic streams-wordcount-output --replication-factor 1 --partitions 1<br></code></pre></td></tr></table></figure><h3 id="3-1-结合Spring框架构建Kafka-Streams">3.1 结合Spring框架构建Kafka Streams</h3><ol><li>配置文件</li></ol><figure class="highlight yaml"><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 yaml"><span class="hljs-attr">server:</span><br>  <span class="hljs-attr">port:</span> <span class="hljs-number">9991</span><br><span class="hljs-attr">spring:</span><br>  <span class="hljs-attr">application:</span><br>    <span class="hljs-attr">name:</span> <span class="hljs-string">kafka-demo</span><br>  <span class="hljs-attr">kafka:</span><br>    <span class="hljs-attr">bootstrap-servers:</span> <span class="hljs-string">localhost:9092</span><br>    <span class="hljs-attr">producer:</span><br>      <span class="hljs-attr">retries:</span> <span class="hljs-number">10</span><br>      <span class="hljs-attr">key-serializer:</span> <span class="hljs-string">org.apache.kafka.common.serialization.StringSerializer</span><br>      <span class="hljs-attr">value-serializer:</span> <span class="hljs-string">org.apache.kafka.common.serialization.StringSerializer</span><br>      <span class="hljs-attr">compression-type:</span> <span class="hljs-string">lz4</span><br>    <span class="hljs-attr">consumer:</span><br>      <span class="hljs-attr">group-id:</span> <span class="hljs-string">$&#123;spring.application.name&#125;-test</span><br>      <span class="hljs-attr">key-deserializer:</span> <span class="hljs-string">org.apache.kafka.common.serialization.StringDeserializer</span><br>      <span class="hljs-attr">value-deserializer:</span> <span class="hljs-string">org.apache.kafka.common.serialization.StringDeserializer</span><br><span class="hljs-comment"># kafkaStream新增以下配置</span><br><span class="hljs-attr">kafka:</span><br>  <span class="hljs-attr">hosts:</span> <span class="hljs-string">localhost:9092</span><br>  <span class="hljs-attr">group:</span> <span class="hljs-string">$&#123;spring.application.name&#125;</span><br><br></code></pre></td></tr></table></figure><ol start="2"><li>配置 Kafka Streams</li></ol><figure class="highlight java"><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 java"><span class="hljs-meta">@Setter</span><br><span class="hljs-meta">@Getter</span><br><span class="hljs-meta">@Configuration</span><br><span class="hljs-meta">@EnableKafkaStreams</span><br><span class="hljs-meta">@ConfigurationProperties(prefix=&quot;kafka&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">KafkaStreamConfig</span> &#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">int</span> <span class="hljs-variable">MAX_MESSAGE_SIZE</span> <span class="hljs-operator">=</span> <span class="hljs-number">16</span>* <span class="hljs-number">1024</span> * <span class="hljs-number">1024</span>;<br>    <span class="hljs-keyword">private</span> String hosts;<br>    <span class="hljs-keyword">private</span> String group;<br>    <span class="hljs-meta">@Bean(name = KafkaStreamsDefaultConfiguration.DEFAULT_STREAMS_CONFIG_BEAN_NAME)</span><br>    <span class="hljs-keyword">public</span> KafkaStreamsConfiguration <span class="hljs-title function_">defaultKafkaStreamsConfig</span><span class="hljs-params">()</span> &#123;<br>        Map&lt;String, Object&gt; props = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span>&lt;&gt;();<br>        props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, hosts);<br>        props.put(StreamsConfig.APPLICATION_ID_CONFIG, <span class="hljs-built_in">this</span>.getGroup()+<span class="hljs-string">&quot;_stream_aid&quot;</span>);<br>        props.put(StreamsConfig.CLIENT_ID_CONFIG, <span class="hljs-built_in">this</span>.getGroup()+<span class="hljs-string">&quot;_stream_cid&quot;</span>);<br>        props.put(StreamsConfig.RETRIES_CONFIG, <span class="hljs-number">10</span>);<br>        props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());<br>        props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">KafkaStreamsConfiguration</span>(props);<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure><ol start="3"><li>常量</li></ol><figure class="highlight java"><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 java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">KafkaConstants</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">BOOTSTRAP_SERVERS</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;localhost:9092&quot;</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">INPUT_TOPIC</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;streams-plaintext-input&quot;</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">OUTPUT_TOPIC</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;streams-wordcount-output&quot;</span>;<br>&#125;<br><br></code></pre></td></tr></table></figure><ol start="4"><li>创建 KStream</li></ol><figure class="highlight java"><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 java"><span class="hljs-meta">@Configuration</span><br><span class="hljs-meta">@Slf4j</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">KafkaStreamHelloListener</span> &#123;<br><br>    <span class="hljs-meta">@Bean</span><br>    <span class="hljs-keyword">public</span> KStream&lt;String,String&gt; <span class="hljs-title function_">kStream</span><span class="hljs-params">(StreamsBuilder streamsBuilder)</span>&#123;<br>        <span class="hljs-comment">//创建kstream对象，同时指定从那个topic中接收消息</span><br>        KStream&lt;String, String&gt; stream = streamsBuilder.stream(KafkaConstants.INPUT_TOPIC);<br>        stream.flatMapValues(<span class="hljs-keyword">new</span> <span class="hljs-title class_">ValueMapper</span>&lt;String, Iterable&lt;String&gt;&gt;() &#123;<br>            <span class="hljs-meta">@Override</span><br>            <span class="hljs-keyword">public</span> Iterable&lt;String&gt; <span class="hljs-title function_">apply</span><span class="hljs-params">(String value)</span> &#123;<br>                <span class="hljs-keyword">return</span> Arrays.asList(value.split(<span class="hljs-string">&quot; &quot;</span>));<br>            &#125;<br>        &#125;)<br>                <span class="hljs-comment">//根据value进行聚合分组</span><br>                .groupBy((key,value)-&gt;value)<br>                <span class="hljs-comment">//聚合计算时间间隔</span><br>                .windowedBy(TimeWindows.of(Duration.ofSeconds(<span class="hljs-number">1</span>)))<br>                <span class="hljs-comment">//求单词的个数</span><br>                .count()<br>                .toStream()<br>                <span class="hljs-comment">//处理后的结果转换为string字符串</span><br>                .map((key,value)-&gt;&#123;<br>                    System.out.println(<span class="hljs-string">&quot;key:&quot;</span>+key+<span class="hljs-string">&quot;,value:&quot;</span>+value);<br>                    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">KeyValue</span>&lt;&gt;(key.key().toString(),value.toString());<br>                &#125;)<br>                <span class="hljs-comment">//发送消息</span><br>                .to(KafkaConstants.OUTPUT_TOPIC);<br>        <span class="hljs-keyword">return</span> stream;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><h3 id="3-2-自定义配置构建-Kafka-Streams">3.2 自定义配置构建 Kafka Streams</h3><p>将Demo中 <code>KafkaStreamConfig.java</code> 和 <code>KafkaStreamHelloListener.java</code> 注释掉，</p><p>在 SpringBootTest 添加下面代码：</p><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@SpringBootTest</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">KafkaStreamDemoApplicationTests</span> &#123;<br><br>    <span class="hljs-meta">@Value(&quot;$&#123;kafka.hosts&#125;&quot;)</span><br>    <span class="hljs-keyword">private</span> String hosts;<br>    <span class="hljs-meta">@Value(&quot;$&#123;kafka.group&#125;&quot;)</span><br>    <span class="hljs-keyword">private</span> String group;<br><br>    <span class="hljs-comment">// 手动构建KStream</span><br>    <span class="hljs-meta">@Test</span><br>    <span class="hljs-keyword">void</span> <span class="hljs-title function_">testCreateKStream</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> InterruptedException &#123;<br>        <span class="hljs-type">Properties</span> <span class="hljs-variable">props</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Properties</span>();<br>        props.put(StreamsConfig.APPLICATION_ID_CONFIG, <span class="hljs-built_in">this</span>.group + <span class="hljs-string">&quot;_stream_aid&quot;</span>);<br>        props.put(StreamsConfig.CLIENT_ID_CONFIG, <span class="hljs-built_in">this</span>.group + <span class="hljs-string">&quot;_stream_cid&quot;</span>);<br>        props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, hosts);<br>        props.put(StreamsConfig.RETRIES_CONFIG, <span class="hljs-number">10</span>);<br>        props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());<br>        props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());<br>        props.put(StreamsConfig.NUM_STREAM_THREADS_CONFIG, <span class="hljs-number">2</span>); <span class="hljs-comment">// 多线程处理</span><br><br>        <span class="hljs-comment">// 创建StreamsBuilder对象</span><br>        <span class="hljs-type">StreamsBuilder</span> <span class="hljs-variable">streamsBuilder</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">StreamsBuilder</span>();<br>        KStream&lt;String, String&gt; stream = streamsBuilder.stream(KafkaConstants.INPUT_TOPIC);<br>        <span class="hljs-comment">// 创建KStream对象</span><br>        stream.flatMapValues((ValueMapper&lt;String, Iterable&lt;String&gt;&gt;) value -&gt; Arrays.asList(value.split(<span class="hljs-string">&quot; &quot;</span>)))<br>                <span class="hljs-comment">//根据value进行聚合分组</span><br>                .groupBy((key,value)-&gt;value)<br>                <span class="hljs-comment">//聚合计算时间间隔</span><br>                .windowedBy(TimeWindows.of(Duration.ofSeconds(<span class="hljs-number">1</span>)))<br>                <span class="hljs-comment">//求单词的个数</span><br>                .count()<br>                .toStream()<br>                <span class="hljs-comment">//处理后的结果转换为string字符串</span><br>                .map((key,value)-&gt;&#123;<br>                    System.out.println(<span class="hljs-string">&quot;key:&quot;</span>+key+<span class="hljs-string">&quot;,value:&quot;</span>+value);<br>                    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">KeyValue</span>&lt;&gt;(key.key().toString(),value.toString());<br>                &#125;)<br>                <span class="hljs-comment">//发送消息</span><br>                .to(KafkaConstants.OUTPUT_TOPIC);<br>        <span class="hljs-keyword">new</span> <span class="hljs-title class_">CountDownLatch</span>(<span class="hljs-number">1</span>).await();<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure><h3 id="3-3-测试">3.3 测试</h3><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ProducerQuickStart</span> &#123;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br><br>        <span class="hljs-comment">//1. kafka的配置信息</span><br>        <span class="hljs-type">Properties</span> <span class="hljs-variable">prop</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Properties</span>();<br>        <span class="hljs-comment">//kafka的链接信息</span><br>        prop.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, KafkaConstants.BOOTSTRAP_SERVERS);<br>        <span class="hljs-comment">//配置重试次数</span><br>        prop.put(ProducerConfig.RETRIES_CONFIG, <span class="hljs-number">5</span>);<br>        <span class="hljs-comment">//数据压缩</span><br>        prop.put(ProducerConfig.COMPRESSION_TYPE_CONFIG,<span class="hljs-string">&quot;lz4&quot;</span>);<br>        <span class="hljs-comment">//ack配置  消息确认机制   默认ack=1,即只要集群首领节点收到消息，生产者就会收到一个来自服务器的成功响应</span><br><span class="hljs-comment">//        prop.put(ProducerConfig.ACKS_CONFIG,&quot;all&quot;);</span><br><br><span class="hljs-comment">//        消息key的序列化器</span><br>        prop.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, <span class="hljs-string">&quot;org.apache.kafka.common.serialization.StringSerializer&quot;</span>);<br>        <span class="hljs-comment">//消息value的序列化器</span><br>        prop.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, <span class="hljs-string">&quot;org.apache.kafka.common.serialization.StringSerializer&quot;</span>);<br><br>        <span class="hljs-comment">//2. 生产者对象</span><br>        KafkaProducer&lt;String, String&gt; producer = <span class="hljs-keyword">new</span> <span class="hljs-title class_">KafkaProducer</span>&lt;String, String&gt;(prop);<br>        <span class="hljs-comment">//封装发送的消息</span><br>        ProducerRecord&lt;String, String&gt; producerRecord1 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ProducerRecord</span>&lt;String, String&gt;(KafkaConstants.INPUT_TOPIC, <span class="hljs-string">&quot;key_001&quot;</span>, <span class="hljs-string">&quot;hello kafka&quot;</span>);<br>        ProducerRecord&lt;String, String&gt; producerRecord2 = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ProducerRecord</span>&lt;String, String&gt;(KafkaConstants.INPUT_TOPIC, <span class="hljs-string">&quot;key_002&quot;</span>, <span class="hljs-string">&quot;hello world&quot;</span>);<br>        <span class="hljs-comment">//3. 发送消息</span><br>        producer.send(producerRecord1);<br>        producer.send(producerRecord2);<br><br>        <span class="hljs-comment">//4. 关闭消息通道  必须关闭，否则消息发不出去</span><br>        producer.close();<br><br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>执行上面main方法测试发送消息：</p><p><code>hello kafka</code></p><p><code>hello world</code></p><p>查看kafka 内消息：</p><p><img src="https://cdn.gumengyo.top/Qexo/24/5/ce4fa82f7d3b938ff813c331aed61fa4.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top/Qexo/24/5/b912bbefbc39efc7e260ed5e8b3c169e.png" srcset="/img/loading.gif" lazyload alt=""></p><p>可以看到已经正确统计单词结果，输出到<code>topic</code> 为 <code>streams-wordcount-output</code> 中</p><h2 id="参考">参考</h2><ul><li><a href="https://blog.csdn.net/zsx1713366249/article/details/132522600">https://blog.csdn.net/zsx1713366249/article/details/132522600</a></li><li><a href="https://kafka.apache.org/37/documentation/streams/quickstart">https://kafka.apache.org/37/documentation/streams/quickstart</a></li><li><a href="https://blog.csdn.net/cold___play/article/details/132351928">https://blog.csdn.net/cold___play/article/details/132351928</a></li></ul>]]></content>
    
    
    <summary type="html">Kafka Stream 基本使用  Apache Kafka Streams 是一款强大的实时流处理库，为构建实时数据处理应用提供了灵活且高性能的解决方案。 Kafka Streams 是 Apache Kafka 生态系统中的一部分，它不仅简化了流处理应用的构建，还提供了强大的功能，如事件时间处理、状态管理、交互式查询等。其核心理念是将流处理与事件日志结合，使应用程序能够实时处理数据流。  1. 前言 由于公司需开发数据清洗服务，而且需要实时性高的数据处理，结合线上数据是输出到kafka，故采用 Kafka Streams 来作为数据清洗服务开发，本编结合一个demo，讲述 Kafka S...</summary>
    
    
    
    <category term="Java" scheme="https://blog.jishuqin.cn/categories/Java/"/>
    
    
    <category term="Kafka Streams" scheme="https://blog.jishuqin.cn/tags/Kafka-Streams/"/>
    
    <category term="Kafka" scheme="https://blog.jishuqin.cn/tags/Kafka/"/>
    
  </entry>
  
  <entry>
    <title>Qexo 博客管理后台搭建</title>
    <link href="https://blog.jishuqin.cn/posts/f054a2aa/"/>
    <id>https://blog.jishuqin.cn/posts/f054a2aa/</id>
    <published>2024-01-20T09:03:00.000Z</published>
    <updated>2025-02-11T03:23:50.662Z</updated>
    
    <content type="html"><![CDATA[<h1>Qexo 博客管理后台搭建</h1><h2 id="1-前言">1. 前言</h2><p><strong>Qexo</strong> 是一个快速、强大、美观的在线 <strong>静态博客编辑器</strong>。使用 GPL3.0 <strong>开源</strong>协议。支持包括且不限于在 <strong>Vercel</strong> 等平台部署, 为您的静态博客添加<strong>动态</strong>的元素。使用<strong>Qexo</strong>可以管理Hexo友链、文章管理、站点统计、发布说说等多种功能，这篇文章是用其中一种方式部署，采用Vercel（PostgreSQL/SupaBase）的方式进行部署，想了解更多功能介绍和部署方式可以查看<a href="https://www.oplog.cn/qexo/">官方文档</a>。</p><p><strong>Qexo</strong>优势：</p><ul><li>支持多种方式部署</li><li>在线Markdown编辑界面</li><li>多种形式消息推送</li><li>友情链接 前端申请, 一键接入</li><li>图片上传、访客统计、Hexo配置编辑</li><li>开源免费、项目长期维护</li></ul><p class="note note-warning">不过使用Qexo后台的前提是 Hexo 需要搭建Github Action自动化部署<sup id="fnref:1" class="footnote-ref"><a href="#fn:1" rel="footnote"><span class="hint--top hint--rounded" aria-label="[Qexo 官方文档](https://www.oplog.cn/qexo/start/build.html#vercel-%E9%83%A8%E7%BD%B2-postgresql-vercel)">[1]</span></a></sup>，这里就不做介绍了，看着篇文章实现即可：https://cloud.tencent.com/developer/article/2277577</p><p><strong>具体的执行流程如下：</strong></p><p><img src="https://cdn.gumengyo.top//blog/img/202401202234950.png" srcset="/img/loading.gif" lazyload alt="流程图"></p><h2 id="2-部署">2. 部署</h2><p>方式一：直接点击下面这个按钮一键部署到vercel</p><p><a href="https://vercel.com/new/clone?repository-url=https://github.com/am-abudu/Qexo" target="_blank" rel="noreferrer"><img src="https://vercel.com/button" srcset="/img/loading.gif" lazyload alt="部署到 Vercel"></a></p><p>方式二：首先将<strong>Qexo</strong>的GIthub仓库fork到自己Github中，仓库地址：<a href="https://github.com/Qexo/Qexo">https://github.com/Qexo/Qexo</a></p><p><img src="https://cdn.gumengyo.top//blog/img/202401202239800.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top//blog/img/202401202240837.png" srcset="/img/loading.gif" lazyload alt=""></p><p>然后到 vercel 选择项目引入</p><p><img src="https://cdn.gumengyo.top//blog/img/202401202245154.png" srcset="/img/loading.gif" lazyload alt=""></p><p class="note note-info">首次部署会报错, 请无视并进行接下来的步骤~</p><h3 id="申请-Vercel-数据库">申请 Vercel 数据库</h3><p><a href="https://supabase.com/">注册 SupaBase 账号</a> 创建免费 SupaBase 数据库, 区域一定要选择 <strong>N. Virginia</strong>在项目设置页面获取数据库连接信息, 密码即为你所设置的值<sup id="fnref:1" class="footnote-ref"><a href="#fn:1" rel="footnote"><span class="hint--top hint--rounded" aria-label="[Qexo 官方文档](https://www.oplog.cn/qexo/start/build.html#vercel-%E9%83%A8%E7%BD%B2-postgresql-vercel)">[1]</span></a></sup>。</p><ol><li>创建项目</li></ol><p><img src="https://cdn.gumengyo.top//blog/img/202401202333335.png" srcset="/img/loading.gif" lazyload alt=""></p><ol start="2"><li>设置项目名字、密码和选择区域</li></ol><p><img src="https://cdn.gumengyo.top//blog/img/202401202334500.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top//blog/img/202401202338573.png" srcset="/img/loading.gif" lazyload alt=""></p><p>设置 vercel 的环境变量，将你设置的密码和上面的 URL 分别填到 PG_PASS 和 PG_HOST 其他保持不变即可。</p><table><thead><tr><th>名称</th><th>意义</th><th>示例</th></tr></thead><tbody><tr><td>PG_HOST</td><td>PostgreSQL 数据库连接地址</td><td><a href="http://db.xxx.supabase.co">db.xxx.supabase.co</a></td></tr><tr><td>PG_PORT</td><td>PostgreSQL 数据库通信端口 默认应填写 5432</td><td>5432</td></tr><tr><td>PG_USER</td><td>PostgreSQL 数据库用户名</td><td>postgres</td></tr><tr><td>PG_DB</td><td>PostgreSQL 数据库名</td><td>postgres</td></tr><tr><td>PG_PASS</td><td>PostgreSQL 数据库密码</td><td>password</td></tr></tbody></table><p><img src="https://cdn.gumengyo.top//blog/img/202401202340634.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top//blog/img/202401202342871.png" srcset="/img/loading.gif" lazyload alt=""></p><p>3.找到 vercel 项目在 Deployments 点击 Redeploy 开始部署, 若没有 Error 信息即可，看到下面这个样子就是部署成功了。</p><p><img src="https://cdn.gumengyo.top//blog/img/202401202343342.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="本地-docker-compose-部署">本地 docker-compose 部署</h3><p>由于<strong>supabase</strong>数据库的认证方式更改了，所以没办法用vercel的方式，我将 <strong>Qexo</strong> 部署到docker并使用自己服务器上的 <code>Mysql</code>。</p><p>docker-compose.yml：</p><figure class="highlight yaml"><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></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">version:</span> <span class="hljs-string">&#x27;3.8&#x27;</span><br><br><span class="hljs-attr">services:</span><br>  <span class="hljs-attr">qexo:</span><br>    <span class="hljs-attr">image:</span> <span class="hljs-string">abudulin/qexo:latest</span><br>    <span class="hljs-attr">container_name:</span> <span class="hljs-string">qexo</span><br>    <span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span><br>    <span class="hljs-attr">ports:</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-string">&quot;8000:8000&quot;</span><br>    <span class="hljs-attr">environment:</span><br>      <span class="hljs-attr">WORKERS:</span> <span class="hljs-number">4</span><br>      <span class="hljs-attr">THREADS:</span> <span class="hljs-number">4</span><br>      <span class="hljs-attr">TIMEOUT:</span> <span class="hljs-number">600</span><br>      <span class="hljs-attr">MYSQL_HOST:</span>  <span class="hljs-comment"># mysql 地址</span><br>      <span class="hljs-attr">MYSQL_PORT:</span> <span class="hljs-number">3306</span><br>      <span class="hljs-attr">MYSQL_USER:</span>  <span class="hljs-comment"># mysql 用户名</span><br>      <span class="hljs-attr">MYSQL_PASSWORD:</span>  <span class="hljs-comment"># mysql密码</span><br>      <span class="hljs-attr">MYSQL_NAME:</span> <span class="hljs-string">qexo</span> <span class="hljs-comment"># 数据库名</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></pre></td><td class="code"><pre><code class="hljs bash">docker-compose up -d<br></code></pre></td></tr></table></figure><ul><li><code>docker-compose up -d</code> 会自动检测到镜像更新，并重新创建容器。</li><li><code>-d</code> 参数表示在后台运行容器。</li></ul><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">docker-compose pull<br></code></pre></td></tr></table></figure><p>这将尝试拉取 <code>abudulin/qexo:latest</code> 镜像的最新版本。</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">docker-compose up -d<br></code></pre></td></tr></table></figure><h2 id="3-配置">3.配置</h2><ol><li>点击域名跳转到页面，需要开魔法不然访问不了，或者绑定成自己的域名访问如下操作：</li></ol><ul><li>找到 vercel 项目 Settings -&gt; Domains 配置自己的域名</li><li>然后将自己的域名解析到vercel 这的配置成 <code>cname-china.vercel-dns.com</code></li></ul><p><img src="https://cdn.gumengyo.top//blog/img/202401202347767.png" srcset="/img/loading.gif" lazyload alt=""></p><ol start="2"><li>然后访问自己的域名到管理界面就行啦，初次访问要设置管理账户和密码。</li></ol><p><img src="https://cdn.gumengyo.top//blog/img/202401202354425.png" srcset="/img/loading.gif" lazyload alt=""></p><ol start="3"><li>博客配置</li></ol><ul><li>Github 密钥：于 <a href="https://github.com/settings/tokens">Github 设置</a> 生成的 Token (建议使用 Classical) 需要 Repo &amp; Workflow 下的权限 <em>不建议给出所有权限</em></li><li>Github 仓：库您 博客源码 <strong>自动化部署</strong>所在的仓库</li><li>项目分支：您 博客源码 自动化部署所在仓库的分支</li><li>博客路径：您 博客源码 自动化部署所在仓库的路径 若为根目录请留空</li></ul><p><img src="https://cdn.gumengyo.top//blog/img/202401202358582.png" srcset="/img/loading.gif" lazyload alt=""></p><ol start="4"><li>Vercel 配置</li></ol><ul><li>VERCEL_TOKEN：您的 Vercel 账户密钥 在 <a href="https://vercel.com/account/tokens">此处</a> 生成</li><li>PROJECT_ID：</li></ul><p><img src="https://cdn.gumengyo.top//blog/img/202401202359461.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top//blog/img/202401210000343.png" srcset="/img/loading.gif" lazyload alt=""></p><p>全部设置完毕成功后会提示如下页面，点击登录控制台</p><p><img src="https://cdn.gumengyo.top//blog/img/202401210002884.png" srcset="/img/loading.gif" lazyload alt=""></p><p>设置消息推送、友链管理、说说等配置就参考官方文档吧~</p><h2 id="4-效果展示">4.效果展示</h2><p><img src="https://cdn.gumengyo.top//blog/img/202401210005189.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top//blog/img/202401210011627.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top//blog/img/202401210011546.png" srcset="/img/loading.gif" lazyload alt=""></p><h2 id="参考">参考</h2><section class="footnotes"><div class="footnote-list"><ol><li><span id="fn:1" class="footnote-text"><span><a href="https://www.oplog.cn/qexo/start/build.html#vercel-%E9%83%A8%E7%BD%B2-postgresql-vercel">Qexo 官方文档</a><a href="#fnref:1" rev="footnote" class="footnote-backref"> ↩</a></span></span></li><li><span id="fn:2" class="footnote-text"><span><a href="https://cloud.tencent.com/developer/article/2277577">Fantasy的Hexo博客利用GitHub Action自动化部署</a><a href="#fnref:2" rev="footnote" class="footnote-backref"> ↩</a></span></span></li></ol></div></section>]]></content>
    
    
    <summary type="html">Qexo 博客管理后台搭建 1. 前言 Qexo 是一个快速、强大、美观的在线 静态博客编辑器。使用 GPL3.0 开源协议。支持包括且不限于在 Vercel 等平台部署, 为您的静态博客添加动态的元素。使用Qexo可以管理Hexo友链、文章管理、站点统计、发布说说等多种功能，这篇文章是用其中一种方式部署，采用Vercel（PostgreSQL/SupaBase）的方式进行部署，想了解更多功能介绍和部署方式可以查看官方文档。 Qexo优势：  支持多种方式部署 在线Markdown编辑界面 多种形式消息推送 友情链接 前端申请, 一键接入 图片上传、访客统计、Hexo配置编辑 开源免费、项目长...</summary>
    
    
    
    
    <category term="Hexo" scheme="https://blog.jishuqin.cn/tags/Hexo/"/>
    
    <category term="Vercel" scheme="https://blog.jishuqin.cn/tags/Vercel/"/>
    
  </entry>
  
  <entry>
    <title>MySQL-高级</title>
    <link href="https://blog.jishuqin.cn/posts/0e1f2a3b/"/>
    <id>https://blog.jishuqin.cn/posts/0e1f2a3b/</id>
    <published>2023-07-09T16:47:40.000Z</published>
    <updated>2025-09-03T08:59:30.029Z</updated>
    
    <content type="html"><![CDATA[<h1>MySQL-高级</h1><p class="note note-success">  此文是我学习MySQL时笔记，教程链接：<a href="https://www.bilibili.com/video/BV1Kr4y1i7ru" target="_blank">https://www.bilibili.com/video/BV1Kr4y1i7ru</a></p><h2 id="一、存储引擎">一、存储引擎</h2><h3 id="1-MySQL体系结构">1.MySQL体系结构</h3><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230630192648123.png" srcset="/img/loading.gif" lazyload alt=""></p><ul><li><p>连接层</p><p>最上层是一些客户端和链接服务，主要完成一些类似于连接处理、授权认证、及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。</p></li><li><p>服务层</p><p>第二层架构主要完成大多数的核心服务功能，如SQL接口，并完成缓存的查询，SQL的分析和优化，部分内置函数的执行。所有跨存储引擎的功能也在这一层实现，如过程、函数等。</p></li><li><p>引擎层</p></li></ul><p>存储引擎真正的负责了MySQL的存储和提取，服务器通过API和存储引擎进行通信。不同的存储引擎具有不同的功能，这样我们可以根据自己的需要，来选取合适的存储引擎。</p><ul><li>存储层</li></ul><p>主要是将数据存储在文件系统之上，并完成与存储引擎的交互。</p><h3 id="2-存储引擎简介">2.存储引擎简介</h3><p>存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的，而不是基于库的，所以存储引擎也可被称为表类型。</p><ol><li><p>在创建表时，指定存储引擎</p><figure class="highlight plaintext"><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 mysql">CREATE TABLE 表名&#123;<br>字段1 字段1类型 [COMMENT 字段1注释],<br>......<br>字段n 字段n类型 [COMMENT 字段n注释]<br>&#125;ENGINE=INNODB [COMMENT 表注释]；<br></code></pre></td></tr></table></figure></li><li><p>查看当前数据库支持的存储引擎</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">SHOW ENGINES;<br></code></pre></td></tr></table></figure></li></ol><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230630193726848.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="3-存储引擎特点">3.存储引擎特点</h3><h4 id="InnoDB">InnoDB</h4><ul><li><p>介绍：InnoDB是一种兼顾高可靠性和高性能的通用存储引擎，在MySQL 5.5之后，InnoDB 是默认的 MySQL 存储引擎。</p></li><li><p>特点：</p><ol><li>DML操作遵循ACID模型，支持<strong>事务</strong>；</li><li><strong>行级锁</strong>，提高并发访问性能：</li><li>支持<strong>外键</strong> FOREIGN KEY 约束，保证数据的完整性和正确性；</li></ol></li><li><p>文件</p><p>xxx.ibd：xxx代表的是表名，innoDB 引擎的每张表都会对应这样一个表空间文件，存储该表的表结构（frm、sdi）、数据和索引。<br>参数：innodb_file_per_table</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230630200019249.png" srcset="/img/loading.gif" lazyload alt=""></p></li></ul><h4 id="MyISAM">MyISAM</h4><ul><li><p>介绍：MyISAM是MySQL早期的默认存储引擎。</p></li><li><p>特点：</p><ol><li>不支持事务，不支持外键</li><li>支持表锁，不支持行锁</li><li>访问速度快</li></ol></li><li><p>文件：</p><p>xxx.sdi：存储表结构信息<br>xxx.MYD：存储数据<br>xxx.MYI：存储索引</p></li></ul><h4 id="Memory">Memory</h4><ul><li>介绍：Memory 引擎的表数据时存储在内存中的，由于受到硬件问题、或断电问题的影响，只能将这些表作为临时表或缓存使用。</li><li>特点：<ol><li>内存存放</li><li>hash 索引（默认）</li></ol></li><li>文件：xxx.sdi：存储表结构信息</li></ul><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230630200854814-16883049088341.png" srcset="/img/loading.gif" lazyload alt=""></p><p><strong>面试题：InnoDB与MyISAM的区别？</strong></p><p>InnoDB支持事务安全、行级锁和外键，MyISAM不支持。</p><h3 id="4-存储引擎选择">4.存储引擎选择</h3><p>在选择存储引擎时，应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统，还可以根据实际情况选择多种存储引擎进行组合。</p><ul><li><u>InnoDB</u>：是Mysql的默认存储引擎，支持事务、外键。如果应用<u>对事务的完整性有比较高的要求</u>，在并发条件下<u>要求数据的一致性</u>，数据操作除了插入和查询之外，还包含很多的更新、删除操作，那么InnoDB存储引擎是比较合适的选择。</li><li>MyISAM：如果应用是以<u>读操作和插入操作为主</u>，只有<u>很少的更新和删除操作</u>，并且对事务的完整性、并发性要求不是很高，那么选择这个存储引擎是非常合适的。</li><li>MEMORY：将所有数据保存在内存中，<u>访问速度快</u>，通常用于<u>临时表及缓存</u>。MEMORY的缺陷就是对表的大小有限制，太大的表无法缓存在内存中，而且无法保障数据的安全性。</li></ul><h2 id="二、索引-⭐">二、索引 ⭐</h2><h3 id="1-索引概述">1.索引概述</h3><ul><li><p>介绍：索引(index)是帮助 MySQL <u>高效获取数据</u>的<u>数据结构</u>（有序）。</p></li><li><p>优缺点：</p><table><thead><tr><th>优势</th><th style="text-align:left">劣势</th></tr></thead><tbody><tr><td>提高数据检索的效率，降低数据库的 IO 成本</td><td style="text-align:left">索引列也是要占用空间的。</td></tr><tr><td>通过索引列对数据进行排序，降低数据排序的成本，降低CPU的消耗。</td><td style="text-align:left">索引大大提高了查询效率，同时却也降低更新表的速度，如对表进行INSERT、UPDATE、DELETE时，效率降低。</td></tr></tbody></table></li></ul><h3 id="2-索引结构">2.索引结构</h3><p>MySQL的索引是在存储引擎层实现的，不同的存储引擎有不同的结构，主要包含以下几种：</p><table><thead><tr><th>索引结构</th><th>描述</th></tr></thead><tbody><tr><td><strong>B+Tree 索引</strong></td><td><strong>最常见的索引类型，大部分引擎都支持B+树索引</strong></td></tr><tr><td>Hash 索引</td><td>底层数据结构是用哈希表实现的，只有精确匹配索引列的查询才有效，不支持范围查询</td></tr><tr><td>R-tree（空间索引）</td><td>空间索引是 MyISAM 引擎的一个特殊索引类型，主要用于地理空间数据类型，通常使用较少</td></tr><tr><td>Full-text（全文索引）</td><td>是一种通过建立倒排索引，快速匹配文档的方式。类似于Lucene,Solr,ES</td></tr></tbody></table><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230702215652288.png" srcset="/img/loading.gif" lazyload alt=""></p><p><strong>我们平常所说的索引，如果没有特别指明，都是指B+树结构组织的索引。</strong></p><ul><li><p>B+Tree</p><p>MySQL索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上，增加一个指向相邻叶子节点的链表指针，就形成了带有顺序指针的B+Tree,提高区间访问的性能。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230702223006023.png" srcset="/img/loading.gif" lazyload alt=""></p></li><li><p>Hash</p><p>哈希索引就是采用一定的hash算法，将键值换算成新的hash值，映射到对应的槽位上，然后存储在hash表中。</p><p>如果两个（或多个）键值，映射到一个相同的槽位上，他们就产生了hash冲突（也称为hash碰撞)，可以通过链表来解决。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230702224041782.png" srcset="/img/loading.gif" lazyload alt=""></p><p>Hash索引特点：</p><ul><li>Hash 索引只能用于对等比较(=，in),不支持范围查询(between，&gt;，&lt;，…)</li><li>无法利用索引完成排操作</li><li>查询效率高，通常只需要一次检索就可以了，效率通常要高于 B+tree 索引</li></ul><p>存储引擎支持：在MySQL中，支持hash索引的是Memory引擎，而InnoDB中具有自适应hash中能，hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。</p></li></ul><p><strong>面试题：为什么InnoDB存储引擎选择使用 B+tree 索引结构？</strong></p><ul><li>相对于二叉树，层级更少，搜索效率高；</li><li>对于 B-tree，无论是叶子节点还是非叶子节点，都会保存数据，这样导致一页中存储的键值减少，指针跟着减少，要同样保存大量数据，只能增加树的高度，导致性能降低；</li><li>相对Hash索引，B+tree支持范围匹配及排序操作；</li></ul><h3 id="3-索引分类">3.索引分类</h3><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230702225311526.png" srcset="/img/loading.gif" lazyload alt=""></p><p>在InnoDB存储引擎中，根据索引的存储形式，又可以分为以下两种：</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230702225742717.png" srcset="/img/loading.gif" lazyload alt=""></p><p>聚集索引选取规则：</p><ul><li>如果存在主键，主键索引就是聚集索引。</li><li>如果不存在主键，将使用第一个唯一（UNIQUE）索引作为聚集索引。</li><li>如果表没有主键，或没有合适的唯一索引，则 InnoDB 会自动生成一个 rowid 作为隐藏的聚集索引。</li></ul><p><strong>思考：</strong></p><ol><li><p>以下 SQL 语句，哪个执行效率高？为什么？</p><figure class="highlight plaintext"><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 mysql">select * from user where id=10;<br><br>select * from user where name=&#x27;Arm&#x27;;<br><br>备注：id为主键，name字段创建的有索引;<br></code></pre></td></tr></table></figure><p>根据id查询比根据name查询效率高，根据name查询需要扫描两个索引效率低。</p></li><li><p>InnoDB主键索引的B+tree高度为多高呢？</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230702231721965.png" srcset="/img/loading.gif" lazyload alt=""></p></li></ol><h3 id="4-索引语法">4.索引语法</h3><ul><li><p>创建索引</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">CREATE [UNIQUE|FULLTEXT] INDEX index_name ON table_name (index_col_name,...);<br></code></pre></td></tr></table></figure></li><li><p>查看索引</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">SHOW INDEX FROM table_name;<br></code></pre></td></tr></table></figure></li><li><p>删除索引</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">DROP INDEX index_name ON table_name;<br></code></pre></td></tr></table></figure></li></ul><h3 id="5-SQL-性能分析">5.SQL 性能分析</h3><ul><li><p>SQL 执行频率</p><p>MySQL 客户端连接成功后，通过shoW[session|global] status命令可以提供服务器状态信息。通过如下指令，可以查看当前数据库的 INSERT、UPDATE、DELETE、SELECT 的访问频次：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">SHOW GLOBAL STATUS LIKE &#x27;Com_______&#x27;;<br></code></pre></td></tr></table></figure></li><li><p>慢查询日志</p><p>慢查询日志记录了所有执行时间超过指定参数(long_query_.time,单位：秒，默认10秒)的所有SQL语句的日志。<br>MySQL 的慢查询日志默认没有开启，需要在 MySQL 的配置文件（/etc/my.cnf）中配置如下信息：</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></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 开启MySQL慢日志查询开关</span><br>slow_query_log=1<br><span class="hljs-comment"># 设置慢日志的时间为2秒，SQL语句执行时间超过2秒，就会视为慢查询，记录慢查询日志</span><br>long_query_time=2<br></code></pre></td></tr></table></figure></li><li><p>profile 详情</p><p>执行一系列的业务SQL的操作，然后通过如下指令查看指令的执行耗时：</p><figure class="highlight plaintext"><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 mysql">#查看每一条SQL的耗时基本情况<br>show profiles;<br><br>#查看指定query id的SQL语句各个阶段的耗时情况<br>show profile for query query_id;<br><br>#查看指定query_id的SQL语句CPU的使用情况<br>show profile cpu for query query_id;<br></code></pre></td></tr></table></figure></li><li><p>explain执行计划</p><p>EXPLAIN 执行计划各字段含义：</p><ul><li><p>id</p><p>select查询的序列号，表示查询中执行select子句或者是操作表的顺序(id相同，执行顺序从上到下；id不同，值越大，越先执行)。</p></li><li><p>select_type</p><p>表示 SELECT 的类型，常见的取值有SIMPLE(简单表，即不使用表连接或者子查询)、PRIMARY(主查询，即外层的查询)、UNION(UNION中的第二个或者后面的查询语句)、SUBQUERY(SELECT/WHERE之后包含了子查询)等</p></li><li><p><strong>type</strong></p><p>表示连接类型，性能由好到差的连接类型为 NULL、system、const、eq_ref、ref、range、index、all。</p></li><li><p><strong>possible_key</strong></p><p>显示可能应用在这张表上的索引，一个或多个。</p></li><li><p><strong>key</strong></p><p>实际使用的索引，如果为NULL,则没有使用索引。</p></li><li><p><strong>key_len</strong></p><p>表示索引中使用的字节数，该值为索引字段最大可能长度，并非实际使用长度，在不损失精确性的前提下，长度越短越好。</p></li><li><p>rows</p><p>MySQL认为必须要执行查询的行数，在innodb引擎的表中，是一个估计值，可能并不总是准确的。</p></li><li><p>filtered</p><p>表示返回结果的行数占需读取行数的百分比，filtered 的值越大越好。</p></li></ul></li></ul><h3 id="6-索引使用">6.索引使用</h3><ul><li><p>最左前缀法则</p><p>如果索引了多列（联合索引），要遵守最左前缀法测。最左前缀法则指的是查询从索引的最左列开始，并且不跳过索引中的列。<br>如果跳跃某一列，<u>索引将部分失效（后面的字段索引失效）。</u></p></li><li><p>范围查询</p><p>联合索引中，出现范围查询(&gt;，&lt;)，<u>范围查询右侧的列索引失效</u></p></li><li><p>索引列运算</p><p>不要在索引列上进行运算操作，索引将失效。</p></li><li><p>字符串</p><p>字符串类型字段使用时，不加引号，索引将失效。</p></li><li><p>模糊查询</p><p>如果仅仅是尾部模糊匹配，索引不会失效。如果是头部模糊匹配，索引失效。</p></li><li><p>or连接的条件</p><p>用or分割开的条件，如果or前的条件中的列有索引，而后面的列中没有索引，那么涉及的索引都不会被用到。</p></li><li><p>数据分布影响</p><p>如果MySQL评估使用索引比全表更慢，则不使用索引。</p></li><li><p>SQL 提示</p><p>SQL提示，是优化数据库的一个重要手段，简单来说，就是在SQL语句中加入一些人为的提示来达到优化操作的目的。</p><p>use index:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">explain select*from tb_user use index(idx_user_pro)where profession=&#x27;软件工程&#x27;；<br></code></pre></td></tr></table></figure><p>ignore index:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">explain select*from tb_user ignore index(idx_user_pro)where profession=&#x27;软件工程&#x27;；<br></code></pre></td></tr></table></figure><p>force index:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">explain select*from tb_user force index(idx_user_pro)where profession=&#x27;软件工程&#x27;；<br></code></pre></td></tr></table></figure></li><li><p>覆盖索引</p><p>尽量使用覆盖索引（查询使用了索引，并且需要返回的列，在该索引中已经全部能够找到），减少select*。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230704235902137.png" srcset="/img/loading.gif" lazyload alt=""></p></li><li><p>前缀索引</p></li></ul><p>当字段类型为字符串（varchar,text等）时，有时候需要索引很长的字符串，这会让索引变得很大，查询时，浪费大量的磁盘IO,影响查询效率。此时可以只将字符串的一部分前缀，建立索引，这样可以大大节约索引空间，从而提高索引效率。</p><p>语法：</p>  <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">creae index idx_xxxx on table_name(column(n));<br></code></pre></td></tr></table></figure><p>前缀长度：</p><p>可以根据索引的选择性来决定，而选择性是指不重复的索引值（基数）和数据表的记录总数的比值，索引选择性越高则查询效率越高唯一索引的选择性是1，这是最好的索引选择性，性能也是最好的。</p>  <figure class="highlight plaintext"><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 mysql">select count(distinct email)/count(*) from tb_user;<br>select count(distinct substring(email,1,5))/count(*) from tb_user; <br></code></pre></td></tr></table></figure><ul><li><p>单列索引与联合索引</p><p>单列索引：即一个索引只包含单个列。</p><p>联合索引：即一个索引包含了多个列。</p><p>在业务场景中，如果存在多个查询条件，考虑针对于查询字段建立索引时，建议建立联合索引，而非单列索引。</p></li></ul><h3 id="7-索引设计原则">7.索引设计原则</h3><ol><li>针对于数据量较大，且查询比较频繁的表建索引。</li><li>针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。</li><li>尽量选择区分度高的列作为索引，尽量建立<u>唯一索引</u>，区分度越高，使用索引的效率越高。</li><li>如果是字符串类型的字段，字段的长度较长，可以针对于字段的特点，建立<u>前缀索引</u>。</li><li>尽量使用联合索引，减少单列索引，查询时，联合索引很多时候可以<u>覆盖索引</u>，节省存储空间，避免回表，提高查询效率。</li><li>要控制索引的数量，索引并不是多多益善，索引越多，维护索引结构的代价也就越大，会影响增删改的效率。</li><li>如果索引列不能存储NULL值，请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时，它可以更好地确定哪个索引最有效地用于查询。</li></ol><h2 id="三、SQL优化">三、SQL优化</h2><h3 id="1-插入数据">1.插入数据</h3><ul><li><p>insert 优化</p><ol><li><p>批量插入</p></li><li><p>手动提交事务</p></li><li><p>主键顺序插入</p></li></ol></li><li><p>大批量插入数据</p><p>如果一次性需要插入大批量数据，使用insert语句插入性能较低，此时可以使用MySQL数据库提供的load指令进行插入。操作如下：</p><figure class="highlight plaintext"><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 mysql">#客户端连接服务端时，加上参数 --local-infile<br>mysql --local-infile -u root -p<br>#设置全局参数local_infile为1，开启从本地加载文件导入数据的开关<br>set global local_infile=1;<br>#执行load指令将准备好的数据，加载到表结构中<br>load data local infile &#x27;/root/sql1.log&#x27; into table `tb_user` fields terminated by &#x27;,&#x27; lines terminated by &#x27;\n&#x27;;<br></code></pre></td></tr></table></figure></li></ul><h3 id="2-主键优化">2.主键优化</h3><ul><li><p>数据组织方式</p><p>在InnoDB存储引擎中，表数据都是根据主键顺序组织存放的，这种存储方式的表称为<strong>索引组织表</strong>(index organized table <strong>IOT</strong>)。</p></li><li><p>页分裂</p><p>页可以为空，也可以填充一半，也可以填充100%。每个页包含了2-N行数据（如果一行数据多大，会行溢出），根据主键排列。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230705150818074.png" srcset="/img/loading.gif" lazyload alt="主键顺序插入"></p><p>页分裂：</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230705151047951.png" srcset="/img/loading.gif" lazyload alt="主键乱序插入"></p><p>页合并：</p><p>当删除一行记录时，实际上记录并没有被物理删除，只是记录被标记(flaged)为删除并且它的空间变得允许被其他记录声明使用。</p><p>当页中删除的记录达到MERGE THRESHOLD(默认为页的50%)，InnoDB会开始寻找最靠近的页（前或后）看看是否可以将两个页合并以优化空间使用。</p><p>合并前：</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230705152251245.png" srcset="/img/loading.gif" lazyload alt="合并前"></p><p>合并后：</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230705152335931.png" srcset="/img/loading.gif" lazyload alt="合并后"></p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230705152408686.png" srcset="/img/loading.gif" lazyload alt=""></p></li><li><p>主键设计原则</p><ol><li>满足业务需求的情况下，尽量降低主键的长度。</li><li>插入数据时，尽量选择顺序插入，选择使用AUTO INCREMENT自增主键。</li><li>尽量不要使用UUD做主键或者是其他自然主键，如身你证号。</li><li>业务操作时，避免对主键的修改。</li></ol></li></ul><h3 id="3-order-by优化">3.order by优化</h3><ol><li>Using filesort：通过表的索引或全表扫描，读取满足条件的数据行，然后在排序缓冲区sort buffer中完成排序操作，所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。</li><li>Using index：通过有序索引顺序扫描直接返回有序数据，这种情况即为 using index，不需要额外排序，操作效率高。</li></ol><p>总结:</p><ul><li>根据排序字段建立合适的索引，多字段排序时，也遵循最左前缀法则。</li><li>尽量使用覆盖索引。</li><li>多字段排序，一个升序一个降序，此时需要注意联合索引在创建时的规则(ASC/DESC)。</li><li>如果不可避免的出现 filesort,大数据量排序时，可以适当增大排序缓冲区大小sort buffer size(默认256k)。</li></ul><h3 id="4-group-by优化">4.group by优化</h3><figure class="highlight plaintext"><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></pre></td><td class="code"><pre><code class="hljs mysql">#删除掉目前的联合索引idx_user_pro_age_sta<br>drop index idx_user_pro_age_sta on tb_user;<br>#执行分组操作，根据orofession字段分组<br>explain select profession,count(*) from tb_user group by profession;<br>#创建索引<br>Create index idx_user_pro_age_sta on tb_user(profession,age,status);<br>#执行分组操作，根据profession字段分组<br>explain select profession,count(*) from tb_user group by profession;<br>#执行分组操作，根据profession字段分组<br>explain select profession,count(*) from tb_user group by profession,age;<br></code></pre></td></tr></table></figure><p>总结:</p><ul><li>在分组操作时，可以通过索引来提高效率</li><li>分组操作时，索引的使用也是满足最左前缀法则的。</li></ul><h3 id="5-limit优化">5.limit优化</h3><p>一个常见又非常头疼的问题就是limit2000000,10,此时需要MySQL排序前2000010记录，仅仅返回2000000-2000010的记录，其他记录丢弃，查询排序的代价非常大。</p><p>优化思路：一般分页查询时，通过创建覆盖索引能够比较好地提高性能，可以通过覆盖索引加子查询形式进行优化。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">explain select * from tb_sku t,(select id from tb_sku order by id limit 2000000,10) a where t.id = a.id;<br></code></pre></td></tr></table></figure><h3 id="6-count优化">6.count优化</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">explain select count(*) from tb_user;<br></code></pre></td></tr></table></figure><ul><li>MyISAM 引擎把一个表的总行数存在了磁盘上，因此执行count(*)的时候会直接返回这个数，效率很高；</li><li>InnoDB 引擎就麻烦了，它执行count(*)的时候，需要把数据一行一行地从引擎里面读出来，然后累积计数。</li></ul><p>优化思路：自己计数。</p><ul><li><p>count 的几种用法</p><ol><li><p>count(主键)：InnoDB 引擎会遍历整张表，把每一行的主键  id 值都取出来，返回给服务层。服务层拿到主键后，直接按行进行累加（主键不可能为null)。</p></li><li><p>count(字段)：</p><p>没有 not null 约束：InnoDB 引擎会遍历整张表把每一行的字段值都取出来，返回给服务层，服务层判断是否为 null，不为 null，计数累加。<br>有not null 约束：InnoDB 引擎会遍历整张表把每一行的字段值都取出来，返回给服务层，直接按行进行累加。</p></li><li><p>count(1)：InnoDB 引擎遍历整张表，但不取值。服务层对于返回的每一行，放一个数字“1”进去，直接按行进行累加。</p></li><li><p>count(*)：InnoDB 引擎并不会把全部字段取出来，而是专门做了优化，不取值，服务层直接按行进行累加。</p></li></ol><p>按照效率排序：count(字段) &lt; count(主键) &lt; count(1) ≈ <code>count(*)</code>，所以尽量使用<code>count(*)</code>。</p></li></ul><h3 id="7-update优化">7.update优化</h3><figure class="highlight plaintext"><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 mysql">update student set no=&#x27;2000100100&#x27; where id =1;<br><br>update student set no=&#x27;2000100105&#x27; where name=&#x27;韦一笑&#x27;；<br></code></pre></td></tr></table></figure><p>InnoDB 的行锁是针对索引加的锁，不是针对记录加的锁，并且该索引不能失效，否则会从行锁升级为表锁。</p><h2 id="四、视图-存储过程-触发器">四、视图/存储过程/触发器</h2><h3 id="1-视图">1.视图</h3><ul><li><p>介绍</p><p>视图(Viw)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在，行和列数据来自定义视图的查询中使用的表，并且是在使用视图时动态生成的。</p></li><li><p>创建</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">CREATE [OR REPLACE] VIEW 视图名称(列名列表)] AS SELECT语句 [WITH[CASCADED | LOCAL] CHECK OPTION&#125;]<br></code></pre></td></tr></table></figure></li><li><p>查询</p><figure class="highlight plaintext"><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 mysql">-- 查看创建视图语句<br>SHOW CREATE VIEW 视图名称;<br><br>-- 查看视图数据<br>SELECT * FROM 视图名称......;<br></code></pre></td></tr></table></figure></li><li><p>修改</p><figure class="highlight plaintext"><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 mysql">-- 方式1<br>CREATE [OR REPLACE] VIEW 视图名称(列名列表)] AS SELECT语句 [WITH[CASCADED | LOCAL]CHECK OPTION]<br>-- 方式2<br>ALTER VIEW 视图名称[(列名列表)] AS SELECT语句 [WITH [CASCADED | LOCAL] CHECK OPTION]<br></code></pre></td></tr></table></figure></li><li><p>删除</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">DROP VIEW [IF EXISTS] 视图名称 [,视图名称] ...<br></code></pre></td></tr></table></figure></li><li><p>视图的检查选项</p><p>当使用 WITH CHECK OPTION子句创建视图时，MySQL会通过视图检查正在更改的每个行，例如插入，更新，删除，以使其符合视图的定义。MySQL 允许基于另一个视图创建视图，它还会检查依赖视图中的规则以保持一致性。为了确定检查的范围，mysql 提供了两个选项：CASCADED 和 LOCAL,默认值为 CASCADED。</p></li><li><p>视图的更新</p><p>要使视图可更新，视图中的行与基础表中的行之间必须存在一对一的关系。如果视图包含以下任何一项，则该视图不可更新：</p><ol><li>聚合函数或窗口函数（SUM()、MIN()、MAX()、COUNT()等）</li><li>DISTINCT</li><li>GROUP BY</li><li>HAVING</li><li>UNION 或者 UNION ALL</li></ol></li><li><p>作用</p><ol><li><p>简单</p><p>视图不仅可以简化用户对数据的理解，也可以简化他们的操作。那些被经常使用的查询可以被定义为视图，从而使得用户不必为以后的每次指定全部的条件。</p></li><li><p>安全</p><p>数据库可以授权，但不能授权到数据库特定行和特定的列上。通过视图用户只能查询和修改他们所能见到的数据</p></li><li><p>数据独立<br>视图可帮助用户屏蔽真实表结构变化带来的影响。</p></li></ol></li></ul><h3 id="2-存储过程">2.存储过程</h3><ul><li><p>介绍</p><p>存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合，调用存储过程可以简化应用开发人员的很多工作，减少数据在数据库和应用服务器之间的传输，对于提高数据处理的效率是有好处的。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230707092338699.png" srcset="/img/loading.gif" lazyload alt=""></p></li><li><p>特点</p><ol><li><p>封装，复用</p></li><li><p>可以接收参数，也可以返回数据</p></li><li><p>减少网络交互，效率提升</p></li></ol></li><li><p>创建</p><figure class="highlight plaintext"><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 mysql">CREATE PROCEDURE 存储过程名称([参数列表])<br>BEGIN<br>--SQL语句<br>END;<br></code></pre></td></tr></table></figure></li><li><p>调用</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">CALL 名称([参数]);<br></code></pre></td></tr></table></figure></li><li><p>查看</p><figure class="highlight plaintext"><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 mysql">-- 查询指定数据库的存储过程及状态信息<br>SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA=&#x27;xxx&#x27;;<br>-- 查询某个存储过程的定义<br>SHOW CREATE PROCEDURE 存储过程名称；<br></code></pre></td></tr></table></figure></li><li><p>删除</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">DROP PROCEDURE [IF EXISTS] 存储过程名称;<br></code></pre></td></tr></table></figure><p>注意：在命令行中，执行创建存储过程的SQL时，需要通过关键字delimiter指定SQL语句的结束符。</p></li><li><p>变量</p><ol><li><p>系统变量：MySQL服务器提供，不是用户定义的，属于服务器层面。分为全局变量(<strong>GLOBAL</strong>)、会话变量(<strong>SESSION</strong>)。</p><p>查看系统变量</p><figure class="highlight plaintext"><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 mysql">SHOW [SESSION|GLOBAL] VARIABLES; -- 查看所有系统变量<br>SHOW [SESSION|GLOBAL] VARIABLES LIKE &#x27;......&#x27;; -- 可以通过LIKE模糊匹配方式查找变量<br>SELECT @@[SESSION|GLOBAL] 系统变量名; -- 查看指定变量的值<br></code></pre></td></tr></table></figure><p>设置系统变量</p><figure class="highlight plaintext"><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 mysql">SET [SESSION|GLOBAL] 系统变量名=值;<br>SET @@[SESSION|GLOBAL] 系统变量名=值;<br></code></pre></td></tr></table></figure><p>注意：</p><p>​如果没有指定SESSION/GLOBAL,默认是SESSION,会话变量。<br>​mysql服务重新启动之后，所设置的全局参数会失效，要想不失效，可以在/etc/my.cnf由配置。</p></li><li><p>用户自定义变量：用户根据需要自己定义的变量，用户变量不用提前声明，在用的时候直接用“@变量名”使用就可以。其作用域为当前连接。</p><p>赋值：</p><figure class="highlight plaintext"><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 mysql">SET @var_name = expr [,@var_name expr]...;<br>SET @var_name := expr [,@var_name :=expr]...;<br><br>SELECT @var_name:=expr [,@var_name :=expr]...;<br>SELECT 字段名 INTO @var_name FROM 表名；<br></code></pre></td></tr></table></figure><p>使用：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">SELECT @var_name;<br></code></pre></td></tr></table></figure><p>注意：用户定义的变量无需对其进行声明或初始化，只不过获取到的值为NULL。</p></li><li><p>局部变量：根据需要定义的在局部生效的变量，访问之前，需要DECLARE声明。可用作存储过程内的局部变量和输入参数，局部变量的范围是在其内声明的BEGN … END块。</p><p>声明：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">DECLARE 变量名 变量类型[DEFAULT ...];<br></code></pre></td></tr></table></figure><p>变量类型就是数据库字段类型：INT、BIGINT、CHAR、VARCHAR、DATE、TIME等。</p><p>赋值：</p><figure class="highlight plaintext"><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 mysql">SET 变量名=值；<br>SET 变量名:=值;<br>SELECT 字段名 INTO 变量名 FROM 表名 ...;<br></code></pre></td></tr></table></figure></li></ol></li><li><p>if</p><p>语法：</p><figure class="highlight plaintext"><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 mysql">IF 条件1 THEN<br>...<br>ELSEIF 条件2 THEN-- 可选<br>...<br>ELSE-- 可选<br>...<br>END IF;<br></code></pre></td></tr></table></figure></li><li><p>参数</p><table><thead><tr><th style="text-align:center">类型</th><th style="text-align:left">含义</th><th>备注</th></tr></thead><tbody><tr><td style="text-align:center">IN</td><td style="text-align:left">该类参数作为输入，也就是需要调用时传入值</td><td>默认</td></tr><tr><td style="text-align:center">OUT</td><td style="text-align:left">该类参数作为输出，也就是该参数可以作为返回值</td><td></td></tr><tr><td style="text-align:center">INOUT</td><td style="text-align:left">既可以作为输入参数，也可以作为输出参数</td><td></td></tr></tbody></table><p>用法：</p><figure class="highlight plaintext"><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 mysql">CREATE PROCEDURE 存储过程名称([IN/OUT/INOUT 参数名 参数类型])<br>BEGIN<br>-- SQL语句<br>END;<br></code></pre></td></tr></table></figure></li><li><p>case</p><p>语法一：</p><figure class="highlight plaintext"><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 mysql">CASE case_value<br>WHEN when_value1 THEN statement_list1<br>[WHEN when_value2 THEN statement_list2]...<br>[ELSE statement_list]<br>END CASE;<br></code></pre></td></tr></table></figure><p>语法二：</p><figure class="highlight plaintext"><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 mysql">CASE<br>WHEN search_condition1 THEN statement_list1<br>[WHEN search_condition2 THEN statement_list2]...<br>[ELSE statement_list]<br>END CASE;<br></code></pre></td></tr></table></figure></li><li><p>while</p><p>whil循环是有条件的循环控制语句。满足条件后，再执行循环体中的SQL语句。具体语法为：</p><figure class="highlight plaintext"><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 mysql"># 先判断条件，如果条件为true，则执行逻辑，否则，不执行逻辑<br>WHILE 条件 DO<br>SQL逻辑...<br>END WHILE;<br></code></pre></td></tr></table></figure></li><li><p>repeat</p><p>repeat 是有条件的循环控制语句，当满足条件的时候退出循环。</p><p>具体语法为：</p><figure class="highlight plaintext"><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 mysql">#先执行一次逻辑，然后判定逻辑是否满足，如果满足，则退出。如果不满足，则继续下一次循环<br>REPEAT<br>SQL 逻辑...<br>UNTIL 条件<br>END REPEAT;<br></code></pre></td></tr></table></figure></li><li><p>loop</p><p>LOOP实现简单的循环，如果不在SQL逻辑中增加退出循环的条件，可以用其来实现简单的死循环。LOOP可以配合一下两个语句使用：</p><ul><li>LEAVE：配合循环使用，退出循环。</li><li>ITERATE：必须用在循环中，作用是跳过当前循环剩下的语句，直接进入下一次循环。</li></ul><figure class="highlight plaintext"><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 mysql">[begin_label:] LOOP<br>SQL 逻辑...<br>END LOOP [end_label];<br><br>LEAVE label; -- 退出指定标记的循环体<br>ITERATE label; -- 直接进入下一次循环<br></code></pre></td></tr></table></figure></li><li><p>游标</p><p><strong>游标（CURSOR）</strong> 是用来存储查询结果集的数据类型，在存储过程和函数中可以使用游标对结果集进行循环的处理。游标的使用包括游标的声明、OPEN、FETCH 和 CLOSE，其语法分别如下。</p><p>声明游标：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">DECLARE 游标名称 CURSOR FOR 查询语句；<br></code></pre></td></tr></table></figure><p>打开游标:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">OPEN 游标名称;<br></code></pre></td></tr></table></figure><p>获取游标记录：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">FETCH 游标名称 INTO 变量[,变量];<br></code></pre></td></tr></table></figure><p>关闭游标：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">CLOSE 游标名称;<br></code></pre></td></tr></table></figure></li><li><p>条件处理程序</p><p><strong>条件处理程序（Handler）</strong> 可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤。</p><p>具体语法为：</p><figure class="highlight plaintext"><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 mysql">DECLARE handler_action HANDLER FOR condition_value [,condition_value]... statement;<br><br>handler_action<br>CONTINUE:继续执行当前程序<br>EXIT:终止执行当前程序<br><br>condition_value<br>SQLSTATE sqlstate_value:状态码，如 02000<br>SQLWARNING:所有以01开头的SQLSTATE代码的简写<br>NOT FOUND:所有以02开头的SQLSTATE代码的简写<br>SQLEXCEPTION:所有没有被SQLWARNING 或 NOT FOUND捕获的SQLSTATE代码的简写<br></code></pre></td></tr></table></figure></li></ul><h3 id="3-存储函数">3.存储函数</h3><p>存储函数是有返回值的存储过程，存储函数的参数只能是 IN 类型的。</p><p>具体语法如下：</p><figure class="highlight plaintext"><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 mysql">CREATE FUNCTION 存储函数名称([参数列表])<br>RETURNS type [characteristic ...]<br>BEGIN<br>-- SQL语句<br>RETURN ...;<br>END;<br></code></pre></td></tr></table></figure><p>characteristic 说明:</p><ul><li>DETERMINISTIC：相同的输入参数总是产生相同的结果。</li><li>NO SOL：不包含SQL语句。</li><li>READS SQL DATA：包含读取数据的语句，但不包含写入数据的语句。</li></ul><h3 id="4-触发器">4.触发器</h3><ul><li><p>介绍</p><p>触发器是与表有关的数据库对象，指在 insert/update/delete 之前或之后，触发并执行触发器中定义的SQL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性，日志记录，数据校验等操作。<br>使用别名OLD和NEW来引用触发器中发生变化的记录内容，这与其他的数据库是相似的。现在触发器还只支持行级触发，不支持语句级触发。</p><table><thead><tr><th>触发器类型</th><th>NEW 和 OLD</th></tr></thead><tbody><tr><td>INSERT 型触发器</td><td>NEW 表示将要或者已经新增的数据</td></tr><tr><td>UPDATE 型触发器</td><td>OLD 表示修改之前的数据，NEW 表示将要或已经修改后的数据</td></tr><tr><td>DELETE 型触发器</td><td>OLD 表示将要或者已经删除的数据</td></tr></tbody></table></li><li><p>语法</p><p>创建：</p><figure class="highlight plaintext"><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 mysql">CREATE TRIGGER trigger_name<br>BEFORE/AFTER INSERT/UPDATE/DELETE<br>ON tbl_name FOR EACH ROW -- 行级触发器<br>BEGIN<br>trigger_stmt;<br>END;<br></code></pre></td></tr></table></figure><p>查看：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">SHOW TRIGGERS;<br></code></pre></td></tr></table></figure><p>删除：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">DROP TRIGGER [schema_name] trigger_name;-- 如果没有指定 schema_name，默认为当前数据库。<br></code></pre></td></tr></table></figure></li></ul><h2 id="五、锁">五、锁</h2><h3 id="1-概述">1.概述</h3><ul><li><p>介绍</p><p>锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中，除传统的计算资源（CPU、RAM、I/O）的争用以外，数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题，锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说，锁对数据库而言显得尤其重要，也更加复杂。</p></li><li><p>分类</p><p>MySQL 中的锁，按照锁的粒度分，分为以下三类：</p><ol><li>全局锁：锁定数据库中的所有表。</li><li>表级锁：每次操作锁住整张表。</li><li>行级锁：每次操作锁住对应的行数据。</li></ol></li></ul><h3 id="2-全局锁">2.全局锁</h3><ul><li><p>介绍</p><p>全局锁就是对整个数据库实例加锁，加锁后整个实例就处于只读状态，后续的DML的写语句，DDL语句，已经更新操作的事务提交语句都将被阻塞。<br>其典型的使用场景是做全库的逻辑备份，对所有的表进行锁定，从而获取一致性视图，保证数据的完整性。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230707212941097.png" srcset="/img/loading.gif" lazyload alt=""></p></li><li><p>特点</p><p>数据库中加全局锁，是一个比较重的操作，存在以下问题：</p><ol><li>如果在主库上备份，那么在备份期间都不能执行更新，业务基本上就得停摆。</li><li>如果在从库上备份，那么在备份期间从库不能执行主库同步过来的二进制日志（binlog）,会导致主从延迟。</li></ol><p>在InnoDB引擎中，我们可以在备份时加上参数 --single-transaction 参数来完成不加锁的一致性数据备份。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">mysqldump --single-transaction -uroot -p123456 itcast&gt;itcast.sql<br></code></pre></td></tr></table></figure></li></ul><h3 id="3-表级锁">3.表级锁</h3><ul><li><p>介绍</p><p>表级锁，每次操作锁住整张表。锁定粒度大，发生锁冲突的概率最高，并发度最低。应用在MyISAM、InnoDB、BDB等存储引擎中。</p><p>主要分为以下三类：</p><ol><li>表锁</li><li>元数据锁（meta data lock，MDL）</li><li>意向锁</li></ol></li><li><p>表锁</p><p>对于表锁，分为两类：</p><ol><li>表共享读锁（read lock)</li><li>表独占写锁（write lock）</li></ol><p>语法：</p><ol><li>加锁：lock tables 表名…  read/write。</li><li>释放锁：unlock tables /客户端断开连接。</li></ol><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230707213906222.png" srcset="/img/loading.gif" lazyload alt="读锁"></p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230707214548831.png" srcset="/img/loading.gif" lazyload alt="写锁"></p><p>读锁不会阻塞其他客户端的读，但是会阻塞写。写锁既会阻塞其他客户端的读，又会阻塞其他客户端的写。</p></li><li><p>元数据锁（meta data lock，MDL）</p><p>MDL加锁过程是系统自动控制，无需显式使用，在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的数据一致性，在表上有活动事务的时候，不可以对元数据进行写入操作。为了避免DML与DDL冲突，保证读写的正确性。</p><p>在 MySQL5.5 中引入了MDL，当对一张表进行增删改查的时候，加MDL读锁（共享）；当对表结构进行变更操作的时候，加MDL写锁（排他）。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230707215127886.png" srcset="/img/loading.gif" lazyload alt=""></p><p>查看元数据锁：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks;<br></code></pre></td></tr></table></figure></li><li><p>意向锁</p><p>为了避免 DML 在执行时，加的行锁与表锁的冲突，在 InnoDB 中引入了意向锁，使得表锁不用检查每行数据是否加锁，使用意向锁来减少表锁的检查。</p><ol><li>意向共享锁（IS）：由语句 select … lock in share mode添加，与表锁共享锁(read)兼容，与表锁排它锁(write)互斥。</li><li>意向排他锁（IX）：由 insert、update、delete、select … for update 添加，与表锁共享锁(read)及排它锁(write)都互斥。意向锁之间不会互斥。</li></ol><p>可通过以下 SQL，查看意向锁及行锁的加锁情况：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs mysql">select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;<br></code></pre></td></tr></table></figure></li></ul><h3 id="4-行级锁">4.行级锁</h3><ul><li><p>介绍</p><p>行级锁，每次操作锁住对应的行数据。锁定粒度最小，发生锁冲突的概率最低，并发度最高。应用在 InnoDB 存储引擎中。</p><p>InnoDB 的数据是基于索引组织的，行锁是通过对索引上的索引项加锁来实现的，而不是对记录加的锁。对于行级锁，主要分为以下三类：</p><ol><li>行锁（Record Lock）：锁定单个行记录的锁，防止其他事务对此行进行 update 和 delete。在RC、RR 隔离级别下都支持。</li><li>间隙锁（Gap Lock）：锁定索引记忌间隙（不含该记录），确保索引记录间隙不变，防止其他事务在这个间隙进行insert，产生幻读。在RR隔离级别下都支持。</li><li>临键锁（Next-Key Lock）：行锁和间隙锁组合，同时锁住数据，并锁住数据前面的间隙Gap。在RR隔离级别下支持。</li></ol></li><li><p>行锁</p><p>InnoDB.实现了以下两种类型的行锁：<br>1.共享锁（S）：允许一个事务去读一行，阻止其他事务获得相同数据集的排它锁。<br>2.排他锁（X）：允许获取排他锁的事务更新数据，阻止其他事务获得相同数据集的共享锁和排他锁。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230707222631598.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230707222910637.png" srcset="/img/loading.gif" lazyload alt=""></p><p>默认情况下，InnoDB在REPEATABLE READ事务隔离级别运行，InnoDB使用next-key锁进行搜索和索引扫描，以防止幻读。</p><ol><li>针对唯一索引进行检索时，对已存在的记录进行等值匹配时，将会自动优化为行锁。</li><li>InnoDB的行锁是针对于索引加的锁，不通过索引条件检索数据，那么InnoDB将对表中的所有记录加锁，此时<strong>就会升级为表锁</strong>。</li></ol></li><li><p>间隙锁/临键锁</p><p>默认情况下，InnoDB 在 REPEATABLE READ事务隔离级别运行，InnoDB使用 next-key 锁进行搜索和索引扫描，以防止幻读。</p><ol><li>索引上的等值查询（唯一索引），给不存在的记录加锁时，优化为间隙锁。</li><li>索引上的等值查询（普通索引），向右遍历时最后一个值不满足查询需求时，next-key lock 退化为间隙锁。</li><li>索引上的范围查询（唯一索引），会访问到不满足条件的第一个值为止。</li></ol><p><strong>注意：间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存，一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。</strong></p></li></ul><h2 id="六、InnoDB引擎">六、InnoDB引擎</h2><h3 id="1-逻辑存储结构">1.逻辑存储结构</h3><ul><li>表表空间（ibd文件），一个 mysql 实例可以对应多个表空间，用于存储记录、索引等数据。</li><li>段，分为数据段（Leaf node segment）、索引段（Non-leaf node segment）、回滚段（Rollback segment），InnoDB<br>是索引组织表，数据段就是B+树的叶子节点，索引段即为B+树的非叶子节点。段用来管理多个Exten（区）。</li><li>区，表空间的单元结构，每个区的大小为1M。默认情况下，InnoDB存储引擎页大小为16K，即一个区中一共有64个连续的页。</li><li>页，是InnoDB存储引擎磁盘管理的最小单元，每个页的大小默认为16KB。为了保证页的连续性，InnoDB存储引擎每次从<br>磁盘申请4-5个区。</li><li>行，InnoDB 存储引擎数据是按行进行存放的。</li></ul><h3 id="2-架构">2.架构</h3><p>MySQL 5.5版本开始，默认使用InnoDB存储引擎，它擅长事务处理，具有崩溃恢复特性，在日常开发中使用非常广泛。下面是InnoDB架构图，左侧为内存结构，右侧为磁盘结构。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230708095029258.png" srcset="/img/loading.gif" lazyload alt="InnoDB架构图"></p><p><strong>内存架构</strong></p><ul><li><p>Buffer Pool：缓冲池是主内存中的一个区域，里面可以缓存磁盘上经常操作的真实数据，在执行增删改查操作时，先操作缓冲池中的数据（若缓冲池没有数据，则从磁盘加载并缓存），然后再以一定频率刷新到磁盘，从而减少磁盘口，加快处理速度。</p></li><li><p>缓冲池以Page页为单位，底层采用链表数据结构管理Page。根据状态，将Page分为三种类型：</p><ol><li>free page：空闲page，未被使用。</li><li>clean page：被使用page，数据没有被修改过。</li><li>dirty page：脏页，被使用page，数据被修改过，页中数据与磁盘的数据产生了不一致。</li></ol></li><li><p>Change Buffer：更改缓冲区（针对于非唯一二级索引页），在执行DML语句时，如果这些数据Page没有在Buffer Pool中，不会直接操作磁盘，而会将数据变更存在更改缓冲区Change Buffer中，在未来数据被读取时，再将数据合并恢复到Buffer Poolr中，再将合并后的数据刷新到磁盘中。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230708100434924.png" srcset="/img/loading.gif" lazyload alt=""></p></li><li><p>Adaptive Hash Index：自适应hash索引，用于优化对 Buffer Pool 数据的查询。InnoDB 存储引擎会监控对表上各索引页的查询，如果观察到 hash 索引可以提升速度，则建立 hash 索引，称之为自适应 hash 索引。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230708100728834.png" srcset="/img/loading.gif" lazyload alt=""></p></li><li><p>Log Buffer：日志缓冲区，用来保存要写入到磁盘中的 log 日志数据（redo log、undo log），默认大小为16MB，日志缓冲区的日志会定期刷新到磁盘中。如果需要更新、插入或删除许多行的事务，增加日志缓冲区的大小可以节省磁盘 I/0。</p><p>参数：innodb_log_buffer_size：缓冲区大小innodb_flush_log_at_trx_commit：日志刷新到磁盘时机</p></li></ul><p><strong>磁盘结构</strong></p><ul><li><p>System Tablespace：系统表空间是更改缓冲区的存储区域。如果表是在系统表空间而不是每个表文件或通用表空间中创建的，它也可能包含表和索引数据。（在 MySQL5.x 版本中还包含 InnoDB 数据字典、undolog等）</p><p>参数：innodb_data_file_path</p></li><li><p>File-Per-Table Tablespaces：每个表的文件表空间包含单个InnoDB表的数据和索引，并存储在文件系统上的单个数据文件中。<br>参数：innodb_file_per_table</p></li><li><p>General Tablespaces：通用表空间，需要通过 CREATE TABLESPACE 语法创建通用表空间，在创建表时，可以指定该表空间。</p></li><li><p>Undo Tablespaces：撤销表空间，MySQL实例在初始化时会自动创建两个默认的undo表空间（初始大小16M），用于存储undo log日志。</p></li><li><p>Temporary Tablespaces：InnoDB使用会话临时表空间和全局临时表空间。存储用户创建的临时表等数据。</p></li><li><p>Doublewrite Buffer Files：双写缓冲区，innoDB引擎将数据页从Buffer Pool刷新到磁盘前，先将数据页写入双写缓冲区文件中，便于系统异常时恢复数据。</p></li><li><p>Redo Log：重做日志，是用来实现事务的持久性。该日志文件由两部分组成：重做日志缓冲（redo log buffer）以及重做日志文件(redo log),前者是在内存中，后者在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中，用于在刷新脏页到磁盘时，发生错误时，进行数据恢复使用。</p></li></ul><p><strong>后台线程</strong></p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230708104200904.png" srcset="/img/loading.gif" lazyload alt=""></p><ol><li><p>Master Thread</p><p>核心后台线程，负责调度其他线程，还负责将缓冲池中的数据异步刷新到磁盘中，保持数据的一致性，还包括脏页的刷新、合并插入缓存、undo 页的回收。</p></li><li><p>IO Thread</p><p>在InnoDB存储引擎中大量使用了AIO来处理IO请求，这样可以极大地提高数据库的性能，而IO Thread主要负责这些IO请求的回调。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230708104625112.png" srcset="/img/loading.gif" lazyload alt="image-20230708104625112"></p></li><li><p>Purge Thread</p><p>主要用于回收事务已经提交了的 undo log，在事务提交之后，undo log 可能不用了，就用它来回收。</p></li><li><p>Page Cleaner Thread</p><p>协助 Master Thread 刷新脏页到磁盘的线程，它可以减轻 Master Thread 的工作压力，减少阻塞。</p></li></ol><h3 id="3-事务原理">3.事务原理</h3><h4 id="事务">事务</h4><p>事务是一组操作的集合，它是一个不可分割的工作单位，事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求，即这些操作要么同时成功，要么同时失败。</p><h4 id="特性">特性</h4><ul><li>原子性（Atomicity）：事务是不可分割的最小操作单元，要么全部成功，要么全部失败。</li><li>一致性（Consistency）：事务完成时，必须使所有的数据都保持一致状态。</li><li>隔离性（Isolation）：数据库系统提供的隔离机制，保证事务在不受外部并发操作影响的独立环境下运行。</li><li>持久性（Durability）：事务一旦提交或回滚，它对数据库中的数据的改变就是永久的。</li></ul><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230708110027460.png" srcset="/img/loading.gif" lazyload alt=""></p><h4 id="redo-log">redo log</h4><p>重做日志，记录的是事务提交时数据页的物理修改，是用来实现事务的持久性。<br>该日志文件由两部分组成：重做日志缓冲（redo log buffer）以及重做日志文件（redo log file）,前者是在内存中，后者在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中，用于在刷新脏页到磁盘，发生错误时，进行数据恢复使用。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230708111140046.png" srcset="/img/loading.gif" lazyload alt=""></p><h4 id="undo-log">undo log</h4><p>回滚日志，用于记录数据被修改前的信息，作用包含两个：提供回滚和 MVCC(多版本并发控制)。<br>undo log 和 redo log  记录物理日志不一样，它是逻辑日志。可以认为当delete一条记录时，undo log中会记录一条对应的 insert记录，反之亦然，当update一条记录时，它记录一条对应相反的update记录。当执行rollback时，就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。<br>Undo log 销毁：undo log在事务执行时产生，事务提交时，并不会立即删除undo log，因为这些日志可能还用于MVCC。<br>Undo log 存储：undo log:采用段的方式进行管理和记录，存放在前面介绍的rollback segment 回滚段中，内部包含1024个undo log<br>segment。</p><h3 id="4-MVCC">4.MVCC</h3><h4 id="基本概念">基本概念</h4><ul><li><p>当前读</p><p>读取的是记录的最新版本，读取时还要保证其他并发事务不能修改当前记录，会对读取的记录进行加锁。对于我们日常的操作，如：<br>select … lock in share mode(共享锁)，select … for update、update、insert、delete(排他锁)都是一种当前读。</p></li><li><p>快照读</p><p>简单的select(不加锁)就是快照读，快照读，读取的是记录数据的可见版本，有可能是历史数据，不加锁，是非阻塞读。<br>Read Committed：每次select,都生成一个快照读。<br>Repeatable Read：开启事务后第一个selecti语句才是快照读的地方。<br>Serializable：快照读会退化为当前读。</p></li><li><p>MVCC</p><p>全称M2ulti-Version Concurrency Control，多版本并发控制。指维护一个数据的多个版本，使得读写操作没有冲突，快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现，还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView。</p></li><li><p>readview</p><p>ReadView（读视图）是<strong>快照读</strong>SQL执行时MVCC提取数据的依据，记录并维护系统当前活跃的事务（未提交的）id。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230709105915084.png" srcset="/img/loading.gif" lazyload alt=""></p><p>不同的隔离级别，生成ReadView的时机不同：</p><ul><li>READ COMMITTED：在事务中每一次执行快照读时生成 ReadView。</li><li>REPEATABLE READ：仅在事务中第一次执行快照读时生成ReadView，后续复用该 ReadView。</li></ul></li></ul><h2 id="七、MySQL管理">七、MySQL管理</h2><h3 id="1-系统数据库">1.系统数据库</h3><p>MySQL 数据库安装完成后，自带了以下四个数据库，具体作用如下：</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230709152834292.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="2-常用工具">2.常用工具</h3><ul><li><p>mysql 客户端工具</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230709153318612.png" srcset="/img/loading.gif" lazyload alt=""></p></li><li><p>mysqladmin</p><p>mysqladmin是一个执行管理操作的客户端程序。可以用它来检查服务器的配置和当前状态、创建并删除数据库等。</p><p>通过帮助文档查看选项：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">mysqladmin --help<br></code></pre></td></tr></table></figure><p>示例：</p><figure class="highlight plaintext"><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 mysql">mysqladmin -uroot -p1234 drop &#x27;test01&#x27;;<br>mysqladmin -uroot -p1234 version;<br></code></pre></td></tr></table></figure></li><li><p>mysqlbinlog</p><p>由于服务器生成的二进制日志文件以二进制格式保存，所以如果想要检查这些文本的文本格式，就会使用到mysqlbinlog日志管理工具。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230709154610864.png" srcset="/img/loading.gif" lazyload alt=""></p></li><li><p>mysqlshow</p><p>mysqlshow客户端对象查找工具，用来很快地查找存在哪些数据库、数据库中的表、表中的列或者索引。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230709155235822.png" srcset="/img/loading.gif" lazyload alt=""></p></li><li><p>mysqldump</p><p>mysqldump 客户端工具用来备份数据库或在不同数据库之间进行数据迁移。备份内容包含创建表，及插入表的sQL语句。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230709160129966.png" srcset="/img/loading.gif" lazyload alt=""></p></li><li><p>mysqlimport/source</p><p>mysqlimport是客户端数据导入工具，用来导入mysqldump加 -T 参数后导出的文本文件。</p><p><img src="https://cdn.gumengyo.top//MySQL-%E9%AB%98%E7%BA%A7/image-20230709161523034.png" srcset="/img/loading.gif" lazyload alt=""></p><p>如果需要导入 sql 文件，可以使用 mysql 中的source指令：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">source /root/xxxx.sql<br></code></pre></td></tr></table></figure></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;h1&gt;MySQL-高级&lt;/h1&gt;
&lt;p class=&quot;note note-success&quot;&gt;
  此文是我学习MySQL时笔记，教程链接：&lt;a href=&quot;https://www.bilibili.com/video/BV1Kr4y1i7ru&quot; target=&quot;_blank&quot;&gt;</summary>
      
    
    
    
    <category term="学习笔记" scheme="https://blog.jishuqin.cn/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="Mysql" scheme="https://blog.jishuqin.cn/tags/Mysql/"/>
    
  </entry>
  
  <entry>
    <title>站点监控-Uptime-kuma</title>
    <link href="https://blog.jishuqin.cn/posts/e8d01234/"/>
    <id>https://blog.jishuqin.cn/posts/e8d01234/</id>
    <published>2023-06-28T16:24:36.000Z</published>
    <updated>2025-09-03T08:59:30.030Z</updated>
    
    <content type="html"><![CDATA[<h1>站点监控-Uptime-kuma</h1><h2 id="1-前言">1. 前言</h2><p><code>Uptime-kuma</code> 是一个基于 Web 的服务器监控工具，用于监视和报告服务器和网络设备的运行时间、性能指标和可用性。它提供了一个直观易用的用户界面，用于实时监控服务器的状态、资源使用情况和响应时间。</p><p><code>Uptime-Kuma</code> 的主要特点包括：</p><ul><li>实时监控：监视服务器和网络设备的运行时间、CPU 和内存使用情况、网络连接、磁盘空间和其他性能指标。</li><li>报警和通知：设置报警规则，以便在服务器出现问题或达到预定指标时收到通知。可以通过电子邮件、短信或其他集成的通知方式接收警报。</li><li>历史数据和性能图表：记录服务器的历史性能数据，并生成可视化图表和报告，用于分析和趋势监控。</li><li>多服务器管理：支持同时监控多台服务器和网络设备，并将它们组织成逻辑分组，方便管理和监控。</li><li>用户和权限管理：提供用户和权限管理功能，可以根据需要设置不同用户的访问权限和角色。</li><li>可扩展性：<code>Uptime-Kuma</code> 提供了一个开放的 <code>API</code> 和插件系统，可以与其他工具和服务进行集成，扩展其功能和定制化需求。</li></ul><h2 id="2-部署">2. 部署</h2><p class="note note-info">本文采用的是 dokcer 容器部署 Uptime-Kuma ，若不想使用docker 来部署可以参考官方文档：<a target="_blank" rel="noopener" href="https://github.com/louislam/uptime-kuma">https://github.com/louislam/uptime-kuma</a>。</p><h3 id="2-1-拉取镜像">2.1 拉取镜像</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">docker pull louislam/uptime-kuma<br></code></pre></td></tr></table></figure><p>查看镜像是否拉取到<code>docker</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">docker images<br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230628164055949.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="2-2-创建映射目录">2.2 创建映射目录</h3><p>这里我创建的目录为：<code>/root/data/kuma/data</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"><span class="hljs-built_in">mkdir</span> -p /root/data/kuma/data<br></code></pre></td></tr></table></figure><h3 id="2-3-运行容器">2.3 运行容器</h3><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">docker run -d --name kuma --restart=always -p 3001:3001 -v /root/data/kuma/data:/app/data -v /var/run/docker.sock:/var/run/docker.sock  louislam/uptime-kuma<br></code></pre></td></tr></table></figure><h2 id="3-配置">3.  配置</h2><p class="note note-warning">运行成功之后，需要开放端口，使 Uptime-Kuma 可以在公网访问。</p><p>我这里设置的端口为<code>3001</code>,打开 <code>http://server_ip:3001</code>访问<code>Uptime-Kuma</code>界面。</p><h3 id="3-1-访问界面">3.1 访问界面</h3><p>首次访问需设置管理员账号</p><p><img src="https://cdn.gumengyo.top//image-20230628165532925.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="3-2-配置反向代理">3.2 配置反向代理</h3><p>我使用的是<code>Nginx Proxy Manager</code> 配置代理，需在<code>DNS</code>服务器添加对应的域名解析记录。</p><p>❗注意：记得开启<code>Websockets</code>支持，否则无法正常访问后台。</p><p><img src="https://cdn.gumengyo.top//image-20230628170914086.png" srcset="/img/loading.gif" lazyload alt=""></p><p>申请<code>ssl</code>证书</p><p><img src="https://cdn.gumengyo.top//image-20230628170522401.png" srcset="/img/loading.gif" lazyload alt=""></p><p>配置完成后，使用域名就可以访问<code>Kuma</code>后台了。</p><h3 id="3-3-添加监控项">3.3 添加监控项</h3><p>登录进后台，点击添加监控项。</p><p><img src="https://cdn.gumengyo.top//image-20230628171254914.png" srcset="/img/loading.gif" lazyload alt=""></p><p>选择<code>监控类型</code>，填入<code>显示名称</code> 和 <code>监控站点路径</code>。</p><p>可根据你实际需求设置其他配置，如：</p><ul><li>设置心跳检测时间间隔（单位秒）</li><li>设置证书到期通知</li><li>设置报警通知，支持多种通知类型</li></ul><p>设置完成后就可以看到站点的各项信息了，如下：</p><p><img src="https://cdn.gumengyo.top//image-20230628172025154.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="3-4-添加状态页">3.4 添加状态页</h3><p>点击<code>状态页面</code> -&gt; <code>新的状态页</code></p><p><img src="https://cdn.gumengyo.top//image-20230628172540869.png" srcset="/img/loading.gif" lazyload alt=""></p><p>设置状态页的名称和路径</p><p><img src="https://cdn.gumengyo.top//image-20230628172650430.png" srcset="/img/loading.gif" lazyload alt=""></p><p>添加服务项，其他按需设置即可，点击保存。</p><p><img src="https://cdn.gumengyo.top//image-20230628172852407.png" srcset="/img/loading.gif" lazyload alt=""></p><h2 id="4-效果">4. 效果</h2><p>访问对应路径即可查看服务状态信息。</p><p><img src="https://cdn.gumengyo.top//image-20230628173052926.png" srcset="/img/loading.gif" lazyload alt=""></p><p>效果可以参看我的状态页：<a href="https://kuma.jishuqin.cn/status/main">https://kuma.jishuqin.cn/status/main</a></p><h2 id="参考">参考</h2><section class="footnotes"><div class="footnote-list"><ol><li><span id="fn:1" class="footnote-text"><span><a href="https://blog.crazymiao.com/2022/08/uptime-kuma">教你两分钟快速搭建一个HTTP网站监控程序-Uptime-kuma</a><a href="#fnref:1" rev="footnote" class="footnote-backref"> ↩</a></span></span></li><li><span id="fn:2" class="footnote-text"><span><a href="https://bbs.huaweicloud.com/blogs/385898">云原生之使用docker部署uptime-kuma服务器监控面板</a><a href="#fnref:2" rev="footnote" class="footnote-backref"> ↩</a></span></span></li></ol></div></section>]]></content>
    
    
      
      
    <summary type="html">&lt;h1&gt;站点监控-Uptime-kuma&lt;/h1&gt;
&lt;h2 id=&quot;1-前言&quot;&gt;1. 前言&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Uptime-kuma&lt;/code&gt; 是一个基于 Web 的服务器监控工具，用于监视和报告服务器和网络设备的运行时间、性能指标和可用性。它提供了一个直观易用的用</summary>
      
    
    
    
    <category term="服务配置" scheme="https://blog.jishuqin.cn/categories/%E6%9C%8D%E5%8A%A1%E9%85%8D%E7%BD%AE/"/>
    
    
    <category term="Uptime-kuma" scheme="https://blog.jishuqin.cn/tags/Uptime-kuma/"/>
    
    <category term="站点监控" scheme="https://blog.jishuqin.cn/tags/%E7%AB%99%E7%82%B9%E7%9B%91%E6%8E%A7/"/>
    
  </entry>
  
  <entry>
    <title>给 Fluid 主题博客增加打赏功能</title>
    <link href="https://blog.jishuqin.cn/posts/92f5a6bc/"/>
    <id>https://blog.jishuqin.cn/posts/92f5a6bc/</id>
    <published>2023-06-17T22:50:10.000Z</published>
    <updated>2025-09-03T08:59:30.030Z</updated>
    
    <content type="html"><![CDATA[<h1>给 Fluid 主题博客增加打赏功能</h1><h2 id="1-前言">1. 前言</h2><p>看到别人的博客都有打赏的功能，所以自己也想着在自己博客加入打赏功能，百度到了<a href="https://blog.kukmoon.com/">谷月</a>的博文，参考博文实现了功能~<sup id="fnref:1" class="footnote-ref"><a href="#fn:1" rel="footnote"><span class="hint--top hint--rounded" aria-label="[Kukmoon谷月.给 Hexo 博客的 Fluid 主题增加打赏模块.2021-11-18](https://blog.kukmoon.com/7bf76e1d/)">[1]</span></a></sup></p><h2 id="2-覆盖配置">2.  覆盖配置</h2><p>以下配置参考 Hexo Fluid 手册<sup id="fnref:2" class="footnote-ref"><a href="#fn:2" rel="footnote"><span class="hint--top hint--rounded" aria-label="[Hexo Fluid 手册](https://hexo.fluid-dev.com/docs/guide/#%E8%A6%86%E7%9B%96%E9%85%8D%E7%BD%AE)">[2]</span></a></sup></p><p class="note note-success">TIP:<br>覆盖配置可以使主题配置放置在 fluid 目录之外，避免在更新主题时丢失自定义的配置。通过 Npm 安装主题的用户可忽略，其他用户建议学习使用。</p><p>Hexo 5.0.0 版本以上的用户，在博客目录下创建 <code>_config.fluid.yml</code> 文件，将主题的<a href="https://github.com/fluid-dev/hexo-theme-fluid/blob/master/_config.yml">_config.yml</a> 全部配置（或部分配置）复制过去。<br>以后如果修改任何主题配置，都只需修改 <code>_config.fluid.yml</code> 的配置即可。</p><p>注意：</p><ul><li><p>只要存在于 <code>_config.fluid.yml</code> 的配置都是高优先级，修改原 <code>_config.yml</code> 是无效的。</p></li><li><p>每次更新主题可能存在配置变更，请注意更新说明，可能需要手动对 <code>_config.fluid.yml</code> 同步修改。</p></li><li><p>想查看覆盖配置有没有生效，可以通过 <code>hexo g --debug</code> 查看命令行输出。</p></li><li><p>如果想将某些配置覆盖为空，注意不要把主键删掉，不然是无法覆盖的，比如：</p><figure class="highlight yaml"><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 yaml"><span class="hljs-attr">about:</span><br>  <span class="hljs-attr">icons:</span>  <span class="hljs-comment"># 不要把 icon 注释掉，否则无法覆盖配置</span><br>    <span class="hljs-comment"># - &#123; class: &#x27;iconfont icon-github-fill&#x27;, link: &#x27;https://github.com&#x27; &#125;</span><br>    <span class="hljs-comment"># - &#123; class: &#x27;iconfont icon-wechat-fill&#x27;, qrcode: &#x27;/img/favicon.png&#x27; &#125;</span><br></code></pre></td></tr></table></figure></li></ul><h2 id="3-修改主题源文件">3. 修改主题源文件</h2><p><img src="https://cdn.gumengyo.top//image-20230617233736066.png" srcset="/img/loading.gif" lazyload alt=""></p><p>找到主题源文件<code>themes/fluid/layout/post.ejs</code>对应文章模板的 <code>&lt;/div&gt;</code> 和 <code>&lt;hr&gt;</code> 之间，添加以下代码：</p><figure class="highlight plaintext"><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 ejs">&lt;!-- 添加打赏模块 --&gt;<br>&lt;div class=&quot;reward-container&quot;&gt;<br>&lt;% if (theme.donate.enable) &#123; %&gt;<br>&lt;button id=&quot;rewardBtn&quot; class=&quot;reward-btn&quot;&gt;<br>&lt;% if (config.language == &#x27;zh-CN&#x27;) &#123; %&gt; <br>❤ 打赏<br>&lt;% &#125; else &#123; %&gt;<br>Donate<br>&lt;% &#125; %&gt;<br>&lt;/button&gt;<br>&lt;p class=&quot;tea&quot;&gt;“&lt;%= theme.donate.message %&gt;”&lt;/p&gt;<br>&lt;div id=&quot;rewardImgContainer&quot; class=&quot;reward-img-container&quot;&gt;<br>         &lt;div class=&quot;singleImgContainer&quot;&gt;<br>            &lt;img id=&quot;wechatImg&quot; class=&quot;reward-img&quot; src=&quot;&lt;%= theme.donate.wechatpay %&gt;&quot; alt=&quot;微信二维码&quot;&gt;<br>                &lt;p class=&quot;wechatPay&quot;&gt;微信支付&lt;/p&gt;<br>            &lt;/div&gt;<br>            &lt;div class=&quot;singleImgContainer&quot;&gt;<br>               &lt;img id=&quot;alipayImg&quot; class=&quot;reward-img&quot; src=&quot;&lt;%= theme.donate.alipay %&gt;&quot; alt=&quot;支付宝二维码&quot;&gt;<br>                &lt;p class=&quot;aliPay&quot;&gt;支付宝支付&lt;/p&gt;<br>           &lt;/div&gt;<br>&lt;/div&gt;<br>&lt;% &#125; %&gt;<br>&lt;/div&gt;<br></code></pre></td></tr></table></figure><h2 id="4-修改主题配置文件">4. 修改主题配置文件</h2><h3 id="4-1-引入-css-和-js-文件">4.1 引入 css 和 js 文件</h3><p>在<code>themes/fluid/source/css</code> 创建名为：<code>reward.css</code>的文件，并引入以下代码：</p><figure class="highlight css"><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></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-selector-class">.tea</span> &#123;<br>    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">0.8125em</span>;<br>    <span class="hljs-attribute">color</span>: <span class="hljs-number">#999999</span>;<br>    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;<br>&#125;<br><br><span class="hljs-selector-class">.reward-container</span> &#123;<br>    <span class="hljs-attribute">display</span>: flex;<br>    <span class="hljs-attribute">flex-direction</span>: column;<br>    <span class="hljs-attribute">align-items</span>: center;<br>    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">50px</span>;<br>&#125;<br><br><span class="hljs-selector-class">.reward-btn</span> &#123;<br>    <span class="hljs-attribute">padding</span>: <span class="hljs-number">8px</span> <span class="hljs-number">24px</span>;<br>    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;<br>    <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#007bff</span>;<br>    <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;<br>    <span class="hljs-attribute">border</span>: none;<br>    <span class="hljs-attribute">cursor</span>: pointer;<br>    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;<br>&#125;<br><br><span class="hljs-selector-class">.reward-img-container</span> &#123;<br>    <span class="hljs-attribute">display</span>: none;<br>    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">20px</span>;<br>    <span class="hljs-comment">/* 图片容器的透明度 */</span><br>    <span class="hljs-attribute">opacity</span>: <span class="hljs-number">0</span>;<br>    <span class="hljs-comment">/* 过渡效果,使动画更平滑 */</span><br>    <span class="hljs-attribute">transition</span>: opacity <span class="hljs-number">2s</span> ease;<br>&#125;<br><br><span class="hljs-selector-class">.reward-img</span> &#123;<br>    <span class="hljs-attribute">width</span>: <span class="hljs-number">200px</span>;<br>    <span class="hljs-attribute">margin</span>: <span class="hljs-number">10px</span>;<br>    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> dashed <span class="hljs-number">#ccc</span>;<br>    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">4px</span>;<br>    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;<br>&#125;<br><br><span class="hljs-comment">/* 单个图片的容器 */</span><br><span class="hljs-selector-class">.singleImgContainer</span> &#123;<br>    <span class="hljs-attribute">width</span>: <span class="hljs-number">50%</span>;<br>    <span class="hljs-attribute">height</span>: <span class="hljs-number">240px</span>;<br>&#125;<br><br><span class="hljs-comment">/* 微信支付和支付宝支付的文字样式 */</span><br><span class="hljs-selector-class">.wechatPay</span>,<span class="hljs-selector-class">.aliPay</span> &#123;<br><span class="hljs-attribute">text-align</span>: center;<br>    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">0.8125em</span>;<br>    <span class="hljs-attribute">color</span>: <span class="hljs-number">#999999</span>;<br>&#125;<br></code></pre></td></tr></table></figure><p>在<code>themes/fluid/source/js</code> 创建名为：<code>reward.js</code>的文件，并引入以下代码：</p><figure class="highlight js"><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 js"><span class="hljs-keyword">const</span> rewardBtn = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&#x27;rewardBtn&#x27;</span>);<br><span class="hljs-keyword">const</span> rewardImgContainer = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&#x27;rewardImgContainer&#x27;</span>);<br><br><span class="hljs-keyword">if</span>(rewardBtn)&#123;<br>rewardBtn.<span class="hljs-property">onclick</span> = <span class="hljs-function">() =&gt;</span> &#123;<br>rewardImgContainer.<span class="hljs-property">style</span>.<span class="hljs-property">display</span> = (rewardImgContainer.<span class="hljs-property">style</span>.<span class="hljs-property">display</span> === <span class="hljs-string">&#x27;none&#x27;</span> || rewardImgContainer.<span class="hljs-property">style</span>.<span class="hljs-property">display</span> === <span class="hljs-string">&#x27;&#x27;</span>) ? <span class="hljs-string">&#x27;inline-flex&#x27;</span> : <span class="hljs-string">&#x27;none&#x27;</span><br><span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> &#123;<br>rewardImgContainer.<span class="hljs-property">style</span>.<span class="hljs-property">opacity</span> = (rewardImgContainer.<span class="hljs-property">style</span>.<span class="hljs-property">opacity</span> === <span class="hljs-string">&#x27;0&#x27;</span> || rewardImgContainer.<span class="hljs-property">style</span>.<span class="hljs-property">opacity</span> === <span class="hljs-string">&#x27;&#x27;</span>) ? <span class="hljs-string">&#x27;1&#x27;</span> : <span class="hljs-string">&#x27;0&#x27;</span><br>&#125;, <span class="hljs-number">10</span>);<br>&#125;<br>&#125;<br></code></pre></td></tr></table></figure><h3 id="4-2-修改-config-fluid-yml-文件">4.2 修改 _config.fluid.yml 文件</h3><p class="note note-warning">如果没有使用覆盖配置，就要打开博客源文件所在的文件夹下的 theme/fluid/_config.yml 文件.</p><p>在文件的 <code>custom_js</code>和<code>custom_css</code>分别引入自定义的 <code>reward.js</code>文件和<code>reward.css</code>文件。</p><p><img src="https://cdn.gumengyo.top//image-20230617235409049.png" srcset="/img/loading.gif" lazyload alt=""></p><p>打开博客源文件所在的文件夹下的 <code>_config.fluid.yml</code> 文件，在最后添加如下内容：</p><figure class="highlight yaml"><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 yaml"><span class="hljs-comment"># Donate 自己为 Fluid 主题增加的打赏功能</span><br><span class="hljs-comment"># `message` 是打赏提示语，可自定义</span><br><span class="hljs-comment"># `alipay` 是支付宝付款码， `wechatpay` 是微信付款码。</span><br><span class="hljs-attr">donate:</span><br>  <span class="hljs-attr">enable:</span> <span class="hljs-literal">true</span><br>  <span class="hljs-attr">message:</span> <span class="hljs-string">觉得不错的话，给点打赏吧</span> <span class="hljs-string">୧(๑•̀⌄•́๑)૭</span> <br>  <span class="hljs-attr">alipay:</span> <span class="hljs-string">/img/alipay.png</span><br>  <span class="hljs-attr">wechatpay:</span> <span class="hljs-string">/img/wechatpay.jpg</span><br></code></pre></td></tr></table></figure><p><strong>参数说明：</strong></p><ul><li><code>message</code>： 自定义打赏提示语</li><li><code>alipay</code>：支付宝打赏图片</li><li><code>wechatpay</code>：微信打赏图片</li></ul><p><strong>记得设置上自己的打赏图片哟~</strong></p><p>hexo 重新加载配置：</p><figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs 1c">hexo clean <span class="hljs-meta">&amp;&amp; hexo g</span><br></code></pre></td></tr></table></figure><h2 id="5-效果">5. 效果</h2><p><img src="https://cdn.gumengyo.top//image-20230618000812083.png" srcset="/img/loading.gif" lazyload alt="未点击打赏按钮时"></p><p><img src="https://cdn.gumengyo.top//image-20230618000739725.png" srcset="/img/loading.gif" lazyload alt="点击打赏按钮时"></p><h2 id="参考">参考</h2><section class="footnotes"><div class="footnote-list"><ol><li><span id="fn:1" class="footnote-text"><span><a href="https://blog.kukmoon.com/7bf76e1d/">Kukmoon谷月.给 Hexo 博客的 Fluid 主题增加打赏模块.2021-11-18</a><a href="#fnref:1" rev="footnote" class="footnote-backref"> ↩</a></span></span></li><li><span id="fn:2" class="footnote-text"><span><a href="https://hexo.fluid-dev.com/docs/guide/#%E8%A6%86%E7%9B%96%E9%85%8D%E7%BD%AE">Hexo Fluid 手册</a><a href="#fnref:2" rev="footnote" class="footnote-backref"> ↩</a></span></span></li></ol></div></section>]]></content>
    
    
      
      
    <summary type="html">&lt;h1&gt;给 Fluid 主题博客增加打赏功能&lt;/h1&gt;
&lt;h2 id=&quot;1-前言&quot;&gt;1. 前言&lt;/h2&gt;
&lt;p&gt;看到别人的博客都有打赏的功能，所以自己也想着在自己博客加入打赏功能，百度到了&lt;a href=&quot;https://blog.kukmoon.com/&quot;&gt;谷月&lt;/a&gt;的博文，</summary>
      
    
    
    
    <category term="博客配置" scheme="https://blog.jishuqin.cn/categories/%E5%8D%9A%E5%AE%A2%E9%85%8D%E7%BD%AE/"/>
    
    
    <category term="Fluid" scheme="https://blog.jishuqin.cn/tags/Fluid/"/>
    
    <category term="Hexo" scheme="https://blog.jishuqin.cn/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>Github首页添加贪吃蛇动画</title>
    <link href="https://blog.jishuqin.cn/posts/c4d5e6f7/"/>
    <id>https://blog.jishuqin.cn/posts/c4d5e6f7/</id>
    <published>2023-06-11T15:58:00.000Z</published>
    <updated>2024-09-05T08:35:10.549Z</updated>
    
    <content type="html"><![CDATA[<h1>Github 首页添加贪吃蛇动画</h1><p><img src="https://cdn.gumengyo.top//snake.svg" srcset="/img/loading.gif" lazyload alt=""></p><h2 id="一、前言">一、前言</h2><p>动画所需要的代码是运行到 <code>Github Actions</code>。</p><p><code>GitHub Actions</code> 是一个用于自动化软件工作流程的平台，包括构建、测试和部署代码。它允许开发人员为软件开发过程的不同阶段创建自定义工作流程，并自动执行重复的任务。<code>GitHub Actions</code> 可以集成到 <code>GitHub</code> 存储库中，并可以被各种事件（如拉取请求、提交和发布）触发。使用 <code>GitHub Actions</code>，开发人员可以轻松协作、减少错误并节省时间。它支持广泛的编程语言，并提供了许多预构建的操作 <code>actions</code>在 <code>GitHub Marketplace</code> 中使用。</p><h2 id="二、创建-Action">二、创建 Action</h2><p class="note note-warning">需在 Github 账户同名的仓库下创建 Action，点击 New workflow -> Configure。</p><p><img src="https://cdn.gumengyo.top//202306120006322.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top//202306120006426.png" srcset="/img/loading.gif" lazyload alt=""></p><p>点击 Configure 后显示如下界面：</p><p><img src="https://cdn.gumengyo.top//202306120007077.png" srcset="/img/loading.gif" lazyload alt=""></p><h2 id="三、配置脚本">三、配置脚本</h2><p>将下面代码复制粘贴到 <code>yml</code>文件中，然后点击 <code>Commit changes</code>部署脚本。</p><figure class="highlight yaml"><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></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">generate</span> <span class="hljs-string">animation</span><br><br><span class="hljs-attr">on:</span><br>  <span class="hljs-comment"># run automatically every 24 hours</span><br>  <span class="hljs-attr">schedule:</span><br>    <span class="hljs-bullet">-</span> <span class="hljs-attr">cron:</span> <span class="hljs-string">&quot;0 */24 * * *&quot;</span> <br>  <br>  <span class="hljs-comment"># allows to manually run the job at any time</span><br>  <span class="hljs-attr">workflow_dispatch:</span><br>  <br>  <span class="hljs-comment"># run on every push on the master branch</span><br>  <span class="hljs-attr">push:</span><br>    <span class="hljs-attr">branches:</span><br>    <span class="hljs-bullet">-</span> <span class="hljs-string">main</span><br>  <br>  <br><br><span class="hljs-attr">jobs:</span><br>  <span class="hljs-attr">generate:</span><br>    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span><br>    <span class="hljs-attr">timeout-minutes:</span> <span class="hljs-number">10</span><br>  <br>    <span class="hljs-attr">steps:</span><br>      <span class="hljs-comment"># generates a snake game from a github user (&lt;github_user_name&gt;) contributions graph, output a svg animation at &lt;svg_out_path&gt;</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">generate</span> <span class="hljs-string">github-contribution-grid-snake.svg</span><br>        <span class="hljs-attr">uses:</span> <span class="hljs-string">Platane/snk/svg-only@v3</span><br>        <span class="hljs-attr">with:</span><br>          <span class="hljs-attr">github_user_name:</span> <span class="hljs-string">$&#123;&#123;</span> <span class="hljs-string">github.repository_owner</span> <span class="hljs-string">&#125;&#125;</span><br>          <span class="hljs-attr">outputs:</span> <span class="hljs-string">|</span><br><span class="hljs-string">            dist/github-contribution-grid-snake.svg</span><br><span class="hljs-string">            dist/github-contribution-grid-snake-dark.svg?palette=github-dark</span><br><span class="hljs-string"></span>        <span class="hljs-attr">env:</span><br>          <span class="hljs-attr">GITHUB_TOKEN:</span> <span class="hljs-string">$&#123;&#123;</span> <span class="hljs-string">secrets.GIT_TOKEN</span> <span class="hljs-string">&#125;&#125;</span><br>  <br>  <br>      <span class="hljs-comment"># push the content of &lt;build_dir&gt; to a branch</span><br>      <span class="hljs-comment"># the content will be available at https://raw.githubusercontent.com/&lt;github_user&gt;/&lt;repository&gt;/&lt;target_branch&gt;/&lt;file&gt; , or as github page</span><br>      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">push</span> <span class="hljs-string">github-contribution-grid-snake.svg</span> <span class="hljs-string">to</span> <span class="hljs-string">the</span> <span class="hljs-string">output</span> <span class="hljs-string">branch</span><br>        <span class="hljs-attr">uses:</span> <span class="hljs-string">crazy-max/ghaction-github-pages@v3.1.0</span><br>        <span class="hljs-attr">with:</span><br>          <span class="hljs-attr">target_branch:</span> <span class="hljs-string">output</span><br>          <span class="hljs-attr">build_dir:</span> <span class="hljs-string">dist</span><br>        <span class="hljs-attr">env:</span><br>          <span class="hljs-attr">GITHUB_TOKEN:</span> <span class="hljs-string">$&#123;&#123;</span> <span class="hljs-string">secrets.GIT_TOKEN</span> <span class="hljs-string">&#125;&#125;</span><br></code></pre></td></tr></table></figure><p>添加 action secrets  <code>GIT_TOKEN</code> 值填你自己生成的github token</p><p><img src="https://cdn.gumengyo.top/Qexo/24/9/9864ac3c197376e0dfc8ac2936cf867a.png" srcset="/img/loading.gif" lazyload alt="https://cdn.gumengyo.top/Qexo/24/9/9864ac3c197376e0dfc8ac2936cf867a.png"></p><h2 id="四、设置-workflow-权限">四、设置 workflow 权限</h2><p><code>settings</code>-&gt; <code>Actions</code> -&gt; <code>General</code> -&gt; <code>Read and write permissions</code>设置读写权限</p><p><img src="https://cdn.gumengyo.top//image-20230615223425490.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top//image-20230615223547928.png" srcset="/img/loading.gif" lazyload alt=""></p><h2 id="五、运行-workflow">五、运行 workflow</h2><p>点击 <code>Actions</code>到刚才配置好的 <code>workflow</code>，点击 <code>Run workflow</code>安全运行脚本。</p><p><img src="https://cdn.gumengyo.top//202306120005242.png" srcset="/img/loading.gif" lazyload alt=""></p><h2 id="六、引入-svg-动画">六、引入 svg 动画</h2><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">![](https:<span class="hljs-regexp">//</span>raw.githubusercontent.com<span class="hljs-regexp">/你的 GitHub 名/</span>你的 GitHub 名<span class="hljs-regexp">/output/gi</span>thub-contribution-grid-snake.svg)<br></code></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">Github 首页添加贪吃蛇动画  一、前言 动画所需要的代码是运行到 Github Actions。 GitHub Actions 是一个用于自动化软件工作流程的平台，包括构建、测试和部署代码。它允许开发人员为软件开发过程的不同阶段创建自定义工作流程，并自动执行重复的任务。GitHub Actions 可以集成到 GitHub 存储库中，并可以被各种事件（如拉取请求、提交和发布）触发。使用 GitHub Actions，开发人员可以轻松协作、减少错误并节省时间。它支持广泛的编程语言，并提供了许多预构建的操作 actions在 GitHub Marketplace 中使用。 二、创建 Acti...</summary>
    
    
    
    <category term="页面美化" scheme="https://blog.jishuqin.cn/categories/%E9%A1%B5%E9%9D%A2%E7%BE%8E%E5%8C%96/"/>
    
    
    <category term="Github" scheme="https://blog.jishuqin.cn/tags/Github/"/>
    
  </entry>
  
  <entry>
    <title>加密算法</title>
    <link href="https://blog.jishuqin.cn/posts/1f2e3d4c/"/>
    <id>https://blog.jishuqin.cn/posts/1f2e3d4c/</id>
    <published>2023-06-09T17:19:00.000Z</published>
    <updated>2025-09-03T08:59:30.029Z</updated>
    
    <content type="html"><![CDATA[<p class="note note-primary">此文为我在校学习物联网安全课程的笔记~</p><h2 id="凯撒密码">凯撒密码</h2><p>凯撒密码是一种古代的加密方式，它是史上第一个广为使用的密码，得名于古罗马军事统帅凯撒。它的基本思想是对明文进行位移，即将明文中的每个字母都替换成字母表中靠它固定数量的字母。例如，若位移数为3，则a变成d，b变成e，…，y变成b，z变成c。</p><p>下面是一个例子，对明文“HELLO WORLD”进行加密：<br>位移数 = 3</p><p>明文  ：</p><table><thead><tr><th>H</th><th>E</th><th>L</th><th>L</th><th>O</th><th></th><th>W</th><th>O</th><th>R</th><th>L</th><th>D</th></tr></thead><tbody><tr><td>8</td><td>5</td><td>12</td><td>12</td><td>15</td><td></td><td>23</td><td>15</td><td>18</td><td>12</td><td>4</td></tr></tbody></table><p>密文  ：</p><table><thead><tr><th>K</th><th>H</th><th>O</th><th>O</th><th>R</th><th></th><th>Z</th><th>R</th><th>U</th><th>O</th><th>G</th></tr></thead><tbody><tr><td>11</td><td>8</td><td>15</td><td>15</td><td>18</td><td></td><td>26</td><td>18</td><td>21</td><td>15</td><td>7</td></tr></tbody></table><p>可以看到，每个字母都向后移动了三个位置，得到了对应的密文。</p><h2 id="置换密码">置换密码</h2><h3 id="平移置换加密法">平移置换加密法</h3><p>置换加密法的一种简单实现形式是平移置换加密法，这很像洗一副纸牌。在平移置换加密法中，将密文分成了固定长度的块。通常，块越大越不容易破译。设块大小为s，置换函数f用于从1到s中选取一个整数，每个块中的字母根据f重新排列。这种加密法的密钥就是（s，f）对应的具体数值。例如，设s为4，f给定为（2，4，1，3）。这意味着第1个字符移到位置3，第2个字符移到位置1，第3个字符移到位置4，第4个字符移到位置2。</p><p>例如，利用这种置换加密法将明文“The only limit to our realization of tomorrow will be our doubts of today”加密。首先，设置密钥（d，f），如将d设为7，则明文将被分成块，每块包含7个字母，不足的用空字符填满。然后，根据给定的函数f=（4，2，3，5，7，6，1）将每个块重新排列，生成对应的密文，如下所示。</p><figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs pgsql">The <span class="hljs-keyword">only</span> <span class="hljs-keyword">limit</span> <span class="hljs-keyword">to</span> our realization <span class="hljs-keyword">of</span> tomorrow will be our doubts <span class="hljs-keyword">of</span> today<br></code></pre></td></tr></table></figure><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ebnf"><span class="hljs-attribute">ohenyltiimtotlrurelaotzainoioftmroowowillrueorodbsbtotfuydazzzo</span><br></code></pre></td></tr></table></figure><h3 id="列位移置换函数">列位移置换函数</h3><p>列置换加密法是将明文按行填写在一个矩形中，而密文则是以预定的顺序按列读取生成的。例如，如果矩形是4列5行，那么短语“encryption algorithms”可以如图6所示写入矩形中。</p><table><thead><tr><th style="text-align:center">1</th><th style="text-align:center">2</th><th style="text-align:center">3</th><th style="text-align:center">4</th></tr></thead><tbody><tr><td style="text-align:center">e</td><td style="text-align:center">n</td><td style="text-align:center">c</td><td style="text-align:center">r</td></tr><tr><td style="text-align:center">y</td><td style="text-align:center">p</td><td style="text-align:center">t</td><td style="text-align:center">i</td></tr><tr><td style="text-align:center">o</td><td style="text-align:center">n</td><td style="text-align:center">a</td><td style="text-align:center">l</td></tr><tr><td style="text-align:center">g</td><td style="text-align:center">o</td><td style="text-align:center">r</td><td style="text-align:center">i</td></tr><tr><td style="text-align:center">t</td><td style="text-align:center">h</td><td style="text-align:center">m</td><td style="text-align:center">s</td></tr></tbody></table><p>按一定的顺序读取列以生成密文。对于这个示例，如果读取顺序是4、1、2、3，那么密文就是“riliseyogtnpnohctarm”。这种加密法要求填满矩形，因此，如果明文的字母不够，可以添加“x”或“q”甚至空字符。<br>这种加密法的密钥是列数和读取列的顺序。如果列数很多，则记起来可能会比较闲难，因此可以将它表示成一个关键词，以方便记忆。该关键词的长度等于列数，而其字母顺序决定读取列的顺序。</p><h3 id="栅栏式置换函数">栅栏式置换函数</h3><h4 id="对角线方式">对角线方式</h4><p><strong>使用了对角线方式。在这种加密法中，明文是按Z字形的方式填写在矩形的对角线上，而按行读取生成密文。</strong></p><p>例如，如果矩形的高为3，长为11，那么明文“this is a test”在该矩形中的填写如图4所示。而按行读取所生成的密文就是“tiehsstsiat”。</p><table><thead><tr><th style="text-align:center">t</th><th style="text-align:center"></th><th style="text-align:center"></th><th style="text-align:center"></th><th style="text-align:center">i</th><th style="text-align:center"></th><th style="text-align:center"></th><th style="text-align:center"></th><th style="text-align:center">e</th><th style="text-align:center"></th><th style="text-align:center"></th></tr></thead><tbody><tr><td style="text-align:center"></td><td style="text-align:center">h</td><td style="text-align:center"></td><td style="text-align:center">s</td><td style="text-align:center"></td><td style="text-align:center">s</td><td style="text-align:center"></td><td style="text-align:center">t</td><td style="text-align:center"></td><td style="text-align:center">s</td><td style="text-align:center"></td></tr><tr><td style="text-align:center"></td><td style="text-align:center"></td><td style="text-align:center">i</td><td style="text-align:center"></td><td style="text-align:center"></td><td style="text-align:center"></td><td style="text-align:center">a</td><td style="text-align:center"></td><td style="text-align:center"></td><td style="text-align:center"></td><td style="text-align:center">t</td></tr></tbody></table><h4 id="三角加密">三角加密</h4><p>例如，在一个固定大小的矩形中，可以将明文填写成一个三角形，然后按列读取生成密文。图5所示的是将明文“you must do that now”填写在一个7x4的矩形中。按行读取生成的密文是“tuhosayuttmdnoow”。</p><table><thead><tr><th style="text-align:center"></th><th style="text-align:center"></th><th style="text-align:center"></th><th style="text-align:center">y</th><th style="text-align:center"></th><th style="text-align:center"></th><th style="text-align:center"></th></tr></thead><tbody><tr><td style="text-align:center"></td><td style="text-align:center"></td><td style="text-align:center">o</td><td style="text-align:center">u</td><td style="text-align:center">m</td><td style="text-align:center"></td><td style="text-align:center"></td></tr><tr><td style="text-align:center"></td><td style="text-align:center">u</td><td style="text-align:center">s</td><td style="text-align:center">t</td><td style="text-align:center">d</td><td style="text-align:center">o</td><td style="text-align:center"></td></tr><tr><td style="text-align:center">t</td><td style="text-align:center">h</td><td style="text-align:center">a</td><td style="text-align:center">t</td><td style="text-align:center">n</td><td style="text-align:center">o</td><td style="text-align:center">w</td></tr></tbody></table><h2 id="RSA-加密算法">RSA 加密算法</h2><p><img src="https://cdn.gumengyo.top//1685516391257-d602b2d6-3cb6-4433-9a7d-d7dff8a1c159.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top//1685516409843-62eff3b1-0c9f-4e4c-adc0-4fceb806406f.png" srcset="/img/loading.gif" lazyload alt=""></p><p>RSA是一种非对称加密算法。假设需要将明文&quot;MONEY&quot;进行加密，并使用RSA算法保护数据的安全性。以下是RSA加密和解密的详细运算过程。</p><ol><li>密钥生成过程：</li></ol><p>选择两个大素数p=11和q=17，计算n=p<em>q=187，根据欧拉函数的定义φ(n)=(p-1)</em>(q-1)=160，选择一个小于φ(n)且与φ(n)互质的整数e=7，计算e的模逆数d，使得(e*d) mod φ(n)=1，有d=23。公钥为(n,e)=(187,7)，私钥为(n,d)=(187,23)。</p><ol start="2"><li>加密过程：</li></ol><p>将明文&quot;MONEY&quot;转换成相应的ASCII码数值&quot;77 79 78 69 89&quot;，然后使用公钥(n, e)对每个数字进行加密运算，并将得到的密文表示成16进制数。</p><ul><li><p>明文&quot;M&quot;，对应的ASCII码为77，加密后的密文为：</p><p>C = 77^7 mod 187 = 38</p><p>密文位数不足2位，需要在前面补0，因此该密文表示成16进制为0x26。</p></li><li><p>明文&quot;O&quot;，对应的ASCII码为79，加密后的密文为：</p><p>C = 79^7 mod 187 = 178</p><p>该密文表示成16进制为0xB2。</p></li><li><p>明文&quot;N&quot;，对应的ASCII码为78，加密后的密文为：</p><p>C = 78^7 mod 187 = 89</p><p>密文位数不足2位，需要在前面补0，因此该密文表示成16进制为0x59。</p></li><li><p>明文&quot;E&quot;，对应的ASCII码为69，加密后的密文为：</p><p>C = 69^7 mod 187 = 19</p><p>密文位数不足2位，需要在前面补0，因此该密文表示成16进制为0x13。</p></li><li><p>明文&quot;Y&quot;，对应的ASCII码为89，加密后的密文为：</p><p>C = 89^7 mod 187 = 157</p><p>该密文表示成16进制为0x9D。</p></li></ul><p>因此，明文&quot;MONEY&quot;加密后的密文为&quot;0x26 0xB2 0x59 0x13 0x9D&quot;。</p><ol start="3"><li>解密过程：</li></ol><p>使用私钥(n, d)对上一步得到的密文进行解密。</p><ul><li><p>密文&quot;0x26&quot;，解密后得到原文为：</p><p>M = 38^23 mod 187 = 77</p><p>解密后的原文为&quot;M&quot;。</p></li><li><p>密文&quot;0xB2&quot;，解密后得到原文为：</p><p>M = 178^23 mod 187 = 79</p><p>解密后的原文为&quot;O&quot;。</p></li><li><p>密文&quot;0x59&quot;，解密后得到原文为：</p><p>M = 89^23 mod 187 = 78</p><p>解密后的原文为&quot;N&quot;。</p></li><li><p>密文&quot;0x13&quot;，解密后得到原文为：</p><p>M = 19^23 mod 187 = 69</p><p>解密后的原文为&quot;E&quot;。</p></li><li><p>密文&quot;0x9D&quot;，解密后得到原文为：</p><p>M = 157^23 mod 187 = 89</p><p>解密后的原文为&quot;Y&quot;。</p></li></ul><p>因此，RSA算法加密后再解密，得到的原文是&quot;MONEY&quot;。</p><p>以上就是RSA加密和解密的详细运算过程。RSA算法是一种非常流行的公钥加密算法，其安全性取决于选取的参数。在实际应用中，需要采用足够长度的密钥和安全的参数，以保护数据的安全性。</p><h3 id="证明题">证明题</h3><p class="katex-block "><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext>证明题一：</mtext><mi>φ</mi><mtext>（</mtext><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>n</mi><mo>−</mo><mn>1</mn><mtext>，</mtext><mi>n</mi><mtext>为质数</mtext><mspace linebreak="newline"></mspace><mtext>证明：</mtext><mi>φ</mi><mtext>（</mtext><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>n</mi><munderover><mo>∏</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>k</mi></munderover><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mfrac><mn>1</mn><msub><mi>P</mi><mi>i</mi></msub></mfrac><mo stretchy="false">)</mo><mo separator="true">,</mo><msub><mi>P</mi><mi>i</mi></msub><mtext>为</mtext><mi>n</mi><mtext>的质因数</mtext><mspace linebreak="newline"></mspace><mtext>当</mtext><mi>n</mi><mtext>为质数时，</mtext><mi>n</mi><mtext>的非</mtext><mn>1</mn><mtext>质因数为</mtext><mi>n</mi><mspace linebreak="newline"></mspace><mtext>那么</mtext><mi>φ</mi><mtext>（</mtext><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>n</mi><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mfrac><mn>1</mn><mi>n</mi></mfrac><mo stretchy="false">)</mo><mo>=</mo><mi>n</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">证明题一： \varphi（n) = n - 1，n 为质数\\证明：\varphi（n) = n\prod_{i=1}^k  (1 - \frac{1}{P_i}),P_i为n的质因数\\ 当n为质数时，n的非1质因数为n\\ 那么\varphi（n) = n(1-\frac{1}{n}) = n-1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord cjk_fallback">证明题一：</span><span class="mord mathnormal">φ</span><span class="mord cjk_fallback">（</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">1</span><span class="mord cjk_fallback">，</span><span class="mord mathnormal">n</span><span class="mord cjk_fallback">为质数</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord cjk_fallback">证明：</span><span class="mord mathnormal">φ</span><span class="mord cjk_fallback">（</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:3.1138em;vertical-align:-1.2777em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8361em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∏</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.1574em;vertical-align:-0.836em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord cjk_fallback">为</span><span class="mord mathnormal">n</span><span class="mord cjk_fallback">的质因数</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord cjk_fallback">当</span><span class="mord mathnormal">n</span><span class="mord cjk_fallback">为质数时，</span><span class="mord mathnormal">n</span><span class="mord cjk_fallback">的非</span><span class="mord">1</span><span class="mord cjk_fallback">质因数为</span><span class="mord mathnormal">n</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord cjk_fallback">那么</span><span class="mord mathnormal">φ</span><span class="mord cjk_fallback">（</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.0074em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span></p><p class="katex-block "><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext>证明：当</mtext><mi>m</mi><mo separator="true">,</mo><mi>n</mi><mtext>互质时，令</mtext><msub><mi>P</mi><mn>1</mn></msub><mtext>，</mtext><mo separator="true">⋅</mo><mo separator="true">⋅</mo><mo separator="true">⋅</mo><mtext>，</mtext><msub><mi>P</mi><mi>k</mi></msub><mtext>为</mtext><mi>m</mi><mtext>的所有非</mtext><mn>1</mn><mtext>质因数</mtext><mspace linebreak="newline"></mspace><msub><mi>q</mi><mn>1</mn></msub><mtext>，</mtext><mo separator="true">⋅</mo><mo separator="true">⋅</mo><mo separator="true">⋅</mo><mtext>，</mtext><msub><mi>q</mi><mi>r</mi></msub><mtext>为</mtext><mi>n</mi><mtext>的所有非</mtext><mn>1</mn><mtext>质因数</mtext><mspace linebreak="newline"></mspace><mtext>则</mtext><msub><mi>P</mi><mi>i</mi></msub><mo mathvariant="normal">≠</mo><msub><mi>q</mi><mi>j</mi></msub><mo stretchy="false">(</mo><mi>i</mi><mo>=</mo><mn>1</mn><mtext>，</mtext><mo separator="true">⋅</mo><mo separator="true">⋅</mo><mo separator="true">⋅</mo><mo separator="true">,</mo><mi>k</mi><mo separator="true">,</mo><mi>j</mi><mo>=</mo><mn>1</mn><mo separator="true">,</mo><mo separator="true">⋅</mo><mo separator="true">⋅</mo><mo separator="true">⋅</mo><mo separator="true">,</mo><mi>r</mi><mo stretchy="false">)</mo><mspace linebreak="newline"></mspace><mtext>且</mtext><msub><mi>P</mi><mn>1</mn></msub><mtext>，</mtext><mo separator="true">⋅</mo><mo separator="true">⋅</mo><mo separator="true">⋅</mo><msub><mi>P</mi><mi>k</mi></msub><mo separator="true">,</mo><msub><mi>q</mi><mn>1</mn></msub><mtext>，</mtext><mo separator="true">⋅</mo><mo separator="true">⋅</mo><mo separator="true">⋅</mo><mo separator="true">,</mo><msub><mi>q</mi><mi>r</mi></msub><mtext>为</mtext><mi>m</mi><mi>n</mi><mtext>的所有质因数</mtext><mspace linebreak="newline"></mspace><mtable rowspacing="0.16em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mtable rowspacing="0.25em" columnalign="right left" columnspacing="0em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mtext>则</mtext><mi>φ</mi><mtext>（</mtext><mi>m</mi><mi>n</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mi>m</mi><mi>n</mi><munderover><mo>∏</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>k</mi></munderover><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mfrac><mn>1</mn><msub><mi>P</mi><mi>i</mi></msub></mfrac><mtext>）</mtext><munderover><mo>∏</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>r</mi></munderover><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mfrac><mn>1</mn><msub><mi>q</mi><mi>j</mi></msub></mfrac><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mi>m</mi><munderover><mo>∏</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>k</mi></munderover><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mfrac><mn>1</mn><msub><mi>P</mi><mi>i</mi></msub></mfrac><mo stretchy="false">)</mo><mi>n</mi><munderover><mo>∏</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>r</mi></munderover><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mfrac><mn>1</mn><msub><mi>q</mi><mi>j</mi></msub></mfrac><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mi>φ</mi><mtext>（</mtext><mi>m</mi><mo stretchy="false">)</mo><mi>φ</mi><mtext>（</mtext><mi>n</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mstyle></mtd></mtr></mtable></mrow><annotation encoding="application/x-tex">证明：当m,n互质时，令P_1，···，P_k为m的所有非1质因数\\q_1，···，q_r为n的所有非1质因数\\则P_i\neq q_j(i=1，···,k,j=1,···,r)\\且P_1，···P_k,q_1，···,q_r为mn的所有质因数\\\begin{equation*}\begin{split}          则\varphi（mn)           &amp;=mn\prod_{i=1}^k(1-\frac{1}{P_i}）\prod_{j=1}^r(1-\frac{1}{q_j})\\           &amp;=m\prod_{i=1}^k(1-\frac{1}{P_i})n\prod_{j=1}^r(1-\frac{1}{q_j})\\           &amp;=\varphi（m)\varphi（n)\\\end{split}\end{equation*}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord cjk_fallback">证明：当</span><span class="mord mathnormal">m</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mord cjk_fallback">互质时，令</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord cjk_fallback">，</span><span class="mpunct">⋅⋅⋅</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord cjk_fallback">，</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord cjk_fallback">为</span><span class="mord mathnormal">m</span><span class="mord cjk_fallback">的所有非</span><span class="mord">1</span><span class="mord cjk_fallback">质因数</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord cjk_fallback">，</span><span class="mpunct">⋅⋅⋅</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord cjk_fallback">，</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord cjk_fallback">为</span><span class="mord mathnormal">n</span><span class="mord cjk_fallback">的所有非</span><span class="mord">1</span><span class="mord cjk_fallback">质因数</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord cjk_fallback">则</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mord cjk_fallback">，</span><span class="mpunct">⋅⋅⋅,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mpunct">,⋅⋅⋅,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">)</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord cjk_fallback">且</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord cjk_fallback">，</span><span class="mpunct">⋅⋅⋅</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord cjk_fallback">，</span><span class="mpunct">⋅⋅⋅,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord cjk_fallback">为</span><span class="mord mathnormal">mn</span><span class="mord cjk_fallback">的所有质因数</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:8.5998em;vertical-align:-4.0499em;"></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.5499em;"><span style="top:-6.5499em;"><span class="pstrut" style="height:6.5499em;"></span><span class="mord"><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.5499em;"><span style="top:-6.5499em;"><span class="pstrut" style="height:3.8361em;"></span><span class="mord"><span class="mord cjk_fallback">则</span><span class="mord mathnormal">φ</span><span class="mord cjk_fallback">（</span><span class="mord mathnormal">mn</span><span class="mclose">)</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3.8361em;"></span><span class="mord"></span></span><span style="top:-0.4462em;"><span class="pstrut" style="height:3.8361em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:4.0499em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.5499em;"><span style="top:-6.5499em;"><span class="pstrut" style="height:3.8361em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">mn</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8361em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∏</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord cjk_fallback">）</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∏</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9721em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">)</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3.8361em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8361em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∏</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">)</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∏</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9721em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">)</span></span></span><span style="top:-0.4462em;"><span class="pstrut" style="height:3.8361em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">φ</span><span class="mord cjk_fallback">（</span><span class="mord mathnormal">m</span><span class="mclose">)</span><span class="mord mathnormal">φ</span><span class="mord cjk_fallback">（</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:4.0499em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:4.0499em;"><span></span></span></span></span></span></span></span></span></span></span></span></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p class=&quot;note note-primary&quot;&gt;此文为我在校学习物联网安全课程的笔记~&lt;/p&gt;
&lt;h2 id=&quot;凯撒密码&quot;&gt;凯撒密码&lt;/h2&gt;
&lt;p&gt;凯撒密码是一种古代的加密方式，它是史上第一个广为使用的密码，得名于古罗马军事统帅凯撒。它的基本思想是对明文进行位移，即将</summary>
      
    
    
    
    <category term="学习笔记" scheme="https://blog.jishuqin.cn/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="加密" scheme="https://blog.jishuqin.cn/tags/%E5%8A%A0%E5%AF%86/"/>
    
  </entry>
  
  <entry>
    <title>软考-软件设计师 笔记</title>
    <link href="https://blog.jishuqin.cn/posts/7b4c3d1e/"/>
    <id>https://blog.jishuqin.cn/posts/7b4c3d1e/</id>
    <published>2023-06-08T23:50:00.000Z</published>
    <updated>2025-09-03T08:59:30.030Z</updated>
    
    <content type="html"><![CDATA[<div class="hbe hbe-container" id="hexo-blog-encrypt" data-wpm="抱歉，您输入的密码错误，请检查后重新输入。" data-whm="抱歉, 当前文章不能被校验, 不过您还是可以看看解密后的内容。">  <script id="hbeData" type="hbeData" data-hmacdigest="0662ddc2bcc52aad534aa940a26654cc3218ff5688a0d6a4cab16f95b77fbee2">e48eba3f1997bda7c9fd47f7d866e78f49c1d53689e8e2dd8b2ab8c12c74fbb388c44a9172002c380486c926847acdf4df64278942ada627fa5cebd0318d0f53a573dbe7840ee8fbae8c0fe89deabf5fe913d8b34f4ecda4004edd4142b412ac600eb5a33b12f70a0e5b01e25c245a4bd6983274ba1f01d067361382604ea14be94418e930c0db16ac54dc50968cf05b7f69eeb99dbdf96577937077b92a0c22ac62c5a0b4a1cf6b70f0b83324f42566c3a17782c9db02bbaecd0fb0dd71c1416127666a80290f703b1aec28985b053f1064ca67901fa7a3ef9d4a593feae41dd02d07251ad357f3f2f0f4ca914b589f12809bc6ba298baaaff0cd84fbfad06de2537115a1b2dc49c68222a2fded93567c7a44efddd7b6dd5950dbac13c87812689a22dd5c0333ecfbb6ccb44757c2f9171ef570977d4a9aa2dc64753155646ab5f377e3c16847ba349767c622992581cd2648ef964409f9945cf08662be54267c7e9a040bebf22c315a0d91088fb31a6fcb65135da40ba0c0dbf6ba44096fbed7bfdaf1015ee1f4d5607410894edba9de7ea4ea73b9092f0dd07a885ce496bf391b46fb046ef7c4a214364fcfc5c05856880dfd7017eca188f2e19dc4a30f6c28c31d687e3c1776c556b98448c1dfd5148fa51231b887d42e9b88655380f83145190120943523a8973ac91ead40a3e6b328c0696621e456d9348bfad998f5df0c57101771b861945225cfdce52d4ad09466b0b48dbda21cddf53441723ab40038cab186550ae911d83f84009e443c9e95b3dca4215018b4102a03d9f98f88809f532fe14cd5ee06279de71999cd012be6c924985956645a5c460c8184ba5b675cced87744fed687168aa811c03bd6004eb2bbd1f06cf90ee8cf8f77d13286e982e8fc425ed430a97666aa1d5454c1403976d7972f49b4588a4291c3ff0353fa6cb7eeed4a367e3bb6a8cc82cc052982bd7f32bc63b6ce6b133b9a8c6ace4c333567003e869eefaacfa58bb79129b638cc45065a65dd316166181e67667236b6168bd166baa58ff12ea6f94a4bfe597212c23a6346e0539fe1f955b523d6681b8785432257d8cbdc7a7a2d004a3e871c603f1fb6e460de7ff2e74ef7d3edd1981efe38b0536e9503ec2a19241ee68c796eeebd7e9866cd27546ab4da9be17e5477c510c8cd5079069827c1ce2816b3e5f83253eee9f097bf6cf24049413aa674d482ce8daf857dabe591ef9accebca59d9a17f8d348a9430bf82e540add3c043de5f4347266b10db6d66144a31524130430a66f858053a06133c6187963b42883f4329ca397debc393c548a70d06d3e2d64b653ae8e63771b9a06dbe53a1ec92d81630c19a6684b326c0b243ccbacca6df016ae02dcd34af8bdf71e62945b7a185b190d1124f67f1a1f74caf941cf3e50d4123ca649947c1bd44a97ae0c2201769d9e0a6d4d9103acff1a4506bf041d3806c598e29334adb707b7702c130bd465fed1898d8ed9b3823c87ea4c0660d8990c2ed0138fc61f9d61820aee414805c469783f116ab3a720d367aa773ce1a494764b8d5c4a0c7862382627fe645b53f194b5546ad025dce26a2627e6312e82134aae655c0708d0dfbde4c83627bcde9e1c25612aed44a4d439f5c11f5fa7b5ee859308ee5f76465f70d8c17672368b5a12d359e043925457d5f9f0a6ebfae9423c10b7d38f5a4a50820348fc59738156aef0ec64d8b9a4227132bb382940b28dcddeb8ed4528253c119748277e891a1bee3049c89e230654ccceb6a0ae260f1b9a07fc09ac645d8f7902b0df2613c51fdeebef46b7f5da369a768468dc3c204580a88763e3bf5fc61992459727337abdf6c2d701e9ad2f8cd9111a8627266485f11e904aced5f4ae7390d3288247c670ebc4f09eda8ce01f394a106680dc6d8064883eb01ed9afb648dd8091e5c475e41f4dcd487e36022a45c994f5dda7fd43ed61fcaddca641b3fa11cc2252f93db0bd420d54aeb22268a5f3348efd966b76fe0434e4ee3621c879bd535874dadca7e15f78009758a59c699afe6cbe65a70961cc3ffe4a83d87b3514e03a924a7374a5293afec8c96ec5423fd29080ef3528d628efcb603b8dcb82e9f375ec356943224c0efd904f21acc4c1c46d95fb2e888c2ed1949d7b723fcb702e5f49ba1fccbc2e5a5092fa5eec7ddf15d987240deaa8a1877aa8d5ad567d3de5e3fb2c1797520b9e0784210c67d7e10b37937ebb47c5ff9058a79599aaf34e3ad69344990370185ec9b6bbff64eacdbfa2ef9a99441ebb6995778c2880b721be3996794e64a926bb0e5c22e092278a8a07f9be6f3387a9bdcfd16b2330d3589df82eb168d46ca3d0b6f8c7fb1a8465d5007dc1e826af290350a05628c36b354513d400f4801b67d30ff4e26c11fc34c8acc1985f4a36a41489d70dcb8c28f217c079d3695cd307b384091a284b201f2333b7b483a3e561a5a2b073116b0f974a8e00a460ab6fb879c6c65e3fae42aaf052e4797bc60d81c44000737d6f3030c6de7183ba3da0828c5974f04c227f8bb108b270a374bfd2bec72c425ef6e686467a3de3548a6532ea315d6d42b6239099cd3c17e02b8cc2d2d625515e00661a2e9da0271b823143d835e4c8d9b7a5fb89436c7dd0b90047296eb761cfbb66464cfc007e4cccb0b8ef1272d534a8d539d910f5ac2e95337723df3f39e39127bb10c0aa8f623fb1eadbfcf7456d49589a63cae00c38724ea718726f4fc98cb66c1042d8cf1b88f7aeb13853f963c3d953bdb0556a0e8442bba9dc4ac62e52705a49a1f727049ceae66a8583a51f5c835ffdea679b5bf16d2ae31a2781738d6962aabf8a3c0750362b20c383247e88220ad21d2e4483d6f416f52519e91331a8e475358efb0d375d3f4c1891544096deacb3c175656f062b69a20e5d33bbeedae6df904f09ce7cbd44f1bed02f98bb76aa168bf44716b826e380d727ca59ecc8fdf35b1fd3168fbab023fcaa3a1015fd13ae0e101efed10927f4c253acc13f46f463427bd35f09a6af44904ff0fa8407216224cdde577c1fff3e61ec531a92632c39142698d3a30bcc4b0181100bfe28c2dd4309647751c0ac33a553764720e16780d2ec9daa463935b6573e11de3d2ee4ca998421f548716bcd40258ed66ef7774593dc97448656c8a91f199f7cf15b6b381ebc4959a0f7707f12d281acdd4f500bcc11582ef2f035a771590a4c1b79bc666146a1b7bed6c4fc93453003ad4fa6f2e8c0c33baee7e760c744c0ba14c8429c96f918f89a7d83341c3be6856449668d4e0ccca14ef326385448550751dff1a62d5234590ecd1057daa991bde2814e47e01dc584ce9818dd4605b93344559e2d4b212527b14887aef9dfe7a43b4c2909de83f3ecae6317e25ae5d18d8e9d28a9dc7ee7639ec19dbf37f8dfe997684f3e75f8cfe2429374313bf8030ab4dcc488b8f4f1f29dc958b7aac0e1747a817da388f6fe3aaa68e19f42d18b2dea1ee6ba0b7bdf95f819496c42659b6a3371d6767a13ae38b97823d06331a269265b103b376254bb551fb1bcbc550c0c5267b2f1bda7ad4d2417d17d583299f56d3f354bd569e949c7e8070d3d646f1df7067312165897c68999ea96b53cb693033f4cb0e01ea21769e138ca374ece278d713a988bfcc11ba50ab29fb520cde5362ef9015f1087993a504dba876c78d1131b6bf46ec36144ab2b911fc7b684c82bc1fb4d37a87dfbe26dfed0fe588ed9f7082ac3dabe856b725604bfda484c800b1929689eb5c6609e989eddd05fc202904d480fed119a2ddba4775e86d6b41ed39778f5bd687b612baa49ca475e1f407a9f2373bb7b3956cc5999d8e8faa814a637e102e2312d6ac072bd948cf5736db529eca3064634c658885f42a056ab6e3414667923a1b997c0e949b19332874f89f033ed1393d14af3dfc16c1038e6402fc9d3f9b011a1d75d8ed4fd069b6928607afe02fec4dba7fcf0165e5595db6f67fff7f0e1fe3981d9f7d498d96e70acb86c046d0ee8cb9360b5921638145edda7adcadb80a815f343e51bfa2866d68ff3cb88d2791f46958ec8789149d834d2da383e25d80a53dbc81cec7f52939234c2f726673bebfddfce6fd3f3a10a7373db87648601f58db8da28a30c57ae9ee48f8706ba86465fd9f7791a4e7d2986c39859ef4044f5c75d281bfa20107f0f4fb24db0e1336f30e7e2a4a1f1cfdc7f3b13e150d31ebee3a577f30b134130a7eefbf39c9cb3ccc2419c7884e92b75f7039ea72f5e5f122131694e4f042e8d105f5df49293a97f44ac12decd061ea691983a96adefb73d57a558f547cd769e97c6ae81937f13f4b02498bccca6e9fb590a4157c91b191bb8568c66df27b5ddffe7ff86eff5285df1992cdda68e4f99b18001a0456c8ecdb07dc14b74f0b6328e4c849b6e624a932b65031ebe61ca820e668bc8b64d9a3a611aaf8a512482efe7440d0a43773e7e510ec54a3dc5ec7c2355195c31cc24e5d67ccec013df2a2fe927ef90bcfcbd81813b31e4501101fe86e704a540106e39f14f63c272add9d57302a5bfca2de236564737d0e504bff0cbbc9181cf52a61675c209993dd74e438ac5694687b51b0b99afddad38d683a80c10382050b6e62b25021739a19bd990eb9f1f9b8f0d024ccbb903d2bb664d82c0eefabb0bc08e93081dd5b33338fa2942e24362f487539d623c79b8e16768e6efe1813ad9aa5e723e40cc94cefc60914df966014518660aa5abbe4db28c254c188f38be8cdb39f0d5e12c6c7c281fb627f45e95ff72226672ea2ed5ec4a712d9a75f99917a7cf9e8c4f317a81490b2ee7ff9d83ad2c10d55090204e55f3cabcaa50b91b2860ce4ad0da044400c22295a8d8c64b8003bbc0940902f48d427eb8eace50815807b2f04c0d0ed694c9a71389a7911b01ba71e99c026c135a63d6b5d583f7846695f46ebc4a5d70dad80cffb362f54eaa64a2a61e76fea1a205d57492febc5b53e11bef30c22c43f662fb3e10c3c483e613f18b2f7a3d585981f0f47a09e68c6a589caef15cf765d75aa4e09b3cf64ebe3e382292c2ff8b01bb400ceff4732ddd22274ddfeedbce83ce4fef8afe5e0175680825bdf35fc2a99990e92a8752b0f82048fe087f813c0b839f1120e748f1a3fb39e801345644622163fa731e0d7597e7e540d031a8952fd4f13b9b87339ef3bac54b638f59f1802642a541b8722066d930af2f0655472e5c00c75007a40ba80c21e533011695521e56ecd6e727d0f98e42d95697776e8c6cadf14e4fc9c32d68daaac1b92bbb1e05b493f326b392ec88d7aceedcef70bddab7c6974191e58675d4dbfc43f78d696a6daa57a27a6b2ce2a95a5bcdbf8dab15b3d1c9095110a5e6aa5be1c1589e37a600b23018ec1db1d906eb9c251fb087dceaf7c039db14c56ee1e53aae0bca7a1537352f19b7efa4f56c3f779817b34fd4a58edcc0127c182e1d968bd8394fbf7244c8fa2537bef245c18299add6d43074555d11b56d18caa540e0887ec1d034c94cd09aa60dc2523e7be8b3ec9edcd188fb533b3a5deb4906ba3acbf90d9b0a779182c4415306086663f95808bc0c2057f3248b959ef58246dac0fefbe5f1973d8f377d463b6f3862b222a309ef03670403249276ae852ab1eaa0ce631fffd71ecac9a7d502b2ff2ea1d1a36f9b05c4fcc07c6a353642d4ac343bf1142b34397a23690936f3b48b272655998ef7bdb695a0ff0555bf8594f0a20cb9d5aac6e50cadbfe087f87b29f2fc7d0cbd17ddf9a3e880e72d222b8601fca40865d23720128867b75040e188fe1264b270ad19fc529dd516cb191f13d77bd468a91f7f969eec299febfed01af3ba7d9656dc266d859a8da72a7951d889b604e6797a43234df0822b70ee4fb08d7828849774cacc0bf278ce25fba819798bd40447a287437d1254476d394fca4b167ade0512db4b9555d9bb355479ce9b2829e7eec4ebc0c43219d7db4a9c3d3650838e63a3f67a9693bbb04bd65d74c2d9d374bf08ffe77ca3a1f6b8ec84a163ea60ce6dad0497002ea07eff4000248f6c4bbf5697ceecaaf9a366b12f706e971099f6f43115cb449940793692fa137219d3bd59dcba878adcf1eb8d8e166e09c45cb38b7f116cd63014bc29159011adbbc4180c303b7539c8a6f0106d4f4abae655bf9c9682b57d6a2cabdc754738b9d35fa202f3c307733f7b447c91bc9d500760275a233d7775428d6dd69b9efa4e0418ae48075af95c42acea32ca07c1c56c6c91f949c5e61028863077e9320d4ca203042aa9ff7e99a8a4f44f0ca610ac925be31651e1a0c8f5b2196dea88804ddba121941afd01bdd0afee2ec555ec4692e2b189e3c8e734175d62f67f98667074b629a70083ac17ba6b33e6713faa2e93ea74792771213a06fc6b2f41e95ab659ecb39c11bd86c5b4ebd6e4badbe6ebb5c179408a51733757a524019eaa19b2bf63d6c468dc0515669d7785e87d40045d56ba9ff7b5aded1f66a94b57034ac85e7c3ceaed544ec151c84619da4b7238a38dd9eab76442a003c61211b98186ae294097c5c883eccd715191a742a41d163e082b3e9a0715a5d125c379836970fbda83c1432413c1fa41c2de0f8165a30e0b0cc6a47158f99787d455e7a915e287fee75954c0c5e5b648616bb5cf5c950251d3627de8af3700ac578ee4f1807455c3f06d8d5dd9abd565204ea63b73996b4c535eb4711e173445bb92546d1ac1697611d314b54f54e6aa4a029b63fb2fdb724e6662f03c1a4dc8a405b24dffe8d5537b3992e8f53ca7724ef6bcc4a9e6574995bd83614e6ca0535d725ab816681fba8fba37be0623102f86ba68ffb2d083aa0ec504ac7530c9b3b9ea9a84b2f30e357165c43457b7ee20bc7f8ca3e1e2a5dc7df717f036b83c48c23d7e898389e64db9552a3002da5a3db6970523f85a86ba4e0c3fa08f3442a5838f879c41b8eeb30b9b40bccac6c3fc35c3662f94aa5fa12e4758720c003740158695468ed8c7fa041909246d9b097fd6b41425d871654113db7ac6a9267a044a33a1a850ce78cea5e1b8cf12c99558343b058e2b99e5cd6bb6d529471bffcb464127f988ddcf86aa936138df9c7a73ddaff5b2ce8198cf77ae47c64a860f49c62056808d876801b0fd1fb530c39c4f80881ac9a4e20c8dc083db6569250ed38a233dcad5a9460ac18fb9ec6610732570127032d76954c9ac95d7aa0e3e0a827bec8ddeb1839e3258016cebd31d9f9121b2aa39972f8ad4af778c035c331fde995e164c543fcc1fe39bb801ea4b26ef6b6669d022ec08082c61726c1044b68a1821f4a97b6fb5ebe481f51a7481ac3459543f1ee80d3d0066fbbb973f1d4acccf36736926df212cdf08e05be86f291285f735739d1ebbfd2275989eab00aea75643967fb4a225417d1c7c66e1a31fe58ba1617bf721fe5c31bf5bdb59174882d40631edb80d588b6357ca287b7421188512a50eb4da0db8b4685858d1eb66005f445865a933367f2fa49efea12d8dc99f4670f9a6d43f98a789b8e11affbc91f4ceb11c4da1f0c8ec917eca31f39ab500e8d38d0ae13a2149eacf6cca732211b67e988e25f456ff5b45dc39285ff86731a73a499309271a8a4d0211406a2ed501ba1b4e201f560bfc03abfa41b946294193fd18d134b448c08c6e6ea22beb1fe062c1d0fca1cf2cf982659b3c35264402f33caa088b4e92a8d389e65997242c48cc7d2be27a8d8ac7b8c5996b0d028e190e70a7a51d4c9dc629f79a847bf86ee70c675a1ce1f2d23731e98673f0cd779b9314ce8351d7a464515fb98a0f08d7a09f7890e6e7db42c00f5e8d669c462fb201838917cee9eaa4c5b24911e253a18c54704fd4ed700112dbb407f6bba1e8c02c00f41bbfb103d7eeaf0da76f38a4b5f6415faa8bd1b82e5d168bc74e645a8e1187cbd67c0cef5b3f07d640c4c41ff98184cfe4530b331a33aabcd09d9fdff55cd4176c3c105b5dcf270993fb682f9d4a9352626215cfc44d05b0a7ab480b879ac6f742ff52be9c7e1014c937c30ac52b849183199a1968697fc5e847def6f97e1279dab0db56072442c6ef0b4cb7b24533ec430981e8cddb3d21bd6aaeff3f325bce36ed5c511f002df6e99fc492bdbe4634eed107d525a687039d0cc6a30237e5d04946cfc7024614370221bb666d0b095d78c9aadfec10402b4d86614b693f1ca91ab1da68cae3299f1f8af61dc693aec941cb9fbd5aa3a2ddcd7e16d68579ea9c4af6d8df76fdf2a7d5ad429f57a433db7df09fd214f5a566f55896e30892256688dbd6163c16f486f1887def46db51db94a4bc05c8edf9fcdd7458979559d49df0a6cd98ec06a10a50ae6071d38a420b862921090896713f8d83a9188d8181e14343560ce008ec8064b658dac75dd3f580f667d49c9d1d09e81664a889632919ada9b94158703f5a3ab7442a18772e75ec726c6c389fbe1c7c74c3ab121b8015f86c810498c0b35bfd6fb0615048bf97dd6d411ce8736f50ff94dd6f7715591a1c63ed1a0f03f616ae91b6b0e15fd7fbd5ff150c8b2ada1ef6b60c6449a7824affaed45fc87e1bb8c41e397996c888bcf368290ad39f49c0e2552401d8501858d85ed75eb6c9fad24f797916b37d5eee9838688f81d8f3a05ad77fb2a6dba26efd962271254249dd6c5e0b36e89b0fdd699445581dec6df4e33b0b8ce3148b8c9f50d7eeafd3057b594910b6878cc9ad86a0b23464256d2372d5ed0107db89449710997f95e0b9f8be790e3a10c481f15378d959d5557b9a81cc8f3d1e33000971adaa9cbaebda34fd712cb130cf063d7a0477bcbd0f03940033880e7fb32974a927bb795f129b25d046d81494096110fb60d06a26ca40a9c039c9d87cbd262975daf1335f6c72272ddf0f2b0e23e789e8e9bb57b0b5bc63525ef83d1822dc2c9756a6adb64f271a9d85b95076faa9232eba611b64f5da19b5fc6fe558c2dae7c2df09e46a53d9c6055ea9d2a7cc993caebe87dcd3f47da05abfbffff5c6d3777122e1a8393385d4e367f872ee83e32961b7083fa08a7be44b4e18d9a8c7b94f6029daee8be5fbc01be1e0efc4b02ca99cc2afdc78d1cd201216a771518e0de7cf5de898cf26424de0a2cd47b5f7443bee0ec6f01455751e3f8ae955ffb56d6be98c3e171772f0d886124af6b716e6feae4fccead97b18a01e850966250a07593dc28e594b695ad5bb0e9cdff41087de0cfc531de67a401c9856687f7af4383e4b8fed5a1e1436feb67ed8b54b6e75fcf8bbee31f93f594fa2b60088dd8162cfd0fdbcff981949979d0417da83583826ff91008c8ca8fe6961e742c5d1c77291626ae850d1d75de1968377c2386d4acc7e79e995573e75b92cf8db43e912c9a02a7f884339ffd94753d69b1b58ec20a0c19be747247d990545aea1d0a3f2383160e0fb48f000a87d07045795ef373f54fd1dbb8162831d3c6ecfe6f993224600aa752fd55ae35a4adddd9573c99f309f4931c1e6968e87e5efa31fc872fc1b1ecf5dc0f458fb95828cedf0c4e6bbb5f51de0a461600fa746b36e32572f233e169d096c135f65ac185163b364a9b7600095a77661eaa7c611bd1c0cc5193e1cadd4ddbecc0c937d0922b3c2e886e5152128015f99780c7423fe0a3a3234ff69aebae72c52c35b7a31c7320736ee75a5dda2f72e5269db590e2ab944699bab5ad5c6dcac3767584f7d4e493e83bb2def0d73f34b95d9ad9fc4fb8771dc74f3ea2a0af53cf62b2e10d1fe2809aac27d19120b842e17648ad2bbc4fd3f141c11d1770cfe5ee5b25557470b453409b2a62acaec66d6751fac5bb98050664352019db6d7bdc956f1e6da3561561790522b482e0c5a612969504a92d16df80e816ada677e730f4b5b46b9e122a73431a2e7d7cdf4672b489f8036967979d2b1d6df37f0a341418fdaf4a3ce9489f5909d63dad6de4030c45ff0584d3e2566ccb271edd4e70c96513869bfba32cd70500f624b58209724e94123788570972afe76bb6b47a025d4eb57d7eb3dc607f7d7398a63fca0a89e315c9b850d176fafdffd7b321c5b078a4dcf4d51593246ccddf6868f8ceee5286905b11c5eab5f1a0c2cfab78429721169a44e8a621286c689dcedb61f4afc5a61b88417703d56e52ecafa59d0b8a05e138497dea80dc85fe65562df810c82a96034b1e205d69f432a3356b4e980f2ebe0bdb0cdfac6ed66fa64139b2b64ae0ad6c741831b1886702db74036d3471bc1d159c2504702afcfde606afa38905af8338d3869779f02c096201fd09b5a313069194d2ef277d2d0270c7b5154d00af4064d2653888248200557f87f0040f860da3cf1b218192e05fc7c966022baa89c47805c20d725bb421a6924e25cd0a23ad2dd02737ccbd862359e6b4cbb79fd67551ba1c1c7b42a991f04499a706fa6855b7c7007b1c29bfd4a1a9239f1805731f427165c5633062681dd4494360941d1c14cc8e4cf355949e6811979d13907f443ed9cfe9b4fc0df54f1ecdbd30c11f8e64fd1deb4bf45270ac8712a868517a61c8d77026f0e3ad3513db304b1cf1daf739e4f9c00ab83bb7a596bb42e266e992cc7edeaa65d7670d58eee93d5e058eb355f1ff02f6c37bda0bee399cebd16d82cc86ec987e81641c07cbaf28d54b280db6c75424e138d3430c7088da93f30e9d70ea98c7da35eb57cc39cc6cf2fef19c9903af831f87b0af2b72c9b88c953587517f1b60211625ede6c14b6aa64b796aa6e7819d4deaea76928e35fbc247b06f1153e40e7be6ee9261985d387eb4f08d096af0f04e997d60d407cb63c5fa3b5d1a2ef66a4cb27721f5578504f08ad96f0014bddb606fc7d7d2dbd71810c0fc933c5cba320a9693e956dd41695f12ca768b3b0f5245feafa66498d8c7845e83e864ac699abb6f2e20a830319fd08d63e784739d4c88395e8052e01b7adcdb45388fb59d6037d88b555e22150a59d49b8515ad89f089aa0b8ff875e588224dce128cca5648b3ff0eff9af6f7ae886a4f3ffc32d9821812ac9ea1ab6971e27c9a675f46fbd862c5e6fc959e4e0290db57cdcc78f547f8d1668ceac49a492c53e4b8c57298aac1f36fdf1c52598ece5647da251d08d4483c9f5e8e60d19bd30a74d37603a40969b62e9d47593c3cb8369de085bf519f5933b7d348e8fa07d86fed456dc245b508b841cbe235045f73a71e00764ceffc44ae5785299b17caba4020a52091537f67174755a27b901572d434c5aad52b4aa348db57ec4416338caa96d4f54690b02a03dd5d451be3841b351f740d11dcadb677de14ec39460c5c8d0c8f9bbb52097ac07f509690f2fbb33ede9208f7d1ad67981c58074b94500b3cebc4965a3930f5ed941f2da6646a303509d106dc1a9ff406aac388b700b7b26d1dced753b0f2cfe47eb9b969bc900a9469b76545e3d5ec9b8ed7e432082c406fd8f9bee6ec09f7b3d43c54e054c3aaf5656f334421a8a4d7724afa04197847014a56bc7220dc10853fddfbc6decb114204eb7a918cb7d47f1b9e55d4c6b6d6bb890d7f92100dffca3f11bfb5bf3621234cac1d2fd300f2097b0f6787c5e40d64fe105b59539815a713cda2c13cde60812b21dec5ff3fb352af9f4ef52ad428be734710788bc2de1fc661840d28105809c609e7fb019ae38fd0de9173e128acf4bc5f0301589efc7042ad68c83a5183993d28897b790968e65b0cfbab97fd788e06e7c70fbb56b722f529c765d3d3b0ac0e78242c762d17961af01e1a19273fd3e12808073bdafc9713009a72d3e434f87dd45ad718fbe224b349c971238e3b032e62d439d00c06952c4f5a940457ade24c727ee1642e82bf0793124e6da551907d3ea5aadc17fd82bab21e7b5a613ff1d9e2f0cc01d25fb60d902c0bc3bd2dc572726b438888862079e1106654a33375a3fba7a5302985ff56b8cd8eb553ed05d6d255da0e60644a0c988e334770e7aca23dcbc4aab5acafb0b7bc02f5ff16cbaee13b50f0330e3d94cb334c340e98b60729ac930e3c7e25f3e382ad30cd29d0a318eee409a94aca26a364d959c759ca1a1f78e6eb64cda86b9172252421b04b086b237067ed5a76d3a80d3af16fe88a00baea5873f350239d54ca9b5238ad86c9f54dfd717dc0e6a8f124d397af9226b253ed64d714273c06233ae08ccbd523b3d58e72bce6f429b09c3847d6f9977ca480e15c6d16cdbcff19182402330ba3a67648ade1b8908c31bc33ef81dcf8d98e4ca3c6a1d4051e4c062ce236cb66e60cb2f935d4aea3d2a8f3a3f568540b47c1272ddb2dcb22a8b43fe94c232a5faa83024eaeccdfc69dff2119b795090808dd256519f38db2defaaf5e56409f53c352d7b1efd4417e83ca8500dc9313e329e7234d8bdce97d21845299bd6300c2c1149ffe9d59705b1bd3aee54d8960e4b9efc218be389f4d48afa8a0f7eda21bd2641cec1f5d1ef54dffcb2ef8bebbed8b4b4f9fd73c0a61fe8b54cfdda80d35aaef08fb6bb5e56c7e7010caac949b654a3f0d2587a28723f92cb13e94f9d2466942ef21c837a01147d7e236c4733ebb4027da300501a1754a34f4887b8b8059ca19579ca2d5590ebd05d1e19a6182be77c72a88378dc6d8b2037ad10a007943a698ef4714ca2f6e7877426a0ef7fd54435f57234fbcd89552a68a66fbf5d8967c59cd3ce7bceaf929c5b40c463615b205c9866cbf9967c6acb9b0e1a80cd2ef10971209167967402f0aabbdcc1604509f48ab594bc0336901c7ffbc2e571bf33e5b1e529d843a5e3dddd530e97aa8de60c292c4e405db85e79aa2de61175d783ce29f18055e75646b862b8ec5d3c539d5ac56a3667f4d87de03d55b1517959f69faee64ed2c2d4c55b402be94f02334bdbb4095f9c8f004fa5fd326a5110d332f179ae7e968fb228273a49d3f165a3a6893313778e1ffd0bd89f4e500594b47649093d6f88eb028f83a770bebee08b32a6f0b270d8799ae80d911838bc3ee72a2c5e71241e9331c546d45f8dd69cd1d6ec7fdf1ce565aea17f303d59ebf3bd3ba1839cdae03fc3927afd92d6c61a2e28cda3dddcaec3a774fe307253be2ec055cfb42cc202614d56b6c926f88662449c54c1f2303b66af9643c89bf4b06e1b1d1f4863a3eb2ac293169e5aba598dc56db9510a7ad6c7180ddbc7bba9b4e3963537fe368dd8ef8cf5456bed8ec6fc8b9d3166092409e1b0b98c368516399bbfcd9908014915326ce72915674a0301c3b72a85819a3852eaedaec838f3e18b04fedeaafe2772dd1ee8e37f926c5baec6233e23c5cae91d73d470bd8b8203da2d503534216b3c3ad340c0a38ceedea6a47935f986c138d828e8233f7a4e2dcb815d7dc62109736c806171969ca6759a20876a43e7200a44fff4f8a3d44824a57fb12472767374d110a24062e05b416ea31aac7b6ce415ea33a337872a9e5a2b14febf44bffcbbb0ac13a315ee8f0a450ebe0f777c8fd46e32f7393ec154b8a4d343cb6e653fbcc5aa5211ddca932de892cdb27ac5b2ded9a365c34c7e15c33e86f27243330fc8cea1dbbc52dd531f13a482d41ddd133cb31788fc9d63c513fd73c1b8bffb444b30e44e329a3b84620ab56d47b4ff28042b28b69bd1a0a48f78abbf9996c667688195493ef407f4804bbbf05e4d0a53d5439416e2801d1aacf529640be710bf48d8435c9bb86a0dc73efde67bb57f06ccd9cfb977e96d9bcd3883466b8ce4f527b3e68dadb04542cc360c68dbd657b8336aa033de8ed7956a515fad398f042bbe816420a5b0eab62be940953a10308fa830e4567b8cde89876283aa3b3be60d47a31542058f504f124ba1489a3265e9bec3944f2664397ea0d01116e3ea3d1eba7558e6ac0df60fad780cbe16720508999b4a1091c7ef28af8121f5936fb11c1ffb227991c707481ed64fee898ec40b00351df4c435710d6c02b14f92d84dd4fd9702f6e67b8e63e7f4b963e128228dae5d087ccb4b051745ca074c762dfb8608a8a963f5c5d783a85610c6ecadab7f2845949b1b917bf658a826a52aeb619383a9319d2764e0f26efb06502af9ab248b5bd159587a9a100c2b26dcfedb54276d18c74751ea98599912e21ed29f0b8bce3e4b36f33feb424aca1ec309574218afd1df941010e4a97c8eb698c3c94fda34f0640a71ac0a63a327e8fe4bbb93df05b7cb50bfa3295b37ab9007da437354dc3aaa3bd6a2ab0adfd231bb4ad1b744b132eb821394725dbc1bdeaef5417e2a0a5a2805c7bb313c408930ca55688166db2e57a6c4328a6f67f0bea288c5e948a3f8e991410b5b5e39e803e8df813279176bbc4aec056a93fb5ffad383ae8101eb886a45fe0bcd738c049a1cc0636c64ed7c09a782fb5421cb6b1b6c064de3682cc15cba8814fc0aa20c16a8750e52c905f41ef9f6d90178d9d3077893b070c3b717647dfd1c107d56ceabe85622ac226afd3083a53ad04537fec3b81265d9400bed2f8c5bbc87cd94fc2b6548e5657ff4418dd6b1042d9d8f1a5efe2224ce1610adc52a3f6005f6f4bb92b35a77e75419405307d4e8a2cfcb1b0bed3a399d64812f52d406df7d0233cd526cb9d7b7273ac5b553eb960055dc4e23f4d3c46a8a959ff00ba5bf375601f89dc05545a822e4f6dccf000b655380b582ed5c68ffaa4f496c5a8f2417b0ac5569235bdce0aebc14cb07ee06c37894ba52a0a61fdad23b4b3ff1e5ef8eb0139144fa1bfbb7e1b765d58f8288e5ee0b1b3af1a4f8aa2690d09def7ae756a72cb1185d10bfd01c45be90642f41704e338f414fa40b7eee393b3bbcd9122ca01863e778f22630ead1a08ca7a8b428d9364a4d119f42d4691075233b3e0133be3393ff2c8864d99bee016ce46a79e78718dfe7fd35cb081ab8b008e369783027134c70ae22808c4c414241f4a6d2009710d022769102db916717f9ed0129f96dc2a90d850d2526de6f8abd8358b9ef078b5563c4f10c8711b96c7691a55adc7281f831284ca2c4055b0ad645761a97f27d0e860817e1e5e3f03fd2060f468d9d09f607d03adae6d47c09a1ee57f0ee9733268073565e794a47f45d99c90803f38383f2496ade82dceb2b7de8447f9344ddf3d13f5fd92c1a963906b0f5446af481cd2b342e4d39da9b061714573aa8a4522d73549e3d75eaf9684a48d7562b68772256dfda8f238e0a0c2fc193e2f508ea837f2f625fdcd39e5a5732cb8aec0a7e700bd0fc7faa4e7123561f04cb5f43909ef0f0f6cfd1ef1fd59afd5da6a9cde99dee710545fcfb89b3b9c1f5bb5f8d828a983c3ddd7fd071d5c039710d1a76a1684c6902fa978c5ff5d5d18db00dda1cd051c0070f9e9d6fbe059c707fe8b48f3e65872c8544afe900d6efc3db645b71e47f23723f6193e5c391e208aa96bd37481191f0c45289a4a78ce204a8b1b9ea04530825273809742eb1cdb69be29ebe6228f606204a78629da688359475099ae5c2ed68af23c7c22480908df26d819b6c211ad53a96ddd3522552b32968472135a2635360d2e75f464487aa33abac68a0b1bdd02c835cf9ad163427c68cf1cabe535809d61b013a8a5bfae5901aa5d42dcf394fccb026c2f9862156edad3ad64c2b978e0828079da9876bad93723e268bbbae65e340275383577d90296242249b23a75467a72fd7966c11228b5296b3513f0d2ada79e239d1752f20d03ed836416b9242613ac9d17ba4d12adc69aab151aa2a3ecbb4c491f6e85b2ef98e93fcd82c4f79e217a78b29745c46a3315d4bc131c580e767f2ea009fd7bc82f7ba7989851ae66458637cfd84757c1c20bdb48fbd7ed8787c89e8d6b492be3fc21761454d41017db3fbbb2892cde5655363676556d18f866610f385d8f3d6fc44df05aca2e0bd80d2e68962b55fe1daa60b8740b8d3aab21d0cc825196c9b99bc07fc1b7d856dad8772660d1a524da6aa8762c141eff11323eb604ebc7ae7b309043121e0c7eb96416a3e93a0899b10abd92cec605c273f1f65c9bb2ae3e3cebb8b040aa9ea42843095614487ded5fb57f8532ab1aafdf6605ba35e40d875c1653c31638bbe64844c57edf54b613ed15699021ec947a8b83849b43cb33e94e0da327f42e653b4c7cce206fadc2af0bc1252186140e8ca53ef60e26564e94d11ab3677f4569b4f59cf54b75b3ba0b3eeab8526289b29dc5072f9a6875c19489457e3172258e675f9e1d83378fad405525fe11cdc977091e3fd8dba702bad1aedd8d01d62500e645fdbf79e7d3b3f0d3f9b84cbee1fde52e6be53e01ebca2cd6aaeb706e5c91b74daf2de0bfcac9cbde014aa89c1ada53e9745320d3f4935ce6915d44cd090815a565867553cef46df4f326dc27649e993e468725b904418472688056d98b5735ab08f92a279af2839ec16dbebf4066b6b6c56adcc135029abfc64131cca1c57b33aabc1f0c538614d0088fd287f92f48b558e0ac0f993919453e2a3584b3da49ef20b100282ffaeffc2ec1c8f6fd59382da11c36394b34a68159a927eb642e3b0cdc5dd48e58ebfa7226447748a2c169390ad64bfe4c2b65b620bba0ba6318b896e784c39030325e6d8e22746ac3aabb74e3869efd615294bec479d53e0d4d70c8eb6db49fff25b06e8d8977fb5bd98bb23f7726b792a3d895bc32954b2434f958cc3978d6d9f6f1b19fd29189bcfeeb8192af9e1f200a83b5e8d8b722294ae07e0b96c464e47c0cd0a0032ab2c2d16188a2926d1ca53909496b6fafe5e26affd675b1f96e048accbf2f7e78e804432853b680e6a96182f7c9577b2c144c1ca041a8895aac36e374a79857882a918c38c755c19a4a4695730aea728c7d63e930c03dde5baa32e13c344364b226635ae38e93adb535ff4e2613d1fe7fbd889b37780c262d7287b48db1f7cd07a9436d4d0abbba50cdee7ff07b912ba7164a1c8221ae21e2d7b1af9360c05dd75127298d3c3a8f3f70211fb811859ff5292a9130f671055a9c110f7c4b1f1eb5e74595ba6ef018d2805c0642913ad0dd9f56fe220edb2309bf1ebfdf8727a765ddd017b7501ac18a9ed01f853b49c623644ed37195aa86c19cb03ea266d4953a4210bf2cad0a4f20639a6fd7f61d35156c8a6cd3094b05c9a0ba8a1a20ce0344d2cd36a9ab65459aa716b21f96c8b8168b4088a4f0b84b91d40430d85388a40f45b480a364dc59a22424824eb411e41af0176e6d5ef308da384c25d0398c04d48d840e99396326c2bf6bbe2060a90a9e470a9e6162738dfa36aefe9fee3d9ab52e6192c5b3754301d69a32b59486092fe547c685472ee26d1c7744440dd9cdbf9f6d225abdfa19359995ba5a50d5a3b5d4dc76ae9308e4f65eeef76002ca3292075a214e61361e5e435624e070d70c14916ea3421dfc2af5b5013a78fc73da85d74be8320ce0c8d812d01c208647f2772c6ec8e2a394be958a0eacec9c3ce6d875ca111ef7874b5e3e52d70caefc47f1f138246933e926599acde6c72e63823012068bb05d9b3d256661b5d6d10632ff31c7e87d37850eddd3984d2a6920c590ad445935bc169f244e26128e69e402197000ceeea2e339756d0fe21ae66f2d9592f5fa5c4c160933e118c150a99ce52ec92a61042eee653c4cfe9e0dd26f0c2bdaa03e3d485f4cce00dbe572232bf65d87f149ff59998d2ac74351b2580aa18ba453a61b90531628f1038f7a782c4bbec362a43441407545a7b23865ce3293cf0400ee3bf8cfe0dd9bedb42e9be7f1755ac75b54ed01f1d0e2acfdb9488e36fe4b960a8f92ae463ce2f9b0c6daf8592fa71c2ae9f0ef11d9b0b8e3df7a36e43bd6039cf12d22107093d90939de8753d8e4de996b7bc5a43793320c720cd1e4d8abec8dfbf0e8b5b3b0fd1aff3e6c74ea11e4a958afc4edc8ded420093fabd20643c1d29df119f8053da352e7fe0afb7fa3e4835a7a6a131d66d1ff81c1d5a9760926e89d4eebceb82fc7b98ee708449bc8120031d4fa56822476692053ac1239ffca2739d988677e3234a6962e521000734f02eb81ac39368ce82676a4effe37386b99d9ad0653d584a67398c276789e1494892cb717083ee8e1613c1875a16db7b3692ca0d4fd74d878d7f3b4e7cb9e8ce38ce0c2ba285d85eda5231322529994a4f98460cb62cec11a05c8ac01e177a2da879ed7f1556a217b50e32972c5feb18384f7811ae7733fd4bc0f570272e360b83d6436c6f1d6a321c5318e72f4a2511404749a45af0ae3acc640953740bd93b481ac0e8e75b56b982f44f53abd546e4ee51229d7c7f27a4ec9d71b4aad1d133b3480fd6e70ac991f40d259c503270b3f9a788a45fe602e1257d6d6ae7c5d27c2729ca64aec0cf4664e99611055b76f98b424f35df94d820a908904d75ac3cc067810c822d51a975159b69f25bf4dcdc0faf683eec0abc9b0298471a6860c902383a940601442ac59883ed177c1d6c2b2dbdfa25333067d802133a20c66c39b0d0508a36c77fe2df7ce71adfd1e9a9b508976cf01539b3a6bb94294005efc92004002016cef5af3059cc87c5b9694b6146a724c29ef1990b51102636a27abb0564b6737b4b51ac637c8302b14fbaff5ec1f859369fe45ac26cf77cfb266ea8ebe9ddcbfe3641c510c0e8e12adb4286276c017f139e8e2bf5af5bf8ec9263932cc75d125ed539f51b02aa6a4c3ba308c8f553bf45685e2ae4b30175734941d5afaa245fe9e6effa18d71022e7c95b75cbe01c91c874ca77cbeaa5793fcdb7f33cd7da81cd320b104149745164bf5b6bd85a45bccb1b268dcf5bec69b168b1bdce650d49bcb3b65a0de878665a662e92b9faff50c951a59d60042c741039f8ca1370af411442edb11a32467add837bc65bdbce8a3189b730e029f58a1682787a82d40723f7edd73f08efbc69d0e263536780fb7cb667e9f9584d8138dbb48e644badb75ba466e8b5a75ed7a596b14ca01db868f7a44b75773b5d487cbd534bab54d8a764c88658c77993e6cc2d62b476a9bc73a6264c5c0c8eeecf01f3b66c5b290730c0259053985ccd73fb8208b88a24f50ae3a682070a046d32e07f23cac617b7e870271fa87083b7f6714d849b65f6e2d6f3b987086beb9eb8b4ff6190ad2bb3a7bdb618473be1d4b8ece25588fda72c5d92e1623a46ab6c156707c0d9a1893f3df74768a8e3e11bf96c33395c9ebaffd437db52aff39357af3008915ca03f13384e6ec0db532853744e6394ac049dcfedca0649de616be6c7921beac7aa63c4a4ac9eb636935e36aeb6c449b5d6400a40c8e15fdcdaf6af5d3eb09adbce5c6a4647a04fe33dfa73b78a881ae0534504090a95a95da0aba27c2d46125f2d662388f1b067944c63b021fd271660fbb154b77fb21041e8e30811750afd6ed4b11dc9d8a0971417a44be5f470487f52aca8358d1263d51f8896e0b91c66fcede5bac27ed5245fb99654c2b8d9b56435243ece56245f9a4919b7560af97372d7f9fa8e5576e7337be772894fb4ed5d3b0f695a479078b947b5a55cd517eb2e0fa09ed105dac308f6020243407cbf017d94535a8f8987790a32839d265bd21fe09d5a44aca79113e5ed9f39077dc1d4503b2af1adb331861e95fc4ddd3375c0324ff718d06c4e6071293c25dc25e8b002c6e91e9293469ea1bd70cb814486fbbf7c1fd31ddc560b0f063f860a73ce00aae881c26a019cebd2d40eab5a7a6d65e6eccd4236781a0ce5cb59b9c94956dc7b0c460c7be5ddf7e6b2c501137b0c9ba28109b336f0e62cf838366cd0803983756a8143de9685806025935fdc3a56139a3f635329fc401c1d3d89ee3c6035c1dddf86eb5d9248a936b3dccb7d0fec1eb00f190e8b0ad9585b62f98ca7b81ecab65070285b30d3bb6731ec5014fe3e2c3a107e32b9de31ecb36eb2b9833e9fac2fd44af576933ebb12c97903cab051517a92c9a422d4aba1c6519e4f7c0662f8f13c2cf68b3d00526893bb0e7fb3df65a1474ebf56fbab1e23adb97b078b1a8a7df7f2acd95ac84c2f063a89395a75f4c199599230c39f65c165334a4a953cfef23aa0b33640cba568611714d69045b2d03da0d18c675187d8bb60c1de75b193f1d8d3c77d5fda4ca344dd2e2f26fccfc469f0283529b00f5dac547a0454024792c1739a6a409e58b4baa37864e6622b7774820655adc3c7b010d4f27fa210cf9c3c82bd7e921614775ca58ad77a3239a2a30ba8bcea47ce5149ee404cae5f143a3f3baa7f9c6de35d6f970304f1482fbf9ff03d55fedef8e78d9eaf4f77ba7c5f5955857a4d93cc371965ab76d317ac7ce5d29fd2edb468408d65490d4e911fb5b14c104ee826fe10fbd9169c6856dc951900bbd37dedef2c972c28eb6c967af2d1cbfd379d1ee023e8aa1b8e642ae964bad781df77386c7bb959ce7ec992ba5055badace596ce5a4c76ae58087de612ee20c1f8dbbbdea8de38c248e38385b0bb18e0d22351b21f650e5ade10ef01d02ceb0d2102b37bc289e41d08aecb7a06d41233cc5c84b84e142fba4bebfe4f7a311c2d6e32e8ce999f174dbb94fe02835961df1e4a10499743822635a17fe6e874fb839e689d202466d80c23cb60496e145c1fbde44ea8359a2e0f5a4fc161eea1122acc3d192ca7fef27e9932ebd24b61e21cc4c4b13418c651616cdfeb65fa7387c7a6761a3bdb97755aa812be7916a996d495a15e260dea9daa20435db1b9f4cc2f4709ed06e8817f78bc84ab34e8d431765076ee89f596e2c0a9422b59c6e770501840e1e16fa7cfcf589171e2c3b6ca152d742f6279a3c5140aec29102e61c350b7170e97fa99f76497c5c5655df855ab0d6131f8868e01298b8c0b23051bbab695848a882c8f089463273e3426b4350c805550e926dc65bdc36f2fada0a54c7e2dbfa3208e6cb9a27c2d5dff26fda92070e3b034d70edef11ba390e9f114832551920b2c74c973c59d6dda54e1f6eb9bbd524b80b4abd4d9edbd748316218f755d2274a64c31cc2a0d5ba6cb4f12b259265c298ffe5f6c078d11a00fdd1158e7686b78453d66bd115d0adc6fa18d88190dccd504ea792720e120ea599dd5b02241bedf417dda79f09bd55f21d68d8f00330331f3837ffc71fe26a9768e1f5f5ada7df06f33e16e602626b4bef316f8ae8d9004640a01ae168b690624892ac04cd65fc543013b5788173453c1d185b49e665b93dc124c69164d1e7db48e66d1922356bdaa3e42199989b5b19dd6df0858e54a1c1e54f44bac4d9bb82637554f2daff58ce7a7ef07c01e314dc9dba623abb11d004172345d8772d6602b8f6b4cd8c07bb7f6083afc33f4e72fb090bc07310347d91908087676b8cf2683e9633b6c90eb6067d51f632d74452c1a9eaf073b3fefb6aba0bc94808a3a598f55706d1c2468a0d6c88511736718e66dc2f4082d6370c3ac3bce7b7521100ca6797f0eeabbaadfeef5f095065f77bd1cb85e92b62b8cb2b6b125e3d5b809c881628aa00966f82eba418386b126cda6c9e83e74e760a9fefe4a712268c8aa5d4ab0bdcb8a5eeed35496e723d93586c7fa80a5d19bde18f0ae690bc1c3aa1ed522129f2928ae8fe1ba63c37b8899beff9fd585519d7c8afa86a5915551b6cc8bc9c394b66697675383bdd4162a4bf4076bf5ab61f27db95d26b5c194f69d8d5810504e181db1a06f348cf350d359328cc934d8ebeec1acb5e372ccc9fd2c7cd277982fdafc492015540069e71375c5f682b820b84e093ea49820a31c3492ba4ef4a8cb49a2b55bcee5d4e8e6e878e5cc15211a12d8cbd7b1e61e07bab56205eb715504ce4b734ff08087072db7480eae45461a13d14cb5a432ab9b7a7457d6adbf0b5d5f2aa65f776447244ddfb175ba4808457ab61efdf5a2c7a70988f5d5c33046042a269553c9a672e7ca34ebc64a65a57758d4992f62310176e30e2f5ea6ff9ff2018d9f4abf088a6e5cd54512d082428247806db8b2d4ed9ee0c63e67d9c9d4058400a009c6d7d1db70df448cb5cc10ba734c9b14bbe4bfd2090a4b1ac6fd1173590a960da046f3baf4efb2710bd0490a95380da01aea2e5d9066e6933f74b93a5e402f86e36b5e596fc7541ecaf832b0ec69b87e18b0dca5780dfde82efe5cfdfb8ec179928c33d1fef86d4986c763c08bfe9612e7d84f0750d487a7e53892c166f345fa94a876cc2d95a899559212698452e279b210dd267c60606bf1b204b06bbf09ada02eb22d41cbc81f68db10fd32fed5ab066305728f67d589de9e0a3dee6c7037b29e01e34383ce87a8937aa348a40e34936c494f11df4df1f2e15d7f77e9c9568b1a62dbdb0fab0480cd3308a441ab9c0a04dbdba2b66622dd2cc7b691aeaca16a8eecb9afb765b93de5ccc86087f2090bd9abecf54415f9a98d2b899749d8a2643b3418f6c0061528938c74845efab3662e964b464fd4ff1b675921d65cb6411af88d22a576aa1a2359986289e8f10762dedf65cac639d56ad6ea9cdd61799da7f672358a54dac7d433b7cacda4dbd83b8d13e0a3fe44ca65423b8fd225a43595fa643dd6c87a0ce0f89ca6b6158cb50ba4795424f9aa800d9f1158f513a9d06aa5f603dbe13a9e2ccae7649909db2b97307d80f366145bf70a237b4a9d45f6417c79d7060fce20c604d091b4a491894fc9ea6cc82d2a07d6b82a60f74c7e6ae75a53cd1b82536f86c9a794f5f969c347f9679223347b4c85b2170ee3f584f61fa6c076ac891f793403764e5d3225a8f4576ead347277d6824607714010b0627ebc88ce79514b77b2ec58e61abc3d9cd64fcdd3bad706c705f41cd5a8eadec73460928d312b319c20de5fd31bbec86f04960c9d76a653de723aa564301002f515353012a4739af6c430b51799a58faf9d9e6c8b44e6a1622423bccc53d4dabd3d52cb1cbd93fabac7cf4e5136e6a622e2076858b9ea4062a24ca10010aa4e49f3c80f6b339cc3a6c9303fc55fc3e3580ef8e80b1a43efdd6e63004722b29d33fe2ea8397b995b7938133911b1c37dcce14034593546ce9411a6b6a9372f40e781b1517c7a69438b5e5dbfe1303638bd0b1c424c72562b89c09c4e33959ac641c149159c4443265b7601b5c64425d270a5c0d449516a212bab352b48cb0fc9d337631bbfca0074cf9b8aefea5495084af63dd285ad7276336e74b24670a335f1c847c8826e13c3e713c6d1eeab1fa7616f36c106ee4cecba12d8f2d2b3c3a8f68e2d23ba9eb7d3e4edf08f588f10c6b771d78e738a8bf3e8a7c05a8a94ca6eb84c914eb91f844df244caf737d53a39b38aa79402df9a536a15c9c0727b472ee0fce6b99f8a2b5d4edc54ba6759aeda901d9366708a2d55115ce11a497e106e4aa6a1ce45e395e57aad298be3600f7d3209ab91edffb0dae64103fc8f6387a8c142b6760dd39bc670a13acdf5282f0c80758a14c691704e08ccbdf1133220a23cb9e318c663ba3b890ebab8df0dc13f6af5dda2231aaea51835ac486e253cffc94febcc06a6713a86551dec6316ad3fb12239c86384d235bb8c7bb830fb9fa04a92b892665c67197e64e9d48c36ab1ea4556616f4ff0b44d8cbf4c1676d74c2e4c6aa8a7ca47a193850658219e80ee22cce82a890e2616f6481a4277bc456943ae36c9cbed1b4998ae0145be7e26978d6d7a2adb3d60cf782ee191a11c1464d388ae7c728af5b2b7abc5327c05ed042e8f27f18ce10b9a21d0a59a53190cedc1d6b96396b3ce51faf6ab8cd2179ac5cf45f07db30cf46eb83a8442a9d6e1c3faa604a5fd8d859025db9b570a2d471bd5c71ef315f39b3571b7390a42531f402dfafb472235f03823bf361ccd14237794e077446641adec05e35fea0aca2b67d2bf3a27f62785e830ca91a770ab5ba289e7a4bac3f2077a0a73c6c270ca16874637bdf1b03cb81d4f97cc6ea6814fd7e482b505aa8080928f193bce5cbd992a9b1f2eb3ad4965b5f51c0ef92db554e39102d1e6e637c70acac84b2c7d20639b414bd4d2462e494b43ab7839f24ffd358ad9b44a54a9ea32d0bce6fed3f0bd2d81ecabf2218d613e58a36f703d48b310a5a83a720ef7b61b6117f79bf6c6bd564e94bb11445c1ce445e71067a14aa4ea2e7ee1c6484cffdf81b47a96a837b146a19ee01714fdf31f22e8c4c95e129b5aa6aad9f4b8606a1f3bf6321552838985bf2c6ef84e6f1ad0becb7d4f9ee5a16f6e29379d74b053c0882477a67834f7d1dc6b9f08182330e1d11c7f28ab3b3ef2bdc3c6759aebd507be4b4052aac5572ca7ad3c771fe5ef54ce0e16cea4865a5b8f754ab21549643bc337dd17e0be5e6fa2b75be28fd41bdccc934eb25985ab58fe5e2515cc2d050a48d17cd7569f473827dccfce8d919fa8c04e852af97b03e976e0260024da6817444040eaeb3e00a0e23eb00a7a3e254d7f2151095d83398640f6b2ed0ecdd6713be0e9aea957e48525ac3d647c9ce59c1e74b798514e732aac1b53c8eaf88b987364233a345718b856ed355babd0367ec5f4d8629c387f4d966a1505f454dbdc44c5ddcfe6d81443b1d1f3a95dbbae63962550cf3f4dc3add9b44e10789d4788b3d672de4c18c4a844a02d054cce7c5d4506333ce4215ac6c493d7b75d8cd563ef751cc625cc0ad153ad38dc4a22cf754f1d2cc05f5e3bac04595c276a62ae07023b97d3907e4e5b999abaddf9c3bda21737f2069ac97e03ce2230d9fa9ff12654efa0e06822e5003efa347d0eec3b1823b7201e5794d23da572857456c0a3f8ed475dadfad89bf4f9880bf325c0f166225960f9424166fdb1a9058dfe16607025c3f7c2ad75063aa07902051d2e05c75c57402b110b1e8c4321f6a034eef9c286a4660efb1db479cbbf0b182e7bef0bdeb32ff482068cfef55ffcdc2f2d8dbc643bde6696d9818db73b1fc116afcfbfa2c34592a6c6e6ad90df1d6dc9cc7ea36b39445ffcdc5fbe8ba06d968f81f136db24ab646fed3ac0e0ab9a6b9a4582c725da355d868e409df6da0a3bd46b847f51b90ef0e2841d65d06388608575f2fa82e5367430f1444dab36a856cf6fad429115d0c80df8729fcec6247dbdb4cc0b971f6bebc9f3577927519b5a4418816b66b69a95d73e723506c0ce8e9e1091daa237f4171952b5752d8c4432f1f03aada1edb0ca44272a447fb06d037701c6e35382d3824a7a0581f7026d7642f019f2a9c870d0b878869849c560f62d755bdd73c70229e2aab5a17b0c51cb618ff33539f278fe644ad56cd1ee8c122110292dcad49983d5b29290ab5996807020ee697e35e2e20db4da0e19859264a25c15ae8fb3313ee4da34aa808115a6c198c20d352a00a8e7a4ab1d423c02c586705a1d84c7f98dde4c8814d405696f05a759ebac146d72812aec380f45e6c86b1bb6900a545091157da96fc241f4ca9d665366f9e33a15c82826e1c0a253e9d06f78f2ddc86a2525a2483930b1cb3cbfc6f0da11d81ab15124b3922055c05cfdd9ac4c45de83e9c993cfd0a9d5e857ec88e49b427f3d5f0cd86daf84bb168aa86823df958b6674a35da8bd5cbfe600bffb304d34b58cd09a70ca44b865e9a52f74473e00ddc7896894621c08038793d92a8ca19c3ed7777d54b33a3ae448c00887c723791d50df458373bce7bc17d5dd167c0d2a40d8561c384a5c455b4f9d859fce6c09525770b19aa61fdb140f0451da1fb81a1f06d5ee17c893da1c592b2ba9aeba3d93e259d3cfd536ba71019ae21238ae59f7e933318474271cd47e032c3de8a0b80226579c41504fa1542e7bb625f61516433246df309a9aa6f88831ed85af0c044e38a24623c36b6472f1404bf3f07180816d62e63db161956a0670d41e161a60b97459d82290329d3699cbf71c7a04697889cfe6a4c252eb93d171cbb4f40cf2680a5442c8f1b1e9a841014a5de41de16a8e2a05c9cc987c28181b564c719b0d5fe9fdf64e935774e33142817b391bc804fe981edbefac393fb1e6a949f6489d9f7a2e006b3400e89c3ef21faabd7ba6654640a24f6f32b8883305b0b9784eef90a21d42c9bc0f1c9b560c5a9ded053411a6d4af207cf73da3312bd9b2fd532ec913044fa547706f8db01c6c0eba5d612655ace30d0f680289555c3267edb8e4aebcb91e6cc98bc9ebca251191d07fe9602d764995856cbe51c8458baf37bebcf9de21158bd8f4537028e6c19c5ae5d3005d4a9990dd859a900d0ce407fdd52006d8e3e90e99ff9281fdf2d2e9a59021b06288332215cfd5e22ad1d8a5138b43f164ed81bfa9035f3198ea04ade43f74a211fccc95f0c5aefad4c1c618a09d15ed2369913d076a7f284020303d86859d6f336109e2cb7951a866ba7c3a26048cd69b1903d1aa7ef5aae8040fdc952ed08c44d13005c9579af827fb1c96971acf7f50fe0c5bdcd9e8b394959389e7173dccea7042b070ad54774efba1527e703cddbdbcd85554e9e47e01f84f0e4026d843736562ecd24639a2b7ae80f265d8b380062811850b2dd21e25ae320a7108c8f7a69e3688134efb472eea77f053a1c6f17ea6da9fd006ac3daa3833e72f51b3c00df1c74fab09b9ffa3f69675102204fafaa5df377f5b64ef90bc5f1d524bea3bacef96c39d7bf65026b8f0cbd336e7b5dc2096d216207e724763012959de9eb4e0c5c0d56d1b352aa039b83afb57fb4265ee995dcc483b4b1293f1c81ef06bb971169cf9ab6de1227eaef097c079352b2b6411f77bcf758c4ad719b59ccfbd15cf7a95a0659bb0d195ce3a4e3f544ef57f40897350cb725b1e8833bc9eeab96bd17077c315433696103af72fcfd6a41fbaaefc39d40972ad3631655845cd1e597ba2ea334d3034b126adf242952a6b2cdd225375db72b76002670f1427845014b7356aa0d0eebd9cf92e7e6e290bb5022fcffcd4275cad968dba8bc660f7f86db4a8b3b384422abf5b2c11b0dd24902ecac89ecc21f8930beb961ad3ceb1109e9443c0bc81be510c87d6dc11ca682ac802d212ae1574f803a197af46262824e9585cd9b97fdbd200e47513a15833ef221d50a11e5d078724d04ccc5bf815a2860faf46406217a16224220eae9a37fcc81e2779cafd3469c91dd7497472ac2f03fd9953d1fbe7922d15602d0534d78697dcdf3932849a26b105e64ca9468bbe22e84f1a1985627152647446c4260f27e8d1f188bdedd0b00e549df9abd8d78569e80eb163fe7d5614f7451c1c9c37a727bb2a5d81f88eb7d1dfc09de1d3877fa68b81b4323a41d956eeee9016c8dc4cbdeebab3d770438130a03a88924530902a75509074e83a42d9e8ba65cfd488ce884b7cac50abb3cc7edd641181df34b824d6317bf3a395efe45b8eec29f387c89b4651b74650cb0d316d02dab791756d4ee23e04d411ca77e9ae703b050f5139c3b8feb204e54dd49a4be373987e65de41bf99fd2145bd2a2b32e29a223d4c88a14b2e0746ba6834a8e9316166b44f611993c075d77792ff46e0b9c2356dc57e9e3277e0d483a62d2664542d4881bb49a3e3f698e5894dc983e1d0ea99904f7ddeb7b49a804a22de9cdd3ce289d6ae36dbef1209d599dfbc7531b354f722e7e217f000258d748fbb8dd47b7616204158c7b1ecf5059f3160bdf1d0e9c2b534d1dab89585080dc6ee002992d2ecce946a5e6b6a6a183c2d857f961428ed4fb0a3c6fc3582b59cdac449efaf4cde457ce54fbc1ab81864e002cb9b522c6b6ac4341b07231338d35fde32f30d2b89a067a35310635f673fd97f22253e16a83247889665a3c76fbd79dd53f565cc09cc45bfc567f16b5b66f0702292fef806d52fbf674af56f433ba3c3057b5f0503495784dbef9e285b1c53ec1974124f1cc9ae2253cb405369996570a4abdaef2dcb3bfdcee39b326e0b1c38260f5f127fbcfd1246d512f5923bcffd418c01b48c25961caa5dc7f9a0a9a1418654ff53e6b06ca492a01f94c108441fb45789cd5497dc3d02bf6a3f06181eeb2a1b2ee234b754d8dbd199fdf5771098a556b184a516ee20dc06c5f739dc516b16f31fe7cb5d4ba47733aaebcfb057debba73f4aad54d092d8a4f412b130b8f3157ddb0d610c6ab5edbacb4893cea03823525909b52a1783ab8f0519f20397fa9a7f864fff5bd95f5cf9f47af57212528590eea401e9cb07e8f2d70e80068aa7729619be6323d4a6dd2154d714d5ccc4f6c1ec64f0cdb7964f143e454c457188e367332e0ecef14aae3ba29d44812cc1190f36861dc2f18b943b3e188cbeeeb5d571c152f43d8c64d79c3a0e47b0f9b6ab2ccc29d9c453c3759ba771963acb6950ebceee0656cb4800c88d78dfe5672026c104caca611ab29c49547ff6b3e556b438078c27582dcab014b8aaeec22036304eab4395870e33212280360023a2d6248f2d0126f1c52e128d314d6b2259f2868efba348563d60922e8da87092228f9a1076bcb7f2f20f5bbae2d3551472113b5b85d7ef194453a654cbd5ad1cb3058d2c1cad874fd63aeb6ec3a45fd9bf470076e04ff7754f4b3665d96efc938460eda597d759ab86ad2ccc7e551c243a6a5c1898328c0eded57b5451c9adee75d53c64b6e5cab9a77e4f4ddab74ddd026e38b24d1651ff450ca0151bc00503d66105688928b39954b32b8caa125a09f49e69580920bd9c96820bb8512381427595fda30cefaf0e08133e9dee35d03c23af01e371815e3df6240528da4b07c46d694b4abb11de873283c227731d584feb8e9479b82c6676506d1dff7698143b58cba13a89200c45b3f0a39c780be1e7035107a6c03a82f8d56349f8366962c97e00917584c692988f6b808b7c01a1af8bf6483a7374b06a6662f4a1bf39818d30c7274278835131e46d6204034677c256d54397ee0ccc3df8a207a70afbdece17cb016bd7ec4a75cc4d63353823c204af09d037177bd0e904e454d1ab35fc6e845e955c5c0d9877d2497aca41d3c1efee8ca5e19575e1787607dabfabf4690b53f8996d9bd260c2b1e19df83c3288fb0a4fc0ac79aba39f23f32d025b5c36bb9dd6541ebe6a9c67b8d49d077529fa778708ab4c3745e8e0e20c36315ac00554dd3c9f9761eb059cb9e5043da9df5ece724848c2be16f7843d4649143df05539e27343ba9e974bcfacad783e4aa2366e4786c2977ed5d57ec35c28a2df969c9bd77d0c6cdded8172fe474ec97dd50829573f507eade4f5b1c030c70483d2b9996af1770322d5be00fdf1d8a0c956396ebfcff39c8b2007d09171f7892622dfc123d29ba8079c89f59d3110dd6fba986eae70566267730fbab41cf0dfa6c541764523998bc21f747816f977429e675663fff03b2870bbfa10c7fadad7613058adeca290c03614331132c98d6cc3c7476811363248e08bb2cfb5796c4b597ca8f6d1abed399a8a1853d558c49dc2fe3c8f691eb48ccc8c02c1bfe6c418516f1564ea74414b2093afafa9135106bcbfcd3ef0cf086b67bef8adedc0ee369fd3e37508b775eab7710ec0c5a1c5763ed1d0782f3109f0ef56c7e1c55712c022ef60e09a3085cef09cb8db9b28beae3fee673cf886c943af298ee4bddef30c59c0d5b7e1b3ee33e5071a6d262bb3e61b0c609e80d69b923dd3530cd506819d3ed51e8eeab4f634dd4fe09c6ebcfa7a655cf316e51b9bc0145d3b5498fe300477f9e6555e88d5bef5f2f560b595311ae9c21dc52aeb34567b2d30401f2b309cde98d7cb588a20ad7985d636297ca5ef6cdc8cb6c88ee9a18b6a2aca3dc93d994d7d4f7a924ba21f335b18bb8ee96627809e489288e9c6a6034aeccaa962f086998e62bfdc1693108a05d385473264dcd2eca7dc679c23ab181911510d202cfe84611e8538708a20fb119a737d689dbdac4be8a62295b5e8ae50ab9cd756e0a604f1106c3276dd3eea7eb5ca0efbfc8b5a6438b68285f3469de412155683e90cc183943ce0067062e38f881ab88d3b9c6ad151472766bc95e1750bc04f3ed1067408bf3d7bbf4ea2a77e576a98e1b8dffff6bfe58240a28cd580b42e47423cca74df7cf299322b608aeacaf42dc94701e7fcb8046b832eb2510e4a1a9d355948a945b2d46f1f48b13c933ce191123988488d8471ae26f008390982dbfef5284f18b32d521294172646cdc1b10c517e6649c95843f3c0e4d7ef6497ff4232e0669ec0db631ed2af12265f9a1d76b97742ca08fdac7f4b8ff3078df394e5f4c01d2570944c62f2a16c5ebe1f69cbff47124b6ef0a5f71f405516db4839ac7b8813f8aa9d28269d1ddf3fe96d72498e859b902a7415367233159ae42a3b845816dae335cdb3e70f75d9c8f02b251468dd5932004ec5f405adef1428aaa870229e787d8d2d8155c889c01997783d4a6b9bbcf69c29c2d3df96ec145f074538ca5fd4e97039a39f567f8f49bb2317ffce309086aa20f891309e4231dd536458c7bb93a5cb124fa154358853efe64a9eb9b02d4349bf9e5165fb0c50818754ce3fcba4e6b83f0c5aaf455f336f67ecae7ada90577b552adc219f2230c00b348956efd9c52e18b95dde4bbdbf67da0edd141b40b06dbcf68bba51f9a00333877686605beab0098b1a31e9f25a362d40d51b4b4cee5136e4978c6b30c81071a8fab9425b012ede4987a6605b4cb1b6e1ddf7afe120b8a080d499010afbbdec363e4ed58e7d3515a78015696904a69adc57a24c35b889656419dd2ba9bb109054d6f9bc6515623e4c5286a4e22d3bbec2028f4cf65ac52a63003c0e0cdfc73e0cceb19c0b8f702e2a7b6d69ae51a3e0eb1dc37d951d89e04358462f9e07434f4e6bc03589eca86f9b89507279a6d2782c1d6897481d9821e1fea6d9c3d99edb607391005e6062d3eae591ffa0d0c1daa60b5e49b33b30982721dc4ec4ea408c9ff3d63035a4352b111af84febd2c7c094abccf287ec7ccabcdc73744ce81067a5392007bb8466ed3e58534323208436b70fd4b5fac482ac2ad857f29f535d1536f8b86a7485adf41c4728a0bb8c79eee226ae5c9ec11468b28f1c9c3d6ec25f9bff32e93c8dd9fe2fcd0d812e1fdecd9d34cb4c89df9d4ad034ae739c50db1b49216ef613a9cf71a413d03b0d050a182f81ac51c32870ac186fd8a07d428ea00ffbe402fc04dc7014f0bb5cc91a92dff736ee325d617ef30d5e51f92dd17d8e6184e4b99202350064a7aea61319dc555e8455d30ff31392dfd55b9f2db4bbf051407e5480ed88bdcd797ff6cd8e7e9c2393b2cc56ac7480bae1f1274fc1c0fcfdebe6d094654b2781aea31715765091b056f3f6face32a70f5481004520192ba0a51297db7e6c9172f74dbf716e0a674146d8834d0d0869a008c4c4b8e6a4b78d84bf3dd599c9ae8412b9c8753639db83c7a56d8d8b81e5370b80b8bcd9ad9f74f1565230cb8bd74f95d020ad2cd8a5b00957854428c3ac17db6df8d52315247b6605b58042ca19eb4005a2a890de7a584ef77a335c5016cdcd0f5d9cdd4fd8e6bbde2ce6c093c4d81eeaeb677a8ceff070e7d20cf1669d1e1c815d1764b33039904f0372a0e5db0f50730a0a062527ee71f79c422bdeb7082a0c1c30e6298a025bd9eca315933d46f6e48cbdc7a9cda63ba9c0972523511d8a0146280a1731743481dd39690fc5cc8efef226bc5c5334e9c132e7c03c000aeafe3112f0f5f6d7dddf2f5a5e3b2394a2d6fe4afdcce7a23f63b26419b686d70d009ad853f8839f80c518a8aaf062927f85077af8f70b73b66c49b2a032d381eb250672d2a9e18e8885b5f8f0cc1ec3feff21e0e1200b673404aa1371402321801cb8f2de26e4d86b9745474c20d6f896a379c5e4103321055d550cd38c11511fda826290548ac43f6ac9919347db2df43f4323edad91f21d490c57d5b1164ee746f4d66eefa77837d8bfe9fad773e37633c66e24f39bb6f0db0c334d6f19730c51713d9fde6bd7b683e630b3588f4aed144156c371adb439a3b235b014cdafd870cdfa93ed8b9aaa894832f055dafd9d69a2388f06cff4c011e90c0286f35d331d9cdde328ecdd5dc35bf1c588d80dd834fb99dfd6a0cd977aa02d486f0ce7974ce41f01187faa8a60c56581c42410727f1c585ddff272fb8c4f2f00305414b1dfcbfb74533cdfba25023581a44dd0bf69077e85d5a0a0732f619effbed622ebfe5c39ea1b154a7cad44eefbcd436bde2046826329fc5666d71752f81f2ebc44bca1e73b1f22a56491183f8a5cf498655ffb1fc1267942d9caa6a380ba6a8988358b024ef2903c0d15b7a60ad8df95f05b744ba2644569182b68fc834163aa975b9e7abad552b8f55163fc8e9c6dedabea176834c4c0c2ce7af61c32863e38aa9060f5dac64fe131fd5ba67297cb96894907226fe1f01ed95d2cc25f5b89874cfffa984dabec4df74bd7454a05da529c5fdc566ff80a82c1d8b7f926d882741bee028df4a6f333b55c592f0a877d7e94f4e6c3b80ff332190ed7f7dab2f301c0f1c1d9fc97a63059612eed04ee0c35191b8f15b1bf7fb852c88d505c94986497aa2db7ae3ef46ccd5675205397aae4ff17ce9f44d7226422bdc209ed33a70c5941b50ee36c3aeedc1bf1e48931eebf84ef81681f050acd77afbfd2bcfef578c756789c5d188a6ca3b5efd4fc7615ce2e6df444328478c1fbe1a8bd260a9f34e298ed1051f65d481dcf1a44c5b5d02c36476614990719c5a2cb9383e55b9e1ba24f1b72aa45b84f9e5a8df71dbfab6b5ca403152bbb579cce82300818717e1ade110e452460b33ed98886680ff49e2f980b179bd3098368b39ec12e16cf3c4b405ad8d81640c7012fbe5d0ba017da5f3beecb89ee641a656d83eb90bda0522002c9a58612c306fa304329444ef348fc8b3c15281830839649eb6e4036c53039850293fbeeb30e6ed35e8e60adccea433eaf1a4a4743bbba2bf8f78e39b6a74bf9b96e3bfdcce5706a3b83865c8d40368de1f72a1745cacb75134e5aabda779e965983b3c2f27a6c21f357e80d46f3e88e13383c036d6d1be6d4e86e1d93ae3288d700a244aad4fcfa46f19d3651e213e3bf71a8e404520939aa04c8304fe77f71a83f867d350cd9ac757faaaf8d831ae1ecc5726c20d3f91c14dacda0a9aef1096954f880d7f16cc301b580765084d55e206fb65c6b74ec308b8f6581a784e3fc32f82f81dac3af2488c7ebd1a74a30f047f954e38d30c651d3a4649ff20331441ec15f70989d7d40209c2bd4ffa4f4e16af886ce2b3d90b0425801bf98bd708cf8ea51dd55c9e0d18d5471edf0bda139e89e5fbc3a5bf0940ab7d625e83fc65538ed8eb110ef840bceed6cde8dae95a0ac94f584060bef5681a3cd7aea5bfed22a1bc35cdc737949c9d918c4809203d8c4b96b67d4e1bd36de714ba2e3eef9c99eb3b66bf3c327b952da3ee383a493951a15e8347e5450a9ed6584a82a8fe6f51ffed21b958798e068a7956ef07fbb109b63aa51157ec848e5fb6f7d7dad6243a10ac7e14cfda40e86ef4f3f8c17065c7d72bc5fe3a26b213f3d160f77e63f2eb842f01fb7f3f47d986a41495715cbe9b2a21faaf9bae2faf9a1dba5f460a9555431e7fced0233b3f6160e0679248b26172e484cac119f41be1a69e61ad7d8f857f38608dd7abfa63abd69461bc77afaf4ab6f879438c3027184cdbd81268e27409fa8302e4bec9b1e6ebacd2007368ef7bb230596a8ace4ce53c46d9655e163eae4f4ed6c3079bb75e49dee6d7c57971990f323eed3ce4ec116ea032b62009fb531e5912a1779e161c20466b6bc800556d6dcaa75857e87973c6199be9f9c5eae870bff0452483113805a8c36d9d2bba755cdecefdc1104286ae765d78ceac6aedaf48735e3b20857cc5f4a87ff73ff565187300339d842b4cc050df07fb0e1f2aee65cbf6b0f0620a143998afebc39427f3aa7161da205cbe386b581256e7c24b946f089a2c56d02f1a5eea02befc6297867629d5c20251314a18813c0d84e5537ba34a211c2ba32c9ad50afe02d8dd5a4d14249817863d94c8dd49eaba017e7e87789221d4b7698acdf2087a36fc7a71473624af142228290b179547b6e6739059dc665203552c513a03a11dac4e127e9ab79a6e665e0aeafd98960907a73cb0b466ce1369488dca7ed357817955b8993a97f7c2003defcb4fc19612946311598d12c2eb3b6c74570cde86cabd282ccd56058de45529d439fc64df79398084530d07d01c660147767d6487fb96802c014d96413625b54442d34753c4c4652f3400dce1aefc9e41937109ddc354fd662e52072581af75ca3ff432a68c2c38c82bfd5472882907f6934bde9c9e366a10143aa5d234bc208534cef4d9460c24bcf3c66d25f4410cf6193fdbc021a45459a3103cbfff7e9141e6900ba56c7fd497087572be99787f1dd561277ccf83ead5ec8d4e306e347d020ca2344855012fff219755d7b7a0d05a6906c10808bb60f770298862342a206b1aa1cab100f80417640fc76a87edfb099b80a7e08e6a390884840ed2f12cacb8633376994ae438e044fffc3f8e5cf9f1ae2c67a7f623432fa7cf6a95a88f776f043e14dc46e251eac13e43dd4dae1120239f255652bd0a5d97a986a6a99535d24f3cbd11f500c078fe79000a1e8264eb4ce1ab0d157bbd1c35910430955425c26b5e9e906f3a8c850c536398a843e6ed93dde13b6a052586bbb1409da3b6c1c42f60ac1bbf0c55179b6960cc4ce7c0f123dbf99173821fb505ee96f3fc55a893992d612d5f8493f450f57255d1fdc429be196c7fab37c276368cb8ed559e2c928dae46ee42baadc1ace963f656ce0ee05e0f2dcdbf33098bd1da573a563355afabda9fa0487e8878557e722eaec216b120c3a62c13e0b8cec7f12651981a2dfd02a0608a68b25a6ece47210199ce015e84e9b34e9b2ba0f990f4ad1f15e42da377cccf52c6a7e8113b117d9cb0420504a0c60bc430526601134c5efeb03a8e3be5dcda5245f8bffdf67e1e43fa0da921240074898bc6163847cecbed54518df0b21f9fd01ab4c5bf664fe94feb9f5a77ad83a43be6fc9f816d4c280c93a569d0ed0ce0a0357e62fa384423dd56912c81320d54035b7052de8c0859bf0d66f8029d33535ceeba2256903794f901bddfad60445ef7ba8db733caaffac2c2ac6b8d8f7fa2813c2eaa5a296bf73be7bc4f59efef5c075128c2d944ba7e918f153811f4085bc6d0cd60af35575c7eabc433bd8c1efe5ac839e0a204e718d13cae13ab9747bbaf30f776cc46ff6d56facca8af161f18ff012fbd418fe6e6a61c3da2d17cd105e3ceaea9a3687ecb26472db1b09631a7b58d09ae6f955081bd6d9eca36fa9b923eb29cfbeeb9bdb6e3c050c16d27cc7e830a0b1a38ab20154e2c3c354cca42a1dfcd38055905426978375bef5a1832636d6780f9c22f5941f3a7ff502e1957a8eec1c4f10c849bf7730ed7c9f3862789c64fd1e2735c0467820a52edef0db951af6161b826c277005663c618dc7f47daaa9d3c994e77d02c292a7122fc1d24ce15218967ce5a34742e84b50ec823e16f72786b7c42fb8ad39c61cb60577e84981673b44d5eb0acaa560cd6ff822896fee2b9616a01e9ebde77fdf0d8e98bd3bcd594e1894c047e0f2af36daf441eb1712a15e6533f1542b40fee83684e868b9038d5be0acd22b2e82a55bd59ffced35f531dd0a50a3e82ab71097436a59669a4aab9d7bf8c892c6b5cce0bfc695228e924fb6debaff04503b4b995ffe67f79a2fe7d788a35c9e01afeeb039f5e1b8bb4b66e1869c5ceb1e7a2f88278c5eeb2834ceb5b23c7e90c2ad79049605de2b6556af161c657c5711df9f68a56e901522b48ffb577d0fa8f51799432875d64b1e0c1ad5ea8003fc946d0c5116be1a16cd4c172d54d5bd5e3336c982e97fa478c5d5bb31b3fdaa65f97041e737521d498965a7a85f1212d35404eba133e276288278e941f38dd82cc29cc24617fc39c83eda23ac022515802843510302b1dd1a71da4f65cf4f1ef0ff3ad0a8229d38747def6b70a91dfc57a983b34d625aa203ce4e53ec3d633d99b61e4a9f0a786c9515325a5b1d8ea46fd1906b326894bc8b181667f699a07cd371e9b8cfef7fbc828a14d6e0ff08e37da64e7cc582de4ef0f27a58bbaa8e438078c0602080dba72fef8b20eaf26039d946c6360567194fe4b3a84370081b99c5b1bd4f99e9ee110053049f0d46314b090401018c1cca31a1466a684ca30984ec68e4c1c484da5d94b4bc3987621fe2bb13c537874887445f1c58b6478175b147cad4db355c308d978740b30a33c3084b9f3e850cd34fdf7a23f2da4014b2e4cd478849d3c4ab7afd444837c79a70bc60367f4097c03a6e6324fe45be7419d90802d86f667e35ce9f1b859ea3ee46b563c4fc0e4a7108ab21920f427fc31631bc968dcdd8c363412edf23038bc67c01380614434ed88bc030f948b719c57e7fa4f42eb28b2f9a29420195a5fc608ed242bbed014840cd94c97b4bdf57f0ab20b207c92354457f7c0c01b6c133fedd190e9c4871c81e5f34029c8af30beb524d160d96661e800057d81109bdd04488505f18b3726ad5eee71e6ca686d1ca51cc1015d2af7d4f91bf4dbc74532cbea1f5522902f8d7028c9f484f3d14fb5d1be5200cb2ffc4ff36952c63757370e3866420458d7ba66602122e036e257c79524eda0a237d3936bc94c3b0fce733698d19bb7dd89d58d11a5ee8ee26b3dd1449bd9140824fe34aab10a99d2dceb3be316ea83619c2d7c728af2721730ccced1e271cc94bb4dab7df1698be1e2fb0c5aac1192ec5d1a6ee05f2e77aa3526b5463a63b99d3b496e0f5e0b07af9f7aeca7373429e11041922f2d4c693c602d6d3eaae92d2ce1edc156cd3c4931657315d74250553d61ec95452173f2dc683de8172831d61b2b3687a0e2624dbafe38a3c7b3cf7be0746100aa968f74cec868ab7796a085b877d186dbe8c0ec9381256f3cb67feee23d9a6741866bd3c2c456e8e327cef3a09e94b9a7fdfb83268c1a72132f876c8f8ecfbcc6a62c2268ec5dfee5c141b082caa6b8ca58053ad2679e9d1454f939557a34fc1fa78f722336ff28d4f6011d95eb342f7e72f0523b9a5595aabe8d5d2454ad01f88064919dafdb2f8853cc0377bce3b70b58b25a6407ae1dec350ca5c2377452ec12f1b091849e314ddb04686075d67d7eccf00a6377e874b2637c2db30b8bc1c5cbe1afdd21948bdd8de3ef0458dc13d0514dfebc352a55dc8fda4516e67a287661ffa116c1ef7c187b7b1ac53f6c62f1512bf18164540f6627007fc3b415d335dc3a05fd1d06b620f9aec7f108719a79bf6baa93c60e6c415a7def8be900eb38e3fdfa2c195658e90988cac9c61276706c18b2b90c03e289986f5a530327a98c9d50a3009e7fa50a27e3ee31ea0ca7208625c3c08d6c7153a23c82ce5b95bbaef3cb872493521dd5ee9952a94ce81170e7f50c9c7b965a2d72e830e477ecd8774ae428538a682e632e3b6e6918429bf89aaf5783ae2c9711a13658c900b37fa7b1cf9d610a9125de3d1e31924790c0c9a8476189edb80743e8fc83d5efcf9dac9a72950b5d7bee8a5747afa23ab58f0a8f68a81b29c9e55a5cafa971967b2da826990f0198ab47bd2023186571a2723112a80fad79e61b8cb8ae226ebf93d569d89d99ffc4132758ab6dae1ad9f6892794dedc459b924519950cce5e74d73aa3b53376d7bf3722a8bdb2986b9475e0dbd959a5a3daf344d4d261e16ba13ad168abca4eaa818e4c0ae1af19d2749294e75b424f66aa6399f1c54df4210ccad3e363731869c9cc31bf9741a868e0b2ec56400a4545fcd1d4f8f13e47ba866c4ee6610226149698140ed4adc4b001573f5eab17b408a5d8b71caffcdc58c2a16a17c28df4326c30af32e9072f5e6a363780a8b6365f988e00b308123a423a46b943be9aa2c1a5c8dec4b5aa02835768ad12730c4a4dc1a1015302b670a9462fb7c103dce989d0a9eb3424f3b094707ca038b40df7b24d045f5b28b3b780080bece8ae6907c6c25609e7b174752c09a4c41cbfc0db1d5ac3c19d5b8c86a3e249727501bc409529ec2793abbe9afc8c90cc53f1dfcad3810c17205b5d7afee2775c3c08ed83c0b7036d281ef48b1c8409b701ca429ba6a95512103f77b92e0394a7aeb5f0c65425f54491e74246f80fd140b4b70420560badabaa79431cb131afe7de10019ba8efa04e32e29979fa61b44c7e4e25ed4b2b62a12c9e0e94c3299a17d8fcc4709a8c3d0812cf0ef6b8f514b28ecb41a134d26c308bdedef9fc1d218715d4e3f38814f5f8f19eafc14a32a4e7958f5c28943aabaf7dcfbd854b350ba9b6f5a692e3e5490531af260c822a94af2c172b710a346b692fdbc5c2d3f4bd1e319b9205d40b1323da07ab68b599b3469ea8eae3f03419abee5a7ca9e8cbdc87a6c3209eadb616a6e2045b21b010d81d4b4d44c92f84aa84f33f349a13e2c10a9728cbfe22cd889190c063370e1d7c273af961f9763660f3c41d5c38bd7ed23212a7150cb617d8bf40856f12cfc74867db9e33d549d16c8de151e2557510db3fa91bf7a42cc7456a9c1f9013e278fceccbc25034423ecf511e7528e164d210183a4f96a5b0950ce20eff6baaa9a263389a886d298050ecd50dddc5396a7b934c5d0ace2e35e2fd46d2f71c9912e9040a90d480d05d9fdaab8f4df39bac044c88d01963b757c9a594a679b6e072b78ed4cc66e960695f6ef5aa569ac1a640aaa7d239f89f3d9dcb3d083c51882a83fc7a0829b5d7210fcd82130cd39aa0eb9cf36ebb1239f392c39cbf4db2ae6d528ac4241710ee2dcd03860d3aa11a8718e817bbb9f35105bacf6d3cfb749c541eeea52185b1671617d43eab81a3187d8f68914d4100db5e4bb35bf7242542d5f5c3e82be31f1990a9b505b61bb8e6edccbc88f4594999b41d5e0f16e4f2d450751729568210359eefda59e2c5eca83e560d2770e2df56015e5822a2c7370822f791657cafc828990024fa189b19f96823860a818576146db796464849dd3e43a7c9aea1c83599b910d56f8d40df035a3296c8de98e17584651f0c2b49b86e128a54180162b64dd6f40e38a4fa8e22fd45686cb9993a2813386f18ecf13ab884d4f354f07b7ffa1f94e8e2d92abef125d8ce4df7c403c1e23fdb3f099bb104d3e5f49105865a49bc30f44115101aa16c5b0c9a0910a7a758d3d7d9df1aee61ed516f57f8737e3ad5d8060ae26d519dacf083b961d3751f9673f6c747060ad1454dab92929f1a49e7ab70c28f8749b066f08c5941f5fd4d7e567a8702cf3c2b51b22c0a23b63259c2fb5f4be417df11163bb2308f88e54ec9f9aaa7a83600069c4b747a2ff98fc8500750884fd172b0c5fb3af5ed5ee04a2b18735e581bdf15ea1e7b77d4e98b5befe4818c9a702dd252836c81e6ae1c1b43324568ef01b092746e232ffb3df541f95eb5d8d58178def37d102c938c8fb51e9df4c0562b592d7e57f5cda52c66389a8b3819cf74e24774d2d34503ebe44d41ed641268d770c468a9e3bf9fa8a01ac2ff9c54783b794b21cd8cb3d6fc083a7809e1bec8567fb3ced3c6fd222cc72f98ef097785f17e634f3f622e40161dbb5e0d3964db81df31847d24261fefa9b70d7843b500d486d7565b34b0f20607160741d01d394f3138853113606e1e02a72d6d0d6dda79631c71ac4d191cf27c608e0efa2e910798c4e1081abd9833c697116f4cbe7b2bd83cc752d2c8fc535e297f9bf744bf5f4ba6fc5ece33df60d1e67bf41ad7a9936a9271df1824a3913877f01ee066c96b4b4192085ae80aa84c7e0625f2a621755523e3ec2c1b0fa8c16cf3373d726ce28be30e2a1355cd3337df317a50bc7d1919e40c37c4e159dded2d3d5d8bf389af7d01008c8a3101701738a70c4449a7c6025f4b0caec800fc4a1012469ec518ad25b3c5b2c3c13d12bb812cadc737cbfaf09a153722948f5e9905b39f7ff6a190808f0a26428f4187961e14a730a0af064df72bb27817b893bf8f6982c3dc15793cdc27e15ab9a7c0404f2ea76519b1614094c37ce25980c363b6b872a3ddd28e6e0af40abb63321dfef1957a029438f79d890d5c32189d8385c2344a67f945a04fb839f5c99a21acec06ad35b5fe6295b215ace0458ddb135d421a34d3d432e65b4970293e0655fdf7fef1faef02973d3cc07b39d6e0cfa4130509d390e4de9b1ae699851dd636a858d698bee093a4600c69b6cc429a1ae31993d839c96ec9d9707105d53d06fbfe0f39fbcb59599801337de989e6b0e71334701ca0d81481550d043c2a047fb72373bea80ea17cc7fa4b0b5edd2c99a7ecd82ceb3e8ac084da28c37e756628d959088e4a08237c14f9c303a0e501e56cc8deae7afb38558725272ebc2c8b842b94ca28372df4e3dff75a485ab86a276a84b42f1ad8e35d4f847d9c28fde5d7fee2ff847736483179103eee785b2ca7e79bdce079819f9c5b573c2a90e522dce62d61f18e42bbbd1337557c8668610662a3cf1fd3e179a1c1b69c7e04de7c5f0eb50ed5cb343a05ba9060e4220c43c5006ae668578216e0f4692e036516f5355776c7f5302d03ad8300237560c14528b061ab816c2bbcb5a9b7402760b8f43afc8b7d43b2196f029a996e7893d0a85094c314e2cf407ac0269dded902e027c6d138fc8a1195e76dfd3465ab49eebb52bc27b1ccf0385e33b32191debc862135721266c895e9c783695c6e67409a723664106e32ae7e8c0dd1ed45f27df99c94af201b306f6b390690dd3f3f52fefa61fbcfc5dafd33febd2394d8156298fa0a60b9294adcd5bf9165683c73bcec9d508ec1a0236222268c0b55d48b42fd64a77845118da27d882598ed4ef8bccf929b71bde969fbc059d21ae91cf60dcee29ac98b9fd4cb60dd36f105c04d841cfe6a46275684e8ba0c88e71bf98e9e0dca275e8b82babf2916731b5ba2f96cb943c602f98a7a5508802b846c445fc55a1c00acf4297dbd84f9790f33ab79aac852b96022a9e406860d8600a33e61efbf24f856ec40f976e4540a96b5e79c873618c90793c6b33a151977f71e8b882c69314e6fd68794690690b4bbd34efe2ba9ea58ecf421aec9545b8b5c4dbad9f376b8bbbe1162eb62ddca064f533e2633b665bc8df9f706950069d8d77e0311475707ba453519d7ad89d36c603d4a0f1b813bf5064452407cbfbd7d705c4ae1c499b24e373a5bfec8816b112d6d422eb6ba40bdfef5595bb557d6a7cfb3f6c08ef11dc2999f44e96583bb5527a398a3dd7fa56cd08525ee131d82c9f68b341651ef0bfc09274f4e9aca622835e3e815e212253aa2373569e8af86877918c5cb7ab312ec0103bda6516ea47e982f931d8f75a1150e2e79af5a3e9299f22112e594ac01c65eb90ae20b9f9bcc6952c637ee3139c3bc06a1965c654db537c8f17929ab09d4f39a7a38f7c2f613457f0e9ed5ce04aa70cec1e57ff7df855b8c43e8e2de87ac34a9478511e59f016b6e353b98928e3eb17184b772b3313592998e2c3e0042cdf236209a0452bfed6359f1033295fc293af2cc568215733ba72e0fab16e669ca710deabe0c0629ebfe761570d2d52a023236adbfe886e0040c44731e27ce41a3f65148fbe60af2c83a3b9d2ec4c309a299c3dfe9b1e7714d1412e1b58384e53e4fe5e92c436aaf72fc203b8ad525c2517bb86a92792cc3148d7e57f895bc662bc05eb613f0d595ff40be4b39a7254bb826a559060b890e625e1b141ed63edf44e9fd83bf23b04abb6fb871df4e5e82abee53500ee1ad686c52406850d5c8763d14581417eb7c16ad4f26669892ca30d858bad19a917515dd01fc6c58c7de55224d0c4976abc1a4aa486f8975524ab679e69d5dfa4511a2cd5c919c1523339976eced848adb8b9bf859adbe3c2f559f75fd764f2f1dcd2c16c4cef375db25f0e14664d2cfb65d417171bd462006ae860bca0cd5cd4ff454aa6bfb577df2a91bb9f70d46e7e3fe09d1ca45993762df29dcc382596b138a5dce0a59af7d7b150c2614b7bf7bf0d292caf11ea6704747022977b776a069c23f53e459e78d485cdcbc051123f7dd5347bcaba87749acd52966e8fe0c6ee83639dec27c41e8b42dd031f608933fe830bde4ebbf4e0803dd04106c81c833e59ba2c6300012d4eecf86cae872e0f6dc464115de7b9b3c8825ff455c32add297df99776e8a63e394af3acd3f9d28f6cb3b017cfb06e2599f0bef0a2ce46177d449b51e089fa098cd4e5077383fd6b1deb9b59045cd3313415f0f0f8e82003e2a35d7f82ea78619c4b870d2041c373600b1f443f6151c18d961e0a2e18f40153cb9813e064290e107b93ebbd9f9f6238d1afeb60e533711034ba9f4c434d01427dfbdcf40f59cfe6e8cbd7b6a63687344e8c5b1ce9151a9643cc07483a0664a44713c6ec6a251b60e9b9f88700097843872a5c313f1e3af3f955e3f9c15dbfff5c15f5412073d38491c5d7e2f702f8ae59976cd6d61ae1e94743d95fc0c6675faa55b64daee476372e69c15eed72fecd449cc9b292debc44947d21412738b68e70ebbcdbea055e62a99332951c8ca6e6622bd7c33bb9d6250f4266fec7293ad62beef035350e2fd79e1bb60f1d94fd6b9aec029b09bcb952b5befcc7d01026361ced4de9f862e0ef6930dbb87f7f0413794a29ee68db835e2a34c73356d277db6a14c5e400482c3c0482726009347666da9456d748ec37f77849b98b5930a6a71c8ac25c9be3ef64bf9c94f31dcff93935eff2ad2acb08410b952e59046a5dafd90524831d3e60a871ac690288394ca3d008c2eb7cdb3b2734193bb871096f15132ffb3e2e9d39d20caf0085e546e91a5b18cedd33049ef2eaacb2ee92f55be5deda976e02febafdbefd05dbef9eb7aac46de0e4269f04616a7ae74992f6a9e7cfe790bc082d9fde46dc9cd1b42db8daf4e0c5ec24a028ca18689db687b145d2b53b599a891ddf511c8d29d1a764ba1ccd8b28e49bb95c6273ede14d4398aa86aba34de8599656f0df3982ca394a20eb88461a4b9f72c274277a5ff3e37479d8737e68e41aa6f7cfdb46040224a37d671a1e54ef7bff4ff3fbe2d0cf2a36f068c9000c76b04d77440aadce1aeb0c9523c9e5b1970d689b930757e4f88436b1fac284c84aef1ef8b739cbf8b60543d0f5a164ecd4d91a3ec8915d7e35091db1c05be082dbdb475c6848d0437cf4159459d48392bd334c9e3ebddb1421c7c63bf145de45e0c7e2a47544a8e389699f0f3b24842f873914f0c44fba407c581a1e846459f7f6f94f06047c883f3a242b481adfe50cbc5c4476fbde9b63c4520b4f8a3be3160c6cedd33daa194bcdff1ca34f6b8013f02a5c72b64d8cc0d984f29971a0c82140661aa2787856bc532e076ad10b982353057852e8d128e36ac63524fbbe23cd48fc3f36f772e4d71d585073e107e74caa074da0f8b3ad5d975661fe049048898b6535554944e48983b66288f1955db881200183e607ef5f7cb35f360f71fadb628617ff700c61c60a838aefe6e0d64049e3835ba7d9be4fbae637cb19b4ed94ebdf73e6a7b8f05f8f81a12205eca67ff281f8c5c78206165e51c3115a6409c3eb4d012b92efed55e56977c647df5384ba698b76c086800ca27851775f9abe2c652f7c424e066ddd989b1709bc8fabd3eccf68b96be32855355e7291483ba360c84229e4b0482a0b7e1f868374914c2d4beb0b5d250a9f5bc4d399d33cba4c6749c92ea598e65fa7758b0d82f7ad4327e2af23c84ef5b836a9dbc6131d0f47e7d116efca46c39579c3942da63c0a69897b2c30255fd65d0e32b3e66e66885ac4d0cd52e78d79b8b2f5816d2e6211f3238384c961498b1f3062511160be848f18d6e7442c61a2145e7191949635d1260772f95d164bc4b01d16dc5ec88b351ad8e412550f636b05123ee6b2e575b4b8ba937abf91ac6e8d8d122d38b650c685761368766f55641fe9ca2fb3ff21b79b403af0a58c8f34b1c71eec43bf8df910fbd58b12682e2722cb388c8e00f858f19683bbae6e8f41512bfd951a0d7b873fc1ce62fb04d836b7c0540af629135783f22298d33cc0bc660993bb471e46b6a4c0888120a1b903d8e4223c7c027e226e9651764254b6177360a7408e736393d32549c0f27a85b2b583d5711ef20d6f1a5974e45c8be5a1519e2ee10755fce52699037fb304713529ecea70c2e60104497557e1f46c647c9e7b1adef0119cd810cdb9bf560f941753c661c0ff6a6896038cf873593dac131f3eadd5d0a2075d2992c7483e7b2e279236404159fe8ae93ecba467631d587a8097c6b92c20d24fc7542b297191f9eea16e53fe456b8331f3de29a4aca1ff5be499523092e142d72ff3b6fbef5e78daf348347a91024a50e46200db981ae136c6593594de4ee5840337b1a7d3b92ee18d93da799f00bbaba4e7fe89f17d1d9b00b80aaaad7bfe53ec1493befc770942433fb3e776b8b6d0e0270e75126c2d1cdc3509af160c753129e7c1f7013fd539e8c399bf75a7d971341224f071fbcf25c964ac5541e5ecaac7747d0b62883956696aa15de75cc9ac2826a4610622fa6b6d18de54fe8cac73ac07b6c3bd2ea414ce8e37b7a4718912fa6bc841e6b586de090b51bf1b3a202648528684540d8734d44dc9c6037442c8ab16fd00e1ecf39119cbb13d07c3395cb7447c7b3626d10d55ca297c7c7708a930b57aad81fea99bd1be4b0f6ce6433b2f7dea57c1fc92dcad6ecf8eea8c086403e7eb2c690c6e13f26966a453cfd052e4208697c52d989ad525f9c7a5b0c4dbb3c103c568254e04c74700173441c05583ef03a8e764b190d5d1815a55f7e68e25f21f0394ae649e4e579a24cde24d79b5b330632a029a174dfcf78606a03f14ff3458effd33409bec0be2a62682b181eb745c483fc590d596291e92e4d74bf5ee73ad2e4e4efcfbcaf9fb227d7cce4c5d58143fafe64b7ffd84fb526bd9c0326ce92cc9cfc7552497fce8b88c9eaa85f64d1846817f81501277def063f9328404827f22f0f798464583e5f57de73679a6a104666a0c4114bf9f71b62ea488f212bf1e209e345f106fc619e5544d62981309ae5eb51481504b0666ed02457256b9f7d16d31d3a1ce2ecdd2332b28ecffb68200e7b431a036a04bb754d36d756afc597cf4350d294e529aba0880f6a96123494a9ef6bf3e3d3086f246beb3c641d03a021eced4ea685952d1273e0df08b9c2aabdeddda79d9eac5d13e5afa22e2b3508f3a191d2cf183a962ac3e41d8bd88e3f231eedccbfdbc73e018642a0caf2a8f4e5ada2ba47d8ed8f5a2cd6953336ce0ad1df127031257dd29fd4e85835ebac8165d876e500b1368b48c80b1f1823a236eab7bbddac9807f37970f277cc0a2fbd945e536c219c466804d0f2fdfc2d55fbb917f9a922cfaea3514b4f58eb730c9c5d1ff4cf3e4cc7a2341102d20c2e8afce4d5414854f00220023b83e153b5cd0a11300578d6974911d1b594c0ec2f5de8ec5e396fc44f7eac5bf4c7762c627aa75db959da8b7b6f5109fb5e95276c07e619729d8be3c2794ba40ff3ed3a4933efe4920925e1093b35a0696457aa0b60471d52ba8cede6b7d85317312b6ae5f1a8d8b1819e01b7af45db40356d8c25049ca896df259316fb16333f55dd5006298b5199a1ffd4ae05d3ae7199ff6cabd9669f25c124ad86399b5edeb18c81bf839bab0bdb6e740804303db9ec670e9257e1ae899667345cbf3b89019ce5bd9c529ad8ae0133115c3085cea3bb47e17155fd787c2c85a9a12a4da84403e57cc70c880e29ce6a6a7de830bff9705dfae65fae07c7b313f3f627ae441809744e21487448a7051e06b551ba1ba4b8af4a225093fcb89518039ad850be8767df49cfee383a63b77d2d77d77f37d3f48e993ca08e0971366cb4e48578a6ed3f2f22efbe1f21e65926329e77ed5c57acf088f22926a21880d569fc9061f7c8dd509849335f2fee7bee8f5d065371441033b0befc1f8ca837acecf99b3fe5fb2d6cc1632f244edad0bc922d9e3988ef3c7b1a824b981f17377b02ccd566e9f9af836bd639d92fb824bd2d5cf248609e6cdf10ec33ad65e5d1e97f63f56b59ca867ceee67df0b9f8c847286656e5f9bd5514fb48aebab97851498506a9dbb43cc5760c5c00852b7cfffc7d107b06ca2feecdc35fb93723fe9b15d5a0c5dea5798d0145bd5f15d14918c0bab94c1940aefde751152e31bcc5392e33451abb6b4edb84db1cc035bd2a88c57f950d6d64dcc62022fc8785efb38507e80ed724b202b49ca213b75e36614c9aaeeb7cbaada551b01721f5b4fb4df6412855d38a1803bf360385f164b1c265436edf02619594329be9e2afaa6615d864ad664f454df5d833e8dc13ea5ff56985784580d26f889c907737e917ce226c02f90b69594f3fe6ec007349f5e84481522d8f2dcbac57eab6b77146c5f20affac0ee1a2513a0f947373fa82b2f20b489d9145b1a6e7f15a6ac09622ad59a7572c1592389ca7c559f457488778dd9e8a100437aa3ac990b52032f39cdd0ff33781e6ed4dd04e8d35f5dbb36724a6af70c240f583a1df580d1c539c1b82ed7a556c53e48327823835a69791c1b0ea52a185dd8093bfaf4cf2b3b70e861445e5695d38d46fa6db60f9960ff07b827ea9ec2799d38bf1987a33b71e562aae1ef72c9f87d5538e74afb372917476bc22536ace662648546e918628b26d65a09a94d9abfc98d7b8dc4e315e89616667cdd261c936551a2812ad4dc08f527843261925eb128ce8cd263df825aadca82c97fd81f9e7fd36bbdc0e786054958b86fc7db77d18a7000257fcb169e582e0f5d1968ca6bc30b9bb8ce61882676b04b4d9bd9475e1ca25cc0b5bdaa5db8f9e2a8ef42867f544968a32501850a313fdb104a5517566e7fcb79d6d1a53f2f7ca1d86eedf9972f26e73d4f131886d1172f7f27bd797bf7a96231e1fcaeb258847e219de12c54c8fa2274a6391bea0a5b29160f9fd048c64f48f06b9b1e7cfaf419b16f650115e9dc9ae5a0b0e73192104131494823b95588b162636b22e02b5aececbdf2523ad4803a0c3cc7ddba4fc8da07de524be494bc6b68fba6d4b0ce76308924a60f351944de7a36b5bb764382f8a8bdda732fad61529faf0ea33bb6dc154317aec5f9a8c483b1214c4e568b082b12cac8babb086f04ce9cbcd18af9f77d9ffa46c1f3c2d3bbb5b27505a86c0538bf4e7053583222e8477c3eba9c333b37f6752feaa26c5a1f0bdd8ae77850a7017619b5ddae5ae744f6bc5fa5c5a5250d78b4a32958613ddf7466d70ba33189705439e666e606e3653af3eb3146eadc2c26c02ba48b6623a37308b7ba0c74b16581e3a603fa317883ade1ee00739c073f3654aef95c5562325420864ff97fb42ab38b5d20a6e96b262425963c2a1bf95a314fd49698da6da3ad90454f03f932c0408ab937bdaede3be1f44b1bce1db3c3aa284d943ede917990bfb570a866959c5f6625819c6283608406ce8d5b8738d4edfc19e2beb097d0c0554da3f4aec034f6ac53126ebfc3ae0dc3eeef6663aba3073d4ff18b8b54326bee397d3a7352d729f60555520f22838b13eb50e4418a70202e0352cadd22fedd86e7b45b81324f9e77bb62bd9a61d147b952f55451ee352be61604134b379e88397976f3d0798f05a1ac7ce6ebd73fb6636ee9fb4d6e6991eb4ff2c5cc1eece0a5949a802acc361c9bd6bee66c84804ca172ad416ff78148344855b3dd2003c704a6a5f2f43664ce54c421ba8f91619d5335f87c28f004ade0ed4542cd39dd9d77a31759f0717276c4791f538ef6a73e0f5ced366e60d3fc50c5c25aec7772e0c0b727de0ca73b26395a8ed3f2448a150b9165cb1cbd738064e4907560d970c7d23479bc291fbb9c2db8eb044a00a4583380c087183eeb70bcfc4a224bbbcc21118fd21a803c9f7ad77cec19328d7ef0157be6c29b99dc43bc186ce649050d3c55aa8ace5afecc03be86a6872aaf8d759187b0e7f5fa1f384b077c1581564367ee085d235c2b11d8de34fbbcd652298450e42302e9b9a43f23d7ef6cce27e92fb1844bc294bc72fe286f32760a210586ea6976039f61dcf89b2faab4e431afec5300060dd75509f7359e093b60eb8d717bf62d3509265fa3248885c95183301d9e498912302211e321b87811ccab586705332c85bc460c270a98e2de9b9b911359f03f5ca12920f99fd7483239e1c45633fc34343c947c885e9c5ffd7e33921ba2eddc321694b974584c4f39519e4990ea98660cda64322b3defaf609dbb23aada3fc7565885c935a060435cf889f622ac78eb3acfd22152a2030a23972ee2f40afe46d45c9e9e8e893b35d620a60fe34f64969a94ef9720a1f6503e22aa57cadcf50d1bd7f06c5c19c61c52628d5bc10b4580734329e8daa587d7aa6b3dbd3e2897d52de11145975433485716ece8a220c6b35e4dbab52338f95fd3ea196d515125e46611c5b80b1ceb4d374f9f0e9511dc7d1659e0464c79a000acf02b5361c0896512f41adf3ae14ae2faacd318532013fc70eb7fcc9cad3a56d336a571f18a86b472aefd737cb86b8c6690ec3b273f40b223281d6a981affd44a30df4b74c89aedffc2a62bdd05eb6e935c65eb1aa34b26473a012b555379098b318020cecf244405b0b37669f6ee454f5a7f1b0b25b956dd651c47a7d2b0fdaa99293096eeb30e7494bb7b079d526701898bca9a05bfc35741d68d5384d7aace26fb013b265092bc512fdd1a92c81906d769ea54793d2dab93ef77b03bedf373b6c86a6d8908b3d441ad162103f209961bf08fdfb2b4aa6af4c0a81c480fbf9060d4c6c667766600fd64324ffd589a255fb98c5e5a61bd1a39b36e87deb5258101740308f3b84aa852eb30bf25b7836c38cf29a3f1e7b8fd7e3e722142b5c650cc85019766e1260c8d5ed6ef99c9e740993c4cc9b79de51e5685d5e936d37c71f4d3dd27e4024876c355c7743d77bc29cb94658a0edeca78b62bd91b1f2470e952e4dcc79df5bbb56bcb1ab339096db9d1eb0abca054b68fcbbf038ed413f7cfe63a91f1d6b7e0b3c4bb87475632c62acbd6c19645ecf3d30e0afe3ed327162269733064e8e0c37821e0a5f66e8ebe6fb3129b39a91e63618e697b284b06221447f48093d42daf3287d6c076ffb4b25b8f6abe6c7051402124f8620d2c76e9537b7b66fe4141c8b24c4c992fa9e4a3b54029a8c987345b71bc03c94cc9cae73963a6f1c06e1422084a2390b1ad5344f1443b9b54ab3425371ed2f9de961163b42f95bfd82a21c8b5633a18fa424ac17cebff0e91ea898682b92e09f2a3944d1191186d6d8a604aa58bded581db470f3b5026af34dd37d6ae717595517032a8ea5be5909eb3ea041c8593c8731407cf58c9dab0f4a97fd8d8b539179c0374c659d36e5e4fede5b21325b73929df387fa45e9128a65b82490e92fa55bcab18a5b215b40d8c1b81b04d849e1613ce54061dc2998230981a211c3c08d6d1387a7b5a81700da2392e9b8462e3ecbec5a0008301f5564d8d6e001d1d2df31a354b040ce2e33bf38b12cd93e1628fbfa5eb2bdf448d574fdbdf8571769a18544004ea7a6f4290db7502ac8200841ff86570ee13dda4c7be7143940347a8e34e98b58d7451e8ef23038fe00b08e85e70a54a41e8ed30e9d1c39f5384d2cfa68d46c1127208c05c959e66e5024bf6b7e2df0538969676efe56e84529483563cfa227b37b4fc3aef32b350c452b4b256601a58c746258a8260da9741fcd9a622d29e9232a2c2132b9babc9e4dcfaab23446c7b177144e1745dbc17283e8221d07072a8589f53ad5291d58db721e9103405b13bffe5e5cdce82bdfca49030a721cdb75a74b0793486f133252833cea14e25a2e38dda55d729ac0f6265f219079f6cd2d5f89bd244704c01c4fcfab4a212786480f5c384800e68c5027f7e5ba2c4401e7f35a7490b5673b110cd716733aaa949c2baa5d5626d605c5a6f9f15e49a75745a34c87b74c1e52fb3f3fc9a257e4483741e60ecaa86268545804199e9ef183f9919712ef64680a0b6b564a6f6d5af1bcc108c915dcc1575f97cd2cdad454582d9e93215009a5e31be685569015d98367ed597d548f3e2acd717fd6206575e607502c4054c0fd41c87c1d45a83ff2c7ae27be5cf75660d256d16454a2905bf0d41dc67b09be4e41425367bc872ba3195ecea004cb2de54a3555b3105434fdedc00b89590dce8ea08c0b46130d6cd381423c662c5196de92c6e28bc73bca3f8adb22b21b0bf351736454e1df755e9c044f69a7e11e91891bec613c91037e43fbbeed4418d71c14a63bd5d031770bdd2b84ea24706f81f8e54df356f4147669463758a37530739ba5d398c73e0b0a25de0bbb08cf410e0c218131820b1e652eb61b4ebd96a7e4b663818ab9eecd1074e0c7eb4e9cf5e265a48da07e83f5433d5b7cd24e35aac3ca3bb474964183ecf669b6b04f38229cdfbefcc46f9105ffdd50c36595f864a0887457cb3dcaa404d4ccd2c1ec43b614450d08d342b375611be0c60ba448c5fcdc10478dc9e3dd7b36db2ec3494bdd351b27c9b45071b0a87a99ce919aff69bfacc3f5723964d01e0ce093c5785d805dd5412021417c200df61e762d5ffcc6bd510e17e363e82b403f4426face0a65fca6101ced42faa5f4ae94cfaeab146349ed588d74f86b6ffa9a5604a4eeba0ea2d6395007d2994d6109aa491e0bc161b17a3ca532af6c8b8aded3333b088d82507a57bc88158e6a821c3872738f5bee79902e3e7dd07c4546c14c60b6856da371dc3646fda782b64bb84753bb3a6ae208dd0157204814289577d16272f996e46797d09ce35db2271130a27ef202fbdb45ecc6ca9368827e51bd4a0c1bc906d32700b089c8226c54c592c86693cf5373c9d5b66d98408f243d3a382033c3059f2263206ff9e55edfd7e398b7692af392c47e4967b7cdb55339e01c10a34449ebd43394f4e34483050043439459ec7fd830ea28a6d4704a0dceb264ba17a5cfaecb5c81457371c40e74b52dd10aabdc5939641ea5ae6fae8d4a265e00a63011d4250b29113f9a7e97130176a5cde679fcc8180fa4552b8b60038fb7796917464fa506e112b695d5a56c5dbf4d6aefa3d368097bfbfe064923843e195a5662ce3c9d6fb665d441ca1afeaa80e597b87f245fb32410e171a52b934f22f0cc74587b5a0fd7c8474ec6f868b191c89f11ea039be9c176b997f2471fdb280fe381c44f122fb235524aa6688eadc90dd24e13d95f3c3c9564a5c68bdbbe3ddc08c60734c589f664ae413fb79f81134ff38c2e4a99a64bbaad491f1f9c3e33b2140f20ac1576d4dae702ab9617b0748bc601187ea57c9a7fc8b52685001d1660dbb9a44b78a367e19189f376ef95738b75cdef7bdf35aca46e628582c81179a760d74cbee21c5cf2c7b8b169874fcfdad907729d8fa1680b16d5eabd6271aeb856af76e3d8ba13ada8d5387e1477ec1e24b99dfbba899d54bc678ffe267a91564111eb1119a93aa4a94fef2b9c6057eabd04e66ec1f9a8f18f5cbf08bc43668241517b2396a196d23f0fb0f3f586ae008e9b85cef4316a10223134dd9de3b10447a4bf1ddd01e3497ce83e298be4bc0dfeb74a1799236e532688752eb96232c6ae8cba8d1de07ea4191cf5dd4ce297d6e917155258f408cb3b21a200f28528666676559e68043c6cd963f8ea230911edea9e6386a1640422849138ba586798a661e6e548afa44dfe3a9bdba0bc93f72c1897e209e74daedb741c75702956e23584dddb5146fc19bfd6136ff1539ee44d6c3277dab135317ee45076224bdd5605369a9debbbdb526fadecb62700cffb22381f9828c0e1ffded94ee0adc72c8255c7913230245919aca6a02e8808341027aa408e16bab998bd9edb415fa969200a40e3c41943961132a91a3e6e948c98760c31a7b14d4322689ef777909b6f5e296ff0ac8e658924cd418d5e24627d166b35033c4e26f88cca20d30a0220ea946de0ff526e67235e3cca2abbfa1a0d0e8dc5c3d4bce8a612c94da429f71e946302b0408981218ac64bf96bfcf209fcc8922ba6605088104e01494dc89df92ef5d0db3b80f5b509af2695df6f36cc34145aaa0c5ef92f65b71c035d00b1bea0a8dd9c07b5d9828c49bc0890f783bdc52b504615b1d0afce9b35d3cbf8eef4881e6e58bc7c3e5e24a4fab8f58411dead8aa1b7ff32bc932ee9c272598da4d4b335578efdc75dac6c28e6c4f6bd35b11cb21db271be54dda8f1bce86269238c5d58821b92e31f4dbc24cc5b382457d9d3eca5f52a511462a058bec4bc574e45a3c8fe5940c5e10ee25426d507c1832d62b93c4698b0f21d0e5a1e3637181d6761cd07cafac15e90e1c4c28aef13f0f399f92adbcede68894952a076f2031abe2dd81cf2558ddbfda24969fbc076d75de843f25e4a79609c25a0e05ef08f131988e7815569d36fbfa824843697387a1df150eefd107f91ddb3fd706cfec73101d8b35982b91162a6f46c02a8145a3a8801bd58378866209ef77461832a3fdd886f435b22b726b597e79454da9bf860f9d2ff2497338552f2a6bc9dc7f91696d313d6f1b606fd838913692703ce9e42e97a34e3239e8c2a654b2f8398d9fd374f177ac3d3705ef39b8b8ba49661cd94fd1e039283b4417755ac6af884053386998307da245034589810d8c1ec4ca96b260e8f4849af48f5fc79f12b32d74ea8f9996bc815af22388f8b1b2113fdbf9fb04069e4106212269009e1d86b333e312f655b6e2e8026398aebef82b59efa3269f834617cb02272437f76fda5054cd1b3f0ff927c584dca4037992377058387a18100d9eeb5e8c21f595b2212f064af1fdab83f79312818d7ba9a957d546253c3fb22901394a7d1c12ee96f2eda90f098b850cf40216118a7c6e5838c66cade6615277267f65817a4a5d62e0b92cde44ef07d415cd5b6aec27ceca491bbc0f6726f2c2acb7610caf951be1e6ebfc0086d1b5ddc6124f8ca65e4af4d7e00d2b717123b05e592776ed6aa3094397860c68af02dab76380364ea656480cb469b75b58206158acd8760fbbbc50fe963c709424666acb490226fa53770173947d0f9ed14654521b89bbd0ddcd818f2e1bdb249fd3e8b604bf697ddeb0b06ea08cc98b683b1e5db28e3c7bd6a9e13f808dbe344cda87ca087d7812dfd4ebca7e8d041da6ffded7d3080eac9b629088cfe9b01ca855f3215580d03c6ed9d86a39210be0f1b8aa0de0dc1a95e468ca8e0d6c0d24aa7b6d5e7626d55e209e955638c3b19202edf94efbfdabb9371085a51671ebe21f8e3b94bc833a393961bc72516be39a54619e7d2d148d0acfb96a97bdb193470541b8c7c6e1f1b10c331a766e321d302920f2ca6d9f154471f8ad06aef4584b771c37d47204e51e5cd3d934ce664b56d7b1079cf35b1107f98bdd5de2c8901f58b4bcc3187cc6adc9c214fc378cbd17a27001240a0391101a968b1714bdd03b99b945d952c6e665caf0727c44f78151f675a0b90cd2a2553baad22fc08eb5fbe9cb9e5b060489227569c5a49c5b6b42f4f9dcc57b0bc69dd974c7ab9f4f391b89343f84980ee6d078355c053af73a41d890993e559c54bc57917506b600c5e203ed0d6bb53680bf6808e5a9f12b55965beb7309860b9386506b94ec9b774f89b910f62dcd7ecc0a6041f3e57fbcfd8a3cdbb118a2228f5e7cc1a3d1b0cea2ae167c774577d8b424c9c209f6e2e6c74035f7c14d5c8f6f0d3d3f5790139112c04fa0bb99aebf80298c54b5000148c6065960a8991607597246a81f642048f3f20f03a601d4457c4ddffa2395760ac8d2ab5841da4768979ab0b07294f86fbfd4c0153a85cbcf0bf4eab845c4edaabc0767ca63ae3dbc9aec072a1cee3802e263d5a947851c7138d6ceddc11f2d211ca20cc92117dedaace22ad3e1590a0323d5e02d7846cd8d276c389fa78ef9267f859c4303395c52721dad211c03bce68376a1dbdad5e1ae3838f3b66b60c6a82ea7fce38e77c8f24246bf4aed615e1cb339e261b52128724e1870520143b5c8930c4514d77a06e92de2c9afb3eb3103ea6ed36de1e0b96ccbf8d66d5ddefb7891a2d98833255870bdc953c586d9c7732bec86d207111d15e26ec7c1e0cbdcd3dd48c5f9758e5169af66f99d61d3369e0e3b90af68e23332fa4d6de74183cc31d4e89c19dbb00e4f57156337bb786ae46122ce42ef748a591331f9c8ebed89d9897290b3e7bdd712915334968e6c7b5511c2e841bb1af3badceecef8ca2f1977dcfdc43003955e269a16d8d6f47fefc543d68572649db2bab9cc9fd9e6518bd2468b3ed57e8114c523fce99e131baa2183aaf16a9fccfd2c08f4cde0c842a191a3cad156dcedfcd3e7596215ef44e0e88afb81c1a5b654226bce34ba23aaee43b9d6ebf01d4f9fd823cd6a3061682bcb2ef0211726d5633c5dac1bd24268f0a1fe5a202360cf890595565da9567487c076487446c36527ae3e7ad2fdfd190885773bdcc8be08e003e7e2b69d9a37ee19f4e4ac726a25742320e3846f32e6fe1cf149c8a168b68653594890107ede55c46db54326a100c8ac73c535fee9c8490429adae897dc2ca181cc42f25fa4bd36e9be299d2c0ee1a0c4f8735938c17f650e27c7e9d4af59c6ee4c9f973fab1c3fe419a2c757b4fe96942ffe38ca31f3c08e79e08286174ca68b786345283b69d41ae53a7fc7ee43534603c194c5a439d6de7d788c8f18b0707d341e71b644fa84f9f2dc9584bca2b49e4362882960b46e06541ed0bb11b926f76a465a6b3ec4c66c24a3b7698a135454517e685303ebda04c2fbeca024a010b10a68c39f9d31679a75866456facc8327f7211bc8138ac97f698648ccfb6b8642faf8a4f2f76686bbb06b719961b82cb12ad97c5c402ca3752fa073433da06ea9e669043261086eff0b244e968158bcfe203c86e9816d9ec93e26bf32074d377fdd70c546a85f424cb50be23aa9c6b8b3b42d8c3f23bb5d87105e447e078b12ad49985a793262841691e6289eaeb0f5903848abd9449dacdefe0df1e6f27a6ff3760dcc2fc9e3945cdb44e9a76eec0b449924b078c6fcc7ee8eab4d1cca183d93d5b3ad9853da6c085e557ed7f69de5ec5742e96491fa3710ff78fcb569b89851d1de73d61766ae2c98f4ff7b3574f9e9aaf2c43158985b99f247c4ceb8953d7a81e09b99ab5fee38cf9522e376394a54c669bea55911a49731b5d560f1452f7508fdd8ffde1045eb0a696b48c911b629a73f8666db78f09f7a5d5180751b10fe2583c243939f6577fd59b976f7bfee0c3b903791bafe839b4bdb05600836f08adeccf6da8fa6692a3d4765dfdbef6933dcc8cd45f2b65fb4844a81a4f04fc5b608cdd00ee1ccd716cd8932759e690a944d4abfade29208946496857d3b9c295c718bbc3dd11a44058ecce8170e0495e645193f049236a571e47d05d1cca9fa6bf583908c3600c511fbf28507407ade7cf81ae12de15375a7f3c2548e222a9cf3661666b78fccb936326216878a971cd3b878feb4d5fcaae7f8ec1ede8f42c0aada8ea4d5108bac8760121f7802941b830d3cf0217249fe2ce52abd9e27d5ff029b58c2d6f1b4dd7cb5f77e8b3903c0eff95e85a3bab63830ec35ba933f9999b677c222f684760e41f3d34adff4938310acf72ffe45bbb576eff6df808f1aba303268835041bc3fb2a4ad35fad9cd868e23e046ddc1d1466a297c53ab83dd30a8d56f8a3587cbc5c0bcb05dddb28b655ad3f3acad49f657de0e2beffa661f840a87353db77244f87cefe87d2930bcdf818e6fb18cfa01e3b8862394728d704f2ee6b2100c46316a1596ceccedcce649f613bb04649cb520292108c5d742162c2f51635e0eb007012aad54d693cc2c82012d00ae7ec7ae06b539593aaa38f6c699a09e17b148067353db1f1591ecf36a3700b7d2af1ae393923e8dbfc64cec5509035cfffa00d3f5dcde9a171426987fd8b56497ed932443a59c3feb3820a9955300a271a703458d1a19dae5d505e33833c80eda84eaf8c8a4e61038ba11f48ae611076dbe66a001c1f53b4c86f213c838d86d560a67b0b7919b0e414faca291683e9f0301ce6979897ac1c8336b5b4a8fea05ab4c0e1a92926fa1f82ca0ebf4ded871385f0c5fa507727c3e334b95c29e64fbbad98de6e9518420d5a403876943b1612bbbb98da9d8ee56faab34e36672ee7dfbf36500a15a56e9ed2ce9c8df8e40fa86fd52a2fc03d178316e4b092630e1d69533a271cf83a8324e62847df2b2523b021d626fa717914a65cda79676ca2ef356358c35447f5cdec55906eb0bbf4d9a22ec42d6184f081c8a0dc98ebb3fff2a400ff07ccba3745b46b2e08510386d1866ee2e1d3806eeb01901d9be7564ea57c6d079f29899dcec1be2329920c7062f54948d2d15a9dc172d38643f90d57d55aeb02c573905fcb500c0512b15d375ce489ba5559de550b5858ed889d1e5604e6504405d166b64be88a0144a641b8ed9aaeea625214420ac056c5798c6ee02c6a0a559269ea67fd130929f8e34d502fbad44b83e3ae0f9d39efb34e5a8a38d29125269ae08f7f7d25e0a7dcf994b63be058b40e4fbc692add815dc296953a00d3809f358ee80a5c8c33092408ae4db0a7ad0d79a0e5d725ab3f98a549c9a21afc7f7ab759fc1d13f984a3479c4f5d3093bdcf3b637a1e7cc7298c2e15775a90286ea9861b647e04e67ea0518d37b2ea1112fe50e168db89ad8941c421b1b9faeb15ccccbb70057e861f27d51b5df6ed398b6210c1e31132fd3a721bea1172963dc49053706106b5b1fe2007f5ff8b91d3d190d4079de8e0ac0820e75e4d19851ceb549c5341cbcb680fefa93d147ba421276b5d8c6a3a8930c204c4827f80b6e99b47e56347d6012bc6f6f4159b511f7e4210c1ccfa98c9b5d8b8aa72115b9cbf2005ff980f73c426818f4cc4474980a92f2b2cfe8561d1a9b1509cb0ef1c9434c680f2f30997dd1d761f88761f6771e03590ed60906c6258c1e6c7496a785d118379df3024f59f00006492ff005b9dd5b859636fb45d2e2f5835e3b5526c9b7d6a42b0363384d2865772b370b90dd9c7f147ddbc6b057b09ae1bf91b5ecefa5c83cd4bd7f778758d7f5af88979d3d8acce2b79a26a880af2e1b7816d0006164b1f06a14cbd673eb644f2b3531d428df8946dada978663cbfd09dd1300a0bbf9d177c8a28cfb8abe208039cfd0f6cf1ca66232c4c5511aeac24e9d31a8201b51e705ae69b66b15c63c34a234d24c555c87aeb747fe0281574bdeaa33bf2b2f5aa3c5184b45b92d04d9a419a029491820256571622685de2b212f8c5a29eecbea4fdf015750b695a193f257d02c59e99ad8bf440f1246227805a95137a4fca38ee34dc75bcfca9eb96fae4ac7fb8c66084b60560d8f4b5db40c63b4692e72e5b0f21b53e4c8edde7a4205b4b4ef50d3419e9a7b782b82d744bfda7ae6d964aa757d768d867e4762e810e639e35158159d866cbefb503a24a4e77e1869c9b2d28e510326d64e264165730f8a0fa9ad5b041bd29126c5bcfd3614bf464ebca9f36bd0d443001c065eff58a30c1b7a9079eeece1e4d2ef55b2ceff75ec97b8de1caf5bf86ee1d1598a986ef867275dd8c137ee10167a58099d830e1255bde3573044d686304083dd5177180368ba5069662bbf5a4b6d4631baa8e56a929edbe30a4edeff1ea8a53c6e149190e8980deb7cb38931e57ab2382537dcc2350151dd6d933ba12a0a9d6d5738da8aa13e1a17bbd11967e7c4860bae38e4afe99cdc87990f21879fd522e15348cd64a529175cce6ab381282afdd4fc3d5efc4f9b0abc4b3a6d4733715e5d461888aafae85646d6eaf3f65f339174a625dcc7a1973fda9a016c7a32a7a3bc1c1a5b7c354aa750c9cd06d06f19a067ef8e598c773020b27018f1db9cd5b60bb0ab3c8932d60987d5455e855a1f0d29bb57d88d6bdfdc4e815e357255110a3a88210bc003f4802762fdaa343f56b7b312e9e10e1ff01b605bfae1e7babb2e6535fb8412df908374b219a8268b61f104272a61f073a99f8eb71b129019ef5910c36ce9c77274c96cad69bf9a9d7f897d0ac319395195fcc94d85c05b14fc84cda3769df5a67322ae52a009c61012ea90b329c30f06ec201bba9f94b095bb2bc33f69b3cdc440d474b7db62b6b16a60adf247f87884e985812cb9eeee6461eab6248b1d637a44e52817846bf975938decdd77e3bc25f1f0f26bc3ed41a5da857dc7e91d1b48260cdc38cbaade65d20f4efdba30f19764fc7baf53f248baad6cdb73a5d43b93ae81b529d7c69985a395f693b410b7b75d9d0f63a099a0bbd8ca45b7cc785deb3ec8d85876e42e2f2c09112e81f007e9464bdddb577cf4f2e2a9e2990f4630699bfa7544ab10a18fa4a4ed93780733b62cbb6ffaf09166d89eb2135bd9e4320d128824058455d5d6bc2ff7ed2deb13b84af1e8e06c78e35f09936afaa639acf657f26661dcf8b2f0d322791f490d31654e84dd58bae630c488d19dd415973184ae40592aeea788b31391de47339d6aecbeb8c070b1ea3edf20a9a1d6165463907f1d5662900ca7811354b70b02f41dc0854e8016e0c12980e237d7b6e3c271a429bb100de99b1d86c9313b7d70e2712b1ec05a1bbda2682199820d98c1f118e5df5e6bf30d4bce845003c5f35369622baa64a8ae4e36d82060b52e94e98b0d0d572f27276962e5b871255a346bd2b0425718d1e96ceddfbd11baf9ef34ae9ee6c649f600e71e41c9590258ebab0c1888282885e4c048e0ad16bcf9d59175187963c52d6f123b74d9f392b09a574827f4759f4151c4e32cfb81564e437ea88036ab5b9cc5787611bcf963dfbc8fdd539f39c441f04a29d7ed785e724fd27a6bf137f5f639d8daa8ffec7d9f23ec730ce881e303dbb90c9b409c1aac7af159e54092ca13fc16056b4e0d563678744d214088f805e1bc5bf08793a501e217231f0c87e38735c3200c90c990bbb42f1ff23b6f4a1207f3e80e9849ab55e956c88cf3f42f8050f7898f9812f6dd536536c12227037e9049400e353365d7fff201633214aa5003a26cc4abb7f2e953348ac411994b601131b803f0cd0f21460199a9d535e7d7583a5c1a9694dd7b43dde09d49823c401bc6d71c98566987ab24794ddeb46b2d4eca8d2ee0e7a9e5409d6d77478eadbed3088247ee41a607f9af61c8cfaaa6f59aa92d651d3f92e2e496732bffefde75976fe9d16c716b47385a46f30bcbe3193a4f1a393342826e3f4a295ba9b4911a3a60d2d8f8635b1d9eade6645382183ad597bbb11b3c192ccdeed9fd065c757415052f82a84cc4218e53889f3fb7da6f1a40edd4d136a9c0b161009ad3412d406e282a97532998fc93a550834bb78e3efcd922f1d909f594a488c1c5915037ed89ef3062aee474ecaec30bea5c60b967c68f0adc325e6a4769babdc1cdb720c6f083523df81a11913541430643d5ac49106b922cb8d1e1fb691d916e5ce0b597268f730d265b23ea00eeeb192352c9bb40541747c3aaa9a91cb51b5f6adcc73e31f9898ca6717b103621755842cdabe6a970ac29f4d11dc362505a6c2a9535b3721da859b87150e45835d21883919a43de73b70530cfd60f5f4cd4bc7c7f2ecf7abe372bd89f941d0f7e57dd7438d743d4f115526c0a4efa0b26b609a48897324dd81e1612540db3e2be94690c0c266f7d199f94362b86c183108fd8d02a0b16a7178ce59fc48047dde43e6773ab97518b1dff338dc393a2fee0d5f138d45e782465a5331d2d25a78e24818c5e8e533771d12ae5b4c4598c7ce3ca0c0e84929207b744c336ce5f47dcbc1d5fc1b30192eae2775f9e254bed01c0e8546d2db1a3152ef738428f74b8c16013ce71966b927bcdf0a28ad0fa9f0863c07a6cc4adfa281800fcf59ba3b184a1eeb8e7aeab0c405b869be02196013a7705d95fe97a5b08048d12fb06fa34565ac553f4ffb0f319c5e90ac8ce02e728642dd41c7fd8ad659215e112b9209af26d50eba0a4c950b2b4d0c917e5ca8589150a8a66631ac33df8fe35dc6d42266ea96e555eacc2a27e459784ad607a3c99da91706ba71c6f21a7ebdd74c78295b8abc8f7a1d046a5442847718e4c06cee27716566ab2ba40d93b6dcbd7ff08c22e668ffc284477031dca9d18403392e53ffa07e04f792bb288d84f7af9f4d21290d935f13d6d1b61a3064832d8f586cbb1e2532ba9c1fec362c2757d7e881fd03580a2c3986bae6e3d3ca055929d1f6788494390440dd3f454f5f464d5e10b9de90816eb1f2db97ca111ede5d9d523a5500c3194a79e8f1083213e5b95ce778fa2a8af1bb4821e1e0729e3f90fb4a2e3a21e50255e5e9058a1c1e2f19a8af01c81395aaa5429e81958328980d7b5052a9a7adcbb8b4c85cbeac7e4ffeb47a62e27c981f676792c7126903d1e9b9ff344bf4dc06f1a3050435506327218f42817451216f7cf8c8e88d45560520c6bb70f0d02bb2385038dcda2f3aea53d8e977eca135f8f77c2b2a865c6b4d9d882c4aaa8405e16b78c30cac8b136732abe277094a260b397bde782c8712d44dab5909546a301b61898c2ae6fe74442feb532c58390d56bb3bd87aef9a59a1dac9999718250b60b1a7fa1ee6259a82fb2ffeeaccb88b798e39d6c0a66efc8c7ba19f4a5bec19c9c21cc1f8bd15c933a5cd8da8470a7655e202e43da16597b0a083a22c24e92cb211cc743e9a01f0bbc53e59644668581a22bacb52fb919fab7be20304cf0cd4e6ef07871328987b4ee3481836f7af718fad06d8deeac29d2388bfb7c953cdf328239d29fbdd4f9bcd69907416abe1f835d80109ca0c375af9f838aa57753b98460174d0ae56e6f447be43a73c71ee693dba6a1cef1a54eeea4f3fe3a5a618a5636ecf60b9bab0b6bf9a21ec8aae98821f84a1a26633aa2067b096a06b0ea3d308c9ba28396eb06c98d4c3dfa1b2c41236326aa9c542bb4a1216403c0123a535fab5aeb177d47ccae9f4f43a3198dab727dd428f7156c6dce2da47404680d4038238439bb853450a6db03d108d03d0b5f4577f79825976266ebb3b591a9485d9dc4ac1e5a1dfe46716abcc89df9d4b2309d7d136552acb58122aece5de81ef36d29a81a3cd48866feb5110e8383cdb9e2e408dc9bd42f644d382266fb2aeb23070144783efe5cb071cad78f8e3f35fb7dd012a1201e893260fe0ac33ed891a79eba447adce8f704b3f93a16a3ec95d9e2ca9f7844cecc63ef5f6c3e308aacbc4109ca211373e3b35034b3d5edfc2e34d3acd07c58832af8c6a7c27824d9cc51013cdd87c2b050d70bc38238dff99286c15c7024c5909f82e3666c00a6c99710497e0d21f6a96af69efee30ad06d3303f8b3facc2e120071d22062512d7010431d4a02ce11998baeb58c346c6cfb29480a025068dec31a28798291770cdef934c024066b1eed62f7300b12e589dfc9961f0cdcb9748b6425583e23ca560cd4214c372e70e6222c2aeadee12eb1ef5e1ad86c73d42392f5e85cd89cc6b8eb48c5f98009c9424822c31000d2fa301eebcd4f46c8f2b07e75f2923252d6b5f9958a6496ebfa1534ae345f595adb8e617afb416b1935abc0157f32ce5ee5ae6d994c33b1d285e4798127bc9193f9cd4b4e19a8183827d99c78b0fbfd76d7cec6f02a7bc2faec5b038ee591a649717e8b4963daf84a21776966f0152ea394860c43b1adbface7fd2bd08ade302e45a861743749eeb68ae536e39190c25dd455a32734da650e3dab2d479e4bfb488a38d82463d20d5f9395983f8d83f15a3339b95320a5cde9a6d820397fa01431580572ea58b09cd1b790d00b01a9bf4f7ae4a2b3eda563eafe12fa1c55e28fa7759f310388ac49730aca0554733f19803c60d0aba0470ab37e45b3794c8968264adafd26d1b775c47ceff4678327113a50beaf6dd9334a7905480b7f07c90a0af51ed4d30e94682b4e1eb6db20b28e7dc258ed81837e1d675c75ce6b3c97f6a5b458b39af8b81df304126cecbd90afb4aac60a5b885b366ead47f377e8b9693558ca963550d14c85caade73c7c65212f0b1ffb71b3a9b173aaa10db0d76bc39827f612d70a1051e203f9f71f22b988c4febf1c82a0744eec8f4110b33f18f9c764f03710fa5429c9f509cb9a788403e53c05245c85998292054dda2da3cbe668d089eca9ce30e44a7e84a9cf682a62c7e81cfc3c00980ded7ff558c7105e704e3943045852a529a8e3c044017f979d8d571d3d9b617a84ea5eec4e7bc84aca73c5b8db49ba3f8d2df4f692e2f44f2e5d60ad828eb27c62c8f12ae498771706260bfa975e9fb91da664613cc4bf79450b3815e172dcd884555c7f700de3d90988da0e16c0b343d517b7017aab980fbba774c931f259fd509bacc1b42a601cac455e8d54499cef4441f8a65f2a062fff3480d887117fe1fa50da79687fa1f280557c87ec0f13baf1069f229c6cc3e599e26073d82d87481d9e8d52aaf8289355dc5ba0a31e5c7f44495b5c7df6b47fdc4ae3de1b49c2cd1e506dc3832171291894c3f0cd364227e558b919b2e063f010c44f55fd802afd34176a7f8b8eef82a9dc223d505861a02cbed259b3283d25100e206d14c06b04867ba04bae60c93618e46d1806dad414dd244a9a3182dc12f57d07b3f5cd298461fd2ddfc0f05805db155b026075d403bd94ed8490ecaaa1c2433c0dfb1732d85e32b67638ab3e0434cf2ec87a6cc9dc45819018f2b82c905b330a802e5c117fc7b6ac0986554059a7f3cc7fae1be00e31f64f47462a1785f08a5da75a3444aaebb987e4270adf60b3e75620a5535ee6ae8fdc69576c895732e8abed6239dfae9eca1c14eb78c93833def9afeb03e342aaf0a1f210bcfa0c819efbf80a4aacf75a622923266da68dba67d61012b483e62d0f411180ed32e3d2d9fe33e6500c2adcce49361e3647ca09af1037c1bf94a93a672197b1e9c52b6c11e866d60ae56db7f7ceac3f88e50cee3c2ef816a3ffa2aae1658ef41b3d2fa8263014b22b186930c175150b0e322d01a6997f13aa1c7e8264dbd97eec77bdf9e9488e6991206bdb29c11201adcaf916973fdbe6fed2c2e4261d6a3ff82f71ecfc985f8cc0d80a62b98e15f8629d40735be0e80921c76097e1202be42ed398f91f66292fc398244365bf690ab69c28fb599b23ce82f5834de627b117e0a871412550e8c5ffa39a63f71ffe80206e7af68e9d5efac12a820cdad0632bd0b2db38310c9841cbe181bfd212c8aeb2c612a9478c34c3b66a6e3bb97803a7f47a47ba7fbaa039b6e94a0d9bbf7a4beefb66e5215a64b3c14da8ec69301138ca40578273b0bafb09b302c08800600ba2c6ca3355284a4ef3ded7b485b88d4deffd82d787d42393bd4d9be12210f8218abb1db4f69b4c5512f3a9a0ca5af89784a07c28c23b17c93f32a2bbd137571d8da3899535ca533ab107f7618893f83574d4e393a6e452fbd8de3b207d84c883381d18204289eaf9b72329835a710a76811e5c3a83e76c95c69dc68469b23e8123983d57f2eb8baf1a0c7eb8ab9055c3add2dd6c80ff1d90859e399be643d2ad0119077a70c8910356fed250be0c156c716530b371d94f2724083c11a24785fe26fb6d6a021ac24a5defc53c422716a024eb119b6be59f2d4781bb777b8c6abdac66f6e0a7dd91e9271dacc29d96dcb64a74e4fdb60df9432be2e6fa577f182af15e2dd7151aab49fe4aba0ec632d61c4d0836bfde8279f7b2ac220dfb88bd5054b85eb7de72e91049bd2d3560a6826b70b56c07a9b30a0e6e8f860b0f53581fef239aeb6e3b1715a98e49f66cb94844fa1e53fb4d9d6f2ad6d08bb6d3fefdba7e8d2705adb9700fcd5b568be5f9508521ffa257d27ab3c52be583983c06e432a433fef70287719e185c875124ddda37605535baae9c115620d1a3a33cb652c44e6cd5e825630f7845f3fdbb4e8f8aa414469069b689dbd2052091578400fffb3606d2b6a983ebd0050615eb08c524ca96e0b152d9edb181b9663d66a65f4d68174b38a77a94acaf0018e08280e14f4b70c194521dd7af0051c0681412720d85dbe2addd0e11812ed7f96b8ab79701e9288563a1ad98b9b7d6cb7259bf7b96e101e873adfa7f37452beadb16cfd6390f535876a511018d401876d01c4eff89d26846cf31bef4b2c0af929a4b44d323f36fd36a3dec55a511e237bd3a8ea12d06e3a551ec618992a4bff16e8741e72e9b9c4629f2644cc05468a8a5e699905d2e334ebd9a460f86b253ca1dee5f03ddaa9c61540b123744df6fbb8ab839d0569f9435273a219ee7b5be695524cd75a1612a6abde921e8f4d35e96383f1d217ede401326e6198cbcc622f0092ac4b8b6bd5105256d05c1a0c10b2ad00fbc3d0efe3762d95fafe184b0e504d10263bdddb7d225ccea2d77bd44dd1b051859c9c9ca0fb42f0084336f56e76683d4462f8c109dc32be30c3f1db4a7c2debd3251d0da823d596607cfd5fa4d6edcb930996c99909676d1df234d649d20d449a65f524e63eb6a15c36eebe877e8f3f6d80e4426f204a94fe1d8c39fe7a63db20e48b0872c161b71b06c3349bbeac13304685689b0f6136bf8cf28d94ab5c19991537d82b819b7c034b73911d40015fb7f730b9e95e4a0c7a732f7a4642eb09e96bdf94ff72863a6d71b96edda8e3123990a0a6d4b8b9f2cdc852180ce06a0675feba556293954d712a6bfce719b970a36a7af78b9459464647c5cb1091a98d4e8684317d57f160f5e936fdc83e460e304fff1afd2ed9d91f3f092409d416bf0a530bd4ea963f1335cd72fb2be9f2371caf7c5a9415acb5c20f1248550225008eb1e0b4b2b8106d03fb9c613966609fabf6f1e454264a77ea3c0660676925cb4650d31049000c0b5bdd0f91bcb30a7daa33ceac95681a8630f522e23c96609c79e07d51a20932e84e6576aabb3ac4df7d469b33adce01f78b7842432f75362309b3356a8f111be16cc4c2dcc631bf3c8693277648fb09f2f4a8a8575953c303e53742ee1cc6979aa5856666ff229dbb100cc950dfde8970fde449bd9b1df47f5d0057395585b8a47ca89867ec1484f5af91d33bb72651a3b211bb232b5faa5aa4f2fc56f1cf3f8923c523d9322eadd34112322477b857ac8fd88bd29f2c6102c630fa75b884d1f5547527db4b52c20dd1e26071cac0f0c008bbf97f790a4d8ddb5cbcee08aa4535172ce79e0bd948204c58304159150bae679187d4590e74ba420ff6ea74c3ba50e2409b43d5ad1bf7107a7e3f6825d7af5a42913c06fa00629bb00945f61782f43a5c5e183eb5d16179c2c1c918e7e9f93b9994158e84ef3071f3584e6453edae1ae8b076cb608cbf7601c8902793bbd53eaec0cd5f95c783746c80e1e1cb271d2f23c82e589936bb50bca6916df30f0952b1ccd9647d40d44594d0a58ccc13bf321186dfd788baea54e66415619b81fca800788d4a3c7b2cdfbceaffb5aa9ff522fc216b02b2ff020ce42ace61241c03b98c1bd69709b32a583482f1d7bde72f614b4bbe17755b29d491824abce5ab9f118af62a483716ac170a7a974edb495b1007175b655ca666f71a041af7a6c954ef31c80e59ff61b2f545d3e7c9fc3b1099c5d2b06083f3727e0c440b8a0d125491df16d638e4eb7a2580598e5017b9b77d516bbbcaf8fe207bec1c95e72168044eee9af75d46083fec6bbc7991f96533bfe719b4fe9438c07ef3aa6b3cc0d2951942a0a90db7acb146fcaa26aa68557eca8bf6f0127642bdcc3ae846879e924a2ef33568fb5dd598dee0955667677c68fa9beb9d5e4c094004501362d336bd42954ad884841981d8662a6b29554970b76077b426d581d230f0273e8aa77fbe2a794eb29f21b752b8db9cbae7def47b0bcffb390c17a14f28561808d5d5c56b67ed087e4417fdc408fe48924cd6b011744fb6d0cbbde14cfa768343de18f2cf7f1a9c21fba034ac0fb60546a4c44f04e864557cd6ed19ef381a69a031d658136b9cb8e32517d3a4bff696b6055300014c75a5c748fc4a89f2191349400a7e45e1bd7f94ebdf6a289372f324b94e757e051c64de1444e46f0794acc07c0acaf614380ac8592087730eb88d5afe1843d39d41246138c509cce62c83898a659d90b3e210b05bd66cde7a8e238aea04d8cacb000cbcac7d8fc3da01e480c97e1b8b99381791def4d83249e6a339d8674920a2107645e85d2eec6efdd7dc700374876ba3206a0f52e42293c9968be01591b40ab07e6f17a9126b091add5281313c44acecd3ff5b3a49ca22dfaefdb45b44486efcc1e74a9b87fa3c1d974d22686adc3f0c4f358f843bb9c2207ca2e3a761615d58ffbacf889c786935ffc521b1585b1a5456ada5484fda68255552d6b74ba913ebd8b888afc4a0457a727e4b006fab05e680be488ca37af3a5a8a9ccb6f067e9d064ad4afe4ea02bd82e395193bbc5e10ad31d36af554a60e33b3c8641fc1f25764ac11fae06543a768c6b8e90e5c8e1659d12e5a827136b32a188da3ad93da498d6b09b588831b0077265843c902eb3d64314483a0c9b7758f34fea232968bea4cb879df86a59fe6baef150db214635358c19744dd2759477e8c8cbd4a8589beb19c2f038c1791b782bfb3a2d20aa2a4adad8bc8c1a61f18e72c31049dc34e62db8d08b052940866bd0f0af95456a462d1787aabf61fe3e939cbaaa236aca72a3952d1542075793b06433821746d79ff75c74eda71b56a388abc174aa4d2a649c97c66156da0784665a8e3400f97362225ee3cc8d6ff70b3b968721b6ed53bc886da0d80acdb8469e3d955ba13e13122117e406c8d6b08579032f0d12743fd356de6beac3faf70cda4ec1ad3dd56086dae71d2fd9dd0fb89e1fc8dc30b44a6d7823588e247b4b59d9216466fb80d6645b6f1bfeaa21216b14eab1ac20f0181793209bc9dcc63e358c24f0c03fa02b085d760b5996ce8cdc2a2bf9a74863f391f569057f594649d616d7378cf27b7cd0bca6e74419b96fe4a9ea34a1c1dda6c5dd1c0f949c7d6c0a16a97d47a141c2399dc2e3146aec6befe1dea2be8e4df5c6f24764a4bd75a5d429b7aefc9f8fbe269fb4f5a97a83ee33798303d17e0d64d3180ceae9d80a1d2b9e965b06fe112e9c8458eef9c225ff8644099f54d3f881c5bd592796316693b87bb147635aef2b49708b9140d46ae0984ceb577b8e764b0be2e297cc08c269cf294a1cd032d75b772ad2ea6a6f362cebf79cacea5a55d64fdeda9e04068e9c45205833c1526b26098be7527391b249238f34d4f5fefbef43ed0db373ceea92e5a774e813906499c440efdcffef1af373bd841a115c95356f4439b49fc6391041a6020bee64a6b0bf45272049af324ecc6e551b26cfffbc955435b9c46efd497cbfbf6f3a173c81d73963319e9920533272e6b28273f565b973516a5ebe8271cc57fdc75e4283653704f86739c04d7633b4c8bf42b6632d43117a427d62e0586584a98b289d2dbd1e8164c0dc65fee39d7f49b4acb65a2b61af816165edfb304fbcac39b73d3466f29e140fcc0d46f8a995374fa40316e325f5f9a1e819d1913f1287ad04ffe95c081a099a3e50639d3cca53c9ff12a9dd7c3f543eed7d8d6c05919fc1b3a3811aedcf15f6106291dc1b126304f7c3a313e22d28bedb29c49f7648a398bdc0defb524d523fc72407d0a6e19cc6b36372cdad95b35d9eec071e3cb3932a36452e7b5a50f3f2aa08be2b9e3e5eefb6f40272137fe770a1125dc50f7d4e888cc43b9ab31d0b48fff3d652ea5d4f1a3def16b6c5b1935f7219ccfa6a83fb4c6393b20f816e3482bec5e9c4cc49696712eeed8beb3d42832f025f1ae07ff70ca6754e4d85429c5073744b2ab3cc5f7018c00aac942f5da0bd8499c6069bc8664f58724126c20935574669af7c73cf22a2209073d6e52a7b6b5d358ea7424a95478d9a7a7a6d994c236cb7f12857f02df6ceff2e3bbe17397a3ab768d16dfb48e441a3492f17ae004508167a32e68bd920ec1d9252d18c3ab16d35c75034f52c00cade4c9fffc1ca0496a636888d888837849f8ea93b4cf0fd9ca7849f4b1a25feaa834dfa1d330d8848e7bbc9851965d3043158436280ce89e8fc030e8e5d92ff88f72baae868fe6d99892f9ca4c835d32978b4e07d8a8561931f511c7128affee2c819d21515e3d76c0143fbbd11af9df5ef2f770c82381be62e97c62aa32448482c852be5222588ecacbe45bbad859a539ddac63812bf1ad8ee784bc3c2467f2ae74f989228462b5592e05b22e6f7b3b1e46f8da398033a470f53bb068d192b7aa2a85b81983160a6724f2a74d7807fae50b6940b80a59adbac382451d1b9a126bae4c35aa99bcfe4803d10a63ac2deb425ab4d5a5930735b606df66e714f209d0f3530ca6b50b668bced92cdd43479084ac0eb7adcc1e5ba908253ca8bdda4bd536d9264a0575747c46465b4d9f72487298ca1449bace551d6703d98e4f7c31fa84a6fb4e469686f3044ad214565bc64f1389821fa290ceb8cfd6f1f571383564ba4f72938848944f8e96c467e4f246286e9b35e755ea5a5b928522f41be21bcfb1ca9cf4410e5136a0b31bf40cf291c8fd35bca96d71a55273dc99d76618a590374a55f3fec14e6eeadf308f29acd0a44aee0002cf79e7bacb05f236e103c7e9881883547f2d7294da092b899a3092e3b0db220c70fba111d894f3403129fa4c3d49b447e058e1cbe5ee2fc15f4e6a58e7ec7e6b398ccea54536f9fb2bfa1bc657eaaad093478ba953c88ff48804191a4360422dd26f2bfac3820c740693a656877033b3f7d344d39cc95c98037ff95d57fd8fd88f872355bd5a55dffb9027a7089083a5243bd5a9516bfa98e2c06b8186d360f4b8d7d37949c0f4fec7cb4a971dc4214c7cccd364730a97860ae8529c89f321328ff5c4501aabfe9701f6b257b1081de28a92876f5d62efaf35f78b46e45afb92e1f6a08372c2b2f84780f3fcbb22df2cec3f2a0e3d3792cb120c21daab686a44e22ce2af5c66de7101c19ba18fe442b6095c67a7f8327be165f065b99ed57cd10c154bf99fdd580084312161a2721b197a9a837d570c6616fe1d5203098c0a661995d0df88326039a712d91f388149d1dd52334a595e64f7e8e4f974fa0d3ad91b7f86d8891a8e103ce1e4b0edbab571680109b9606de7d492a58d944db6d608629b05ea89674383ab5cb2ec33698878fe98e8f0f2fcf538de1130c0a87ab6db37c976286ae40146a6951c327ba1e9cfe66926c12ed3a89a0b99e14fc9e1ecc2c4e2550849fa43c815b51cbb97a747074b3e24e4300fc02d465b0646347c0d891221f6c44a29aea622d55802e4d47df29a7023868fdc7e9ef256e70026a176687d322478bcd6521178267f051287b5475b5d2a50790a4602a36e8d10038091fab3d5c0a5cfccd3365abf1c4bb9d671c94a54b37c83a81c4f4998beb073c95471d019dd086b37b0c9ed5b7c674d9c0632d6b0c9e84b1e3919507209ca6f92cfbc534a161b281d1b76419616de7f9d5fef763194a10cc574183203e5a6252a8b031b706ea316e07506c695ff6ccdfd80f9f10893e2ccb1209dd4e500f2b94580f22008147a337053d889769dceee11b746de96a341c563280ac73874fdd92d32b5e2d5da11269bd045e7e229a7abd6c6014f0d7189492456403196fa691d971dfe18daee1ec7f842252610dabdb5b4bbc885612f91cf06b42cf7c591432d5b11145f45dadd06b6e0246845bf7ca92d8d63370d9136708a20eb88ba8dd5204012be7b068dbeed8af8913b2cb867788a1ab9d16c2ca6c181ef645acd4078251fe84f2db3fb1f69f3f0887c32e475022142c4c40e9e3e47b48079722204eccd97d43ce1607d1f4d3ca8f1a18782245d3f7ca404c7f172b69dc18190e45dff1822926113eae3857f3e5237b26e1b49d7c500787cd20ebec23192de62f26b100d68ddd458b3d553c7cbaf664b2ec875b4292b7c4abd98338eb15b1cfdedc99185da8d4bb61134b3c77fc20838a23c7af3f2300a8b358d8f1df1935f694864a4e0038ad6784d30059910f1cb566d799891dd4a2e443073766644e40f6794ef7e233383944cb8485194d0f27cda4b56f58e15ac34c946fa5ffdabc4dc904230a21dd23b6ef57e7ad15837d599ce2acf40f183bcc75fdef1ee2eb2a36f38f155b5960a7239d2c61a7eb0be2493a638f1de9448dbcd1efe27cab4df3ea863fcffc8e7ffebb212e2767be0bdea680d142fd52df836261f08e1457a427de83e0d6729b64c9b48f7dcff9a2783c9c43c4d25d30e894b39089007442a0b16a7edda9d2c34cb18b2359b9ca2e526c500a8c23b0f6cf24c22736cd8ea20c91b1ad45d9b113a3573e9af969952d7fb344ec95350b76a92c293222feac0119ec2c138e7904297a6aefa6b1026fe3fc13f359b203e514c1ccf40ff2f24e39882fd9bfc5e5bdfbb2db5192b2731e6aa925116dd6e8213a893d671442eca155cf6fd551c209b947a42d193c6faa0887c959fdb3a82a268604eb504c93c2786618dfd68f164785667254114ee1e964da0ccea1fc583e015251b2370dff5dfbe03a1734714093ab9c60ae691729599f7ee0c99bbab2394d85144e11abc54a7b003fe0c0a4c755076afa44b4c8f92d8e4fc34f518dcd3488ffc008064bdece8ed8750705ccae9b9c89727fca81929fe1f73dcc8a0ea259e1ae5413ff4d290c5fd4bed79515aa4ace5d6b87266860ec02547f4d4545ac921c559fdca21749bac99240dd742f259b9e2a1b2c80ce5fb1d6ee351133a2a0c8c574cf66b8e33da1a7da0a450042637ebce0a07b3ae41f2df1697b6b53f4924d4eb79add2800b9addefe189751c8d61f3c61ee397f9f945b05485287c236e191a85f1843d626d4d37a4b39643f37046265c2aa1fb67a103c46ce8c5906113fb3c64ab8a80e16f7180758f5670daac777553e6608cbae01dcae262624e6794a1a8102c15424e7b4c1ba5bbb777a6268f8b40307856fdb0c3c3daa959cd0ce8d02b36e436bccb3e3519c61fc832a047049803fd3d946029e4c1af5e72034da5e63a1493c4f95baa0e756e3062fcd8ca4aa2311f171aea558d28feef538ee45f44d7e73ccc98dbf838b79df02f0d390d56ef5c13cdec1197bf44732e81f475797f28a321a5279284f0ffc03c3a53ad47a51207f2808780b17d632b158bda015252e77efc3d5d3ab129aab12f062eff46943811824f0998d0c9b22ae77c28d74f8b3a3a01b883da733c0bcaa555943869fd3255c55a827f8f8a27deba77ee61516c21bfad1dccfa81477a3b173cd4de5f213e098c78ee60b7192611d8b1060fe1be32d26b363f8501dcf9588e55709f80224e850b91f16141f6f7f85180af32a27574be6e97f97de9089a336101cc9f02eb26cf14e5ff6ebaff206f918ff67210e813e8d628a6c29f35b9308c826deaf917358fd00dc005618f1162c5747ce8c163311dc6e24bd35c4726d6e1a2cf169731a983f6dc73e856f7732e3fd3cd03f62b19ad0ec48848c4bce1b9d9a33e7b730c2d95dd1d604300bc22b5d8ebc42977085cc6b8278db949336c6d17b136dcc2ecf16c6c7a85b7eb93a621c83df3fd95fdef4185398e9b38e715ee54b2d15d6f1f8957600bdfe0889218e99a6d1f9ab0d42fac6295b1a621e5d9a3a14ea5c945554eedbde3e49f9ed13d165c5ef53513968cf6409218a12638f9e1f62c234cbbafa7af694bd4b5a8a2f0aa29507fc4b6ef2609e8e4adb1a37aff6196707eff83abc867384979d76534e18b13937935965add1658b77f7fcfce48fc9b621db60ef3136f6036d51badc116fd363fc691d4799f3ec59658a06a4fcee607c6d183367e20c7e44737e9e322763517581e268a2c4b6d2af1716fa89248b9d9d56fb66af071b91b73f4a2c1edf82a71f1a663c7b948f3803e24246b69f7013906d006fd4b6fc78a713401b55807e12ab0264fc3fd481390721c22e483cde01f14ed6b865b252617ed1318507bd2d615dec9c08c5ac8550de8ca7bca92510c22ecf91e25deffe9c53db3fa75dc2251b0b79bb6e71c69710a67a51251ae6903aa56951e7fbe97eef9217ae59636cc504e366ea9ce21e5668f65bfe121a89ac907520948ff878239027c73ca9f76293d6e7a961c12dd615d20d6ee824a1bfea6982fdc49100e4b55799fc6464cc75770f0d2eb909af54b5f4ed23358a3922ff090830429775f0d8d09eaa6c61190acce13e697ca38bb8496afeff63c8ed406bf397a52cb80c1502decd69feb0e4aa43778c14279208512b1712d0662a41aa8c214a193686f0984bf54895a5bf740588d00c1c24d706128bca2d232a7a9e704dcc5523f7f715b58192d47b601209293df992eb5408448f4d5157aca6475164aa9d22cd21cd7f953ce4414010256dc098baecbefea40be61a0d3c523776794383e30b8ac8a7f866d74341e610221088a56541f53c1acca5ddf168b5811c7cc75a215adfcfac208872fc8e8ac73ebc076e8ecd3194fff60ca33180080eed07df871ee605adeaed8b82e58b716e02e9b59edb2fb229ffd39ef732e843280213b53b1274b6359e7b8f165bf50b0db6e03bb08f5c0ea9e2c313d387ffaab9a8a99614ddcc732153ab7e179a1acd5e9779416e20be403b71643674bde1c6ee4a1707ad910f6bebb40055bab06478dcaeaa564a1a3bc6a2d15cfd6ddedb7c6c22a2c31d088c4ec5682a171d4559e852f60dbcd86fdbf015c2c1c3cd1c779af6d31d4555bb2a8647dbe1339039030a8ea15499572211a0d3e0b1bb139e7209fc6d5cb4f5b30a0a449876ee4febccb3285e456bc0169c7bf9d0687012e65d6b397373ab9ba4d7be4ace30868b6df48404deb9eadfcceecee4294e09145bfb231c81aa0c809ef087a0d5e9c5d3ed5665e4a9919b00c2e47cc0d898c35e1ddff6a4a7cb6620adaf2239145bbf474ec18b0c55a66e68081334d6bfb4310ef1b7dedbcbf785d8b216ea6f21efc1dd191cdacc3d393e6a4b4ce5f58170c2f1da88e651c79483dc996f690b304e90b7ba4f7a552fdd6d5c7c393046243979baed5d4ea3d45a0c0d3f3f3a155b0f22bebdf6291584b1580d67533617e31ac8bca237aba20bfd7da518f1c671bff0a98c6d7dd94d36b8a4a6e558d2ad71bc05ad119a14745d7388f675b3e05c0dc704ca015549dbab82141f23d08afbc1199aedb87e52937213f26b926b756edde732e9ff590eef0d2281a3a9ff0d4710c68e3f62ea711efadc71c033e0c48dffdec095de8cb9011dd1fb0d49f8f6c7f63897ede26336f19ab75786e8b59b113db54112149a15b6ddd4e076c2fe2447563946a6afbb7abf7381c19159b88d73bafa470cd2dc93f8f488b400aaf1c3f36c69868adf697fa6cfb7c07de556ebd3ea1fba793475da2fad0e3576b3f7fb41ddaec6f9fe19b904d9e1e082b1a13655653cff02522a5cc6f9260c577fa62853e2c0c161f041055fe932ca909605c36086b1430f9766ceefcbe1d38bd19f030b7e1ddad088d74cf00b1d21b59e78087ffbc06c7426530e63f6334c767d3f89137956914fa7251679736268ee72835fc821e815f1bb0863fa59502e2dbf5b328e51eb08acd717fc0b5109366411e79a4d93abab9ba6d596abb6434af8c80aa41b89ebcbe833887793ce6bbf6ebc615e6d91b6869016e5ab9a879f0fcc3f5de0b736af8018a916cdb4cde0405184e8b7c97841eec348b79ace133a97a047924635ce63b152e509ea19826b58e39d0dac0258c1384b45473964971e2f029adeebd6296da94dcecd3c988f98b7106ba791675d02ff3980766a4aca9c2fc0c64bc5cecc87511e9529b83ad07a9b69b3ce4df01308b4022d38598d4373a8a4bddc348f72c9c17fdec9bf45efc57d38ffc0f36878eef5091eae86e20cedf0c9ccdba1a7e90e4f8932454d8538ef1ad88a18d9b87502b3e8ab73cb34b57c67ad301c00c75b858c1f8e8474a90a6b257bf3bbfb3dc6a8f2ad8616c8ece13c530cf966f732e4751491339e551665c2592c749d6d76ac915a43754d6a9438878bd1b6b98a5667ac7d62dcdfefeec079ff34d6fb059caf40d1cba8e29e34b5463170f17f1d67b8f17dc464dd4e90b0ea8eeb085590d52992b131767e740540ef7dc321de2edfbcada67284761581d634fe919deeed400ce4bd3bd40e9182d88d94bb1c9625e90a6ae2b9e55407cc6419f626348521f394da7ab6668ce89f191c37e859f707c3fac66d6dfdee1995b5e4c2be358469f8f21b61b515cf265b8271c61f0d0e20e41971ae62246051cf39c30b26bff3102a8fe425c092fdf86b250bdebc9f122c325cec1afebcb5cb1677373ee9035b7a97413c397461e6cd1b276afb78cc24fd065d14b14d758d6a706839570ed623301e88e3ea25b6c640985d89fa4fb1c974b347beef00a65ed9b3b46e3b53cedc7eb81583caccf80ee335484923cd2901310328527d1e4647c3a140d8ee0f75d5931734270d0a903b2e7e8f21ab3a91d185491d650b2655bda2c94c2679eca0b734fb11800852937a44b10732a0d78e56a0c05bd43cbebc44802cfe8398dc7875b81f10aabd1b04252e32c7bc7127203b8a8d48e6c8592bb6ef3e38445ec858900a9349edee1d2edb4c7516f1e6b8f63e0300fc5d59d89163dea3a910da925aa5362b69b9b78532907fe43984d1f414950739515c9bb76b2370c32ce3243cf9bd79f50ea925e4eeb2597aa0db17d727fd554365db13216938e5e9625466fa788cf8167cda9c7c4c363cfdf6a2c2cc83a2fcefb05f1e763e23e948581623ef887250be8f7474a58b6c445ca5c2b914d2b297dd4e9ec5ae716fbf8adc004e384be5cf2e228e4dfbd417b1abde0df356a753f720c0464c08f84595851e3c274c489f5a9043e5ec425ac2bc19009199920add5a5825874b508143079a6fda34099311bbd8365b26ab7455b8e23ac5d38e314467840a819453f2a4d7953fe78fee836710b84709adb633f478dc67c71554b7639357436b2b3b2101dab033a89fa3e9587ab41ba9158ce9a7ac3a0faaec4dea58ed9f65062aefb25da16c2b6d03cdcf5fccf93cbaeee7d65afd9fd692114e39b8ffd4be987e896a2f1927a5079c793904e35827c42fdf24aab2abc9a4046a254330d59150c90d7921438587c15c5167bd15af008c1eb1aee4cc66ba8e7999bb4b26d83b4b2f54edcd8afab57c3de28e07bfea92e0f5587cee17edcffa5c867b51c14fe023850538bb1a01e6c2a349d89d2caa0a68da283d608d11a17c173d69991f10b4210c2dca863c3bbcbaa93513087360ae80512b4bf7d8f08bfc7845214f06be88b65a84a5d8a4062b7b98996092de60e42fe09f0d4acf5bca211f574a7c6d2c14aa2b10cf8f774d2f199822c9a0a9b2f88aeb6763e05783de592021ea4ddd17d8a2db57c4253b79b5a914c2e446623fe33dac06a0f28fdd9c1bbe02f0bb9ecc52f9b0cbb68e81338b470f4ddd10b8e3fce278bc87ff1c80aaa4e4bfa80d0b18a75f487fae401f3ee7a09344665e4dd77e3a96f6da5aa0e93496f27e60dc4ad6679764600343ab644bfb80bf5f1dccf9ba195f602a1f266a060570aaec7185c53513d5c0bfbed38f29c3bcbb56114d5e2054fbd65a16224d684261f76407d2efa9994ff79cd88d959021ecde2f7828d5c2a66e09777ed5209bb2407c6fc4af852bbbd651769d2194348df8f70bc2433d5a614fb27f7111426d9e34825ccfe212c50a039cc201d870a89c9d72552731910d909b94dbabbc02ee45844f06e69f1c926eff1649af3571267ef36e1be25fd107ee379e1b3efe383aa35cf4e791cbe8aa0ee35d6efde058d8b2d3f5d8656b585f170546db7c75707ae3e750617724fc7656bb46c8a41c7f41abef2a5116b0b5ed5bed815a6ecf2a6ff783fc69948fd3bfa2a9bd1e6adc5b1b07b1c65330ef1e927407b46890da596b6ad4b410446b108941c2cc0be01cc120ecb03755061576312d1f2aca815993be3a8459409297ab4fe0beef9fe4f2feac874adbb4e493d84ddcacb4341ab1f7555a081b0a835de750095554def84830fda8097cba0087657b45817247521d4279538f2d8b38173df3cf9711a25b6371c713f922ffbf48a2b93e35d74ecba24a7f785c1356204c1608388fbaf30cdd593d928fc4767dc52eaa8d99daaa7c155308e2be0aaf5d61c621d705f5b9e1b69748ad0e5eebd28ff35eee89acee8c5f98e8866f17ecab41caae37ce96fddfe7b7cf2afc8bb582714b279fcf076fa819410de113f5e926a038bb3c54b868efb353c8716f7b90656a4c5e94e1a2bbe2acc2b943de37d44420a042bb332cc07136d10d059075bf7f0630cfb274ef924bfb70b698c5fc2ff8dc3203034b44201e8517f0d344c4f273580ffd00b51f5effeace91dc8493143fc68584e0b035ab1fe486075be719070e979c0fb38690e50366d6fb2157d525b49e58c96012b9ff66cbcad4f4f09d2af00ca51530c6fafdadc876547314505202f0923ef3ce25a98528bac73037d7d03f0931cc2804bb51963e4669c81f020c86665de7ccc076cb2e5f0a6c61eb2b6092c6bf9cdbf59b889d41247ae9f5d1fa99c2abf4beac80d7704e1d03f129f4c67bf6d9fdc27e3fe3f1e4a6c1bcb5262d0dcf77e3d5d33be9dedf405cd7e1b19794469b0c32f51a47bdd11bc49d9b611717ae0b1c458c26da8330ce26f168a0687e172c9e1cd8e7999bd49495de471fe27abc93f02ccd1816bd47bfde208339c4784c89971e515e3458ca197e0abda53233554221d45ce0b105bb5e2e26883c5651b198e04fdf811de7126efe28134777a78c9ce045f1e2cfbd79e4b949753fca0b07fca053419648d0f1f1af74c88df2a912fb94e7145e5f1791be613bfa31b8cf9e3ea234db99b0f2b94a2999f7d13ff945c2ee190073f993c9c8a0cba6f5f17ac67e94395f27ad3bfc1ffbd857329051f69c6d97f3b2f2d7b6c5775ef38a6c2a73a6d506bbbc641cdb81696b0fd1c6da9ef96fdaca2f4c7b5862c666a39436d309f0fcb757c5419779a5f760f0bd45ba574cb107aeafabd4c801ab7cbdc55eca78db89d7d4225ad225fc32b92e8bcf78636d6f0815255a412993bd2683ed001106c9946248b50dd48329bb8b084e53db61fe6b1635303a75a81d0a442cdd16fba7d7305dfa0bc1711688a4de415771297873be59efd26e2cb368218e6cac348af3d5af6d900511481139bf8aa4533db2d9ad53d7ab98fd0ecb3945dc91bfc5002aa1a8d60ac2ce8c2a359b74aedef4d82bb5cff2c25b07d90b078e590cba39fca6fdd0eef4633ccff9f2171d50a08a4c89ba02f3902ca0cfcd6ef01d765a6b326f7517b1189dd116182eb97c6883eb6a1fcb93104ab379f0d13a147c6cf3dff443bb39608bfc4395640b46b922ecec0e5ad9e34996d12ad7d49232a61e7bff80a484320d1847d069aca06f7d0b5be65b163a0cecbb57610ab3a1544024e5edcc6463f630f671de5648549fefaa62fb29072ae231cc162621a77cd280a3e3e760943a4e7764a55b960b42e2889c52917d581974c86607120dc302e177a52879322bcce8ab67f308477267588c4e9bafd2a2a59adbc409bae9e821a437413a9c69e2098ec54071c660bc1afb9a604aafc3eab97751418384de451e7045ce0eeb89a45fea6de06e1032c3f17e411b2934000ad1d7331372e3084d252b5571213f94a7d1fee6d3f98f4476c3ebde4190ffdc5470409957e13da08a6f7fa0c030f5770d84fbf666c6b057fbb8f8259aca60d1de827839f8e4220858572feabf4a256f2a0f68a2d271e39019845a6bfc5eed1637e1db6ee987a60c9b39c1a8245b100af2afff0abca9c69781e8a9bb805a115df7ad0ba968a02e08101b6306cfb09b0117bba26bd88be08ac18463fc6f31726dff0fd3a4b5f89dc1fde86271736d4bf4767717c20a3d01697ce5ee058803c9d2b11a8ce79ef0c3acfc3488427a410a358f115762f6bf8e6cb944cc5a184c9d4c575bf12d5f53e5d59a887dfe16377a614a230b9e6e0f0a4bb1c6b4496d5a0206b96ed70810830e436acfa2fd8e869e62a18f74f2e262b5575f87e72d771ab15485b77bbde2d852471b3bd34dd4635edfa0c7d40db6ce8b18e448f53c22f69526e46960b548cca998d063e4f5c71a570826ca2029f6963f3e860cdf53a28fad72748c5b71519253d648e72f5a2fc0c6a309aaa9fe3fa907d4a8d28d3bdd7b2c9dcb7349e161a172ce488268ecd076e7afd9e5937d770372fd63d0e737b6091c89dd819622a899ac35910da1c9e4b9a81f1437104b7440a5cb594e733e9ba04784da7d310deeee5d32ea838d68c7e39e46c3d66a3689ea625129789eb5aab8d27aeb8d80e29bc4f288aa9b2ee611384db3d271bc3e5b213347f6a875ab104a793295218e91d2c98bb77b8a13ba503db56843f84504669165821d9c23e60c449318c3a7f9475c3b332d3cef87328d60a683b67c417a18ca8d228dc95a431616d9417fc0c2b61febaff84a19e8ad9dcd6e642d7aa7ceca9cfe51f9d5197ecebaac4b16e22df4f315c376d14ebe2252ddc079187810fe318ef424ecbb008bb4919ecbeec197fab64fe8093bdef3093d0b07eaeed3d217ee19302cdba21529577f76a0c3dd1e2de547be6a8f87b2416aba5aafa376d63e564a05895ec33f99f6ee6237261868aaa0ef642f136c4ab81df032fd8f35349e09e71ac5cf09aea199b4f2144629dedd0be5db85ee83e7aff794fdc44a85be88b16692fd7b76f5d80fd20fe1057341dffd5ca48909ddf2a1f2077dcf2a2df728443f76c604fe910fef56583e6e35535a97a95f8af164db15f7613473b2b680cbea22e478ad6c39cdd14fa2cedc6088aa6534210f0545db07808f82eab3c8b3f5b66a9bf39e09d4a5d5a7989a307b62ad39b536021e6f06879e5b93b624c8109824a7ffe2d4400536818ecb0f25b931fccd143c72c313bf0c7ce1535797cf3a29cbd6d5d288548fa68712c12cf2f44b910282853ab3556951fba2992de9b12547228c62547d8e74bb4bd4cb5f47d18fa86e92e3067b07e865877940c0edc8b84b7a240e49b2a7aea7e30314e51a24e34c3fda0782cf340320e450ee76f6d07ea5a0384fffda28efd6799eb973c8230b205686b4239d56382f78d81ff962d9b69ffb5138a29b79fd435c24361fc65118cc0f8edbff3a56decd711fba87aa08acbf76533aeff5d89b5bcbf8eeb058a37c33fe1a1ef06b7521efb41792dc9d04da9d5edc27940def7900dbd8a04c8726fd958ed0559802bd67660f5f33d3c08acb5d1c4e0bf4b9f89b24ca84cc83329194761a178955f1cd55a26653efed1f9cd83409561f1c0ab284ee519fc3bfdb4954f797859dd54300e47418882907ae96d5b441c53a09b52c03c5c33b00900b3435217aef64bde11ab2e8af1076ec22ea64fada3b55dca4e557e645d47044d81455238c68f561167f8fee3420b8bcd07e2a20f0e21afc574b38744a12c29a990d7fde05f040ce97b8669d9a2dd36eda77d9b534a4599cd2cd1f85d928deeaff643c1fac7a388a920406371a4e6b91ccb6fc35b679cf6bb004771ac8fa621b3a9c26741d7f11a49e390afcfb2a1838e353fd270f0c7b3a20f1a2367f3d8f045cb7b3d9f21170051784c5978fc1b5eaf31344fbda645af7d2028ce29996d9e397304101f619313f9ef9eda4363e94a1a22a076006f4a91488f1b5cc71c02310abe757a6e3b9372c6a3dafaea38fc94cee0374b974fae9b4c027ee59880b4f25d2a0a99ac10d2b22dd47f30a8db8167fee56963ffaca07f2f7e4ce850268cc5381d911ba6510c90ed23aca71dc74e9bc83422fbbef375976c0091ad612cffeb825b81e17c01cb97d4194ae30a96410fa1168d8168e1e4a33fef32668e41446105d4d94b7544506d306c55982ed5b329725e58b7b40e9afba4af42696ebd3fd4c9dc4d97f3388d5c50808812773ad661d943bcc89cf29282912ce939d190a199d91aae5775fed2ecc0432444379e809300a61910bb53df46c27aa1c4198e20920a0b06e4e6d4c978d705f4dec6b6587239b51cde03d20188adc28578f17d3529fc73ad67543544fc1c4578e5516d310f8d70acbdfbda386aede595e7d759f858c6f360f395f21ae98211922004adfb48c03f2c0409a748cf6b68b6034caef9c9b72f2943d540efa4cabe596f1a9568bbebfe95ad2873fbfc200693737a86fa1c5e1fd7518013553f85f621dad4fc6546b4a1987a567a9da66590c78b194224b51beb8cb100bc7e768d81459f9c1965307ab8ac4456f5080aad02c433364d3f62cd08e74b695ed317dc4408da4c04db6ac3c6df6875f66b0bd5308d43840ea432ebd3801043345b3e3d1c68944d0ef134262240d90957567e8e315f5764e3e2de5ac28c52238136e80f040c25ce97b6c5d751c81c16fc98ed09e3f1e58bb7e0c47bf398c79529bed15251eb78149988700ad0976b26553906a56f4f29c3abeff1889e7a2699c656069248c0e12759978fbca9b59e9169200580b4df663a55e0c7a4614c9e356a268473e45f7b39892783e6c2cf88ba226aacd80b12b5207cfb472e14f6f6dd24f36ba38ac3d9f1691f7192756bf4729e2a7d691f86617760a3e8858f44d760bedb3c3d9cffdb6893eee96a44ab219e15db15b152d6a658b63eac79b80a979f0d6e3d8bebdece92dbd5dee6a2a988edfdfd8c39b601fb801be728fe46d88720bf81632b06ee6f75419390953569610616870724e0c7f5f54f1d38a66758874c4e2dcda728fc9c69cae495044124c9b24310ea1b2d5c3dc12c5a6a61a965e101cbd82a2dc8db9be4513212be66d9ad68e02cc29c0758d25d29d3f0eb51a92935d0d2419f8628bea88f44cd275b3ceb2694fc8fdad5133b6f458b24ba26d3641410f2f607020cd84ef6e65ae3b6ad52dbaa62d977baacf979492ecfe183cdcf4e4adfb796a24578790579edf80b129db3f299c53654e1604f0c834e7f304f111a2a60887fa818e2403c51f5b265f1dab8fd03e8c0c5518c9bfd3926955d0df96378946704069b1a0b5c8c97736a24566c7e1ab4a152dcc44b6c67e7ed67be118f940bbf22e90592afabf2f6a5008df237e10ef824a0ca54aa4864dd71c66f1ea989a061187682aae27c9dcbde907313e92d8e61150bfc458b870df2023af7cd4b5f9756f5d5b4f851b067abed9460b324a91f42f51eeb26de669d042e0d5a7c2730534a4e7016c4754cc0f2c14a7ea1b925c1be0dddd0da05bd3ffeadbc16e7955473e2e84fef65d8271d2d8fea29638af86954b0a3cdc073022c678b0a7c099091eaecdf5dcb38bf3920986adbb8a1aa042f95231b05cd66fe984d213b7f9d3e1eedc05fc5c530f4fc1bc3c95f1fa499e6ecbbb665ba1a396eb58b0c8c305823b3321f8ada4bb12930b379935314225389eddc5da6d5b4131d455c3951606c77010bd94c4e5b16439d3df0f9e3e42fdb0788772f7171b756f3a4b4e63512e8e2738edb225b6a9d8e49789f840d1b2a9ff22c5a525a4307dad2132f3b8d25ce22fbeeb2e9ff254d41aa60658102f5be2006ea814c3e2730745c4125a1144b16918a1582bdc1bbcc209ff5541265da23842e5d89465ba4cda2bb3c55525b593e51bf167519d109986ee0ee8238128aea0e00f9017c9439fad1a519bc649941d01c6ec360b619d705896843c9e42833eafdb495b233ca40fec44cc7f93fc2f106af291d00202619ae31f40876aaf700e86b7c2d7b21efc8e2faa3ff77ab0ff1d1e6076a3d0a9b7cb92a4a9e3ddb226a504aabbb4174bdccb0c5089d40ab1b5792c01013ace59ab2d50addeaf6069184bb0b81140de561629330df2a2a8635304109f92e86e440fc1d484c69b4ddbd75502fb93a08bacefd66e319e079d910174aaa55d83537967bd5db94fb849cd22e69efe7b453e99648a29937ed4397241781e14fd5917c4871718c6b64a3c7dccef6cf7147a646220f9f89f1a0323b0bd647ba2ee430af79bc205e2be28a0bbfdefe9a9efc9b6408209e55c8ca007526abd3b214f2cd2a4d961f2fc9c9bb95cb22e56a8dc295216612fd2e09bc83c6242811b15cbccf56e738c45609cec5cce3c43e44123d1266b955427714a4251d2ffa7dcfc83737d936665744fec78b23bb904961ab2beffeac6c1029004835c206940ffb19aba238f16a732d9f316876199d4ccf343b206d44e5452be794571d4745451c27d41e995b7c7c310235a8eb3962e779243654dcf4b717bd9b9e99a7cff6237b896cedb8525befa25c565e11e77e8efa19d53b0c01bb59881b0b612c97e17dd8a6bbe2b3b5837cdacc3f979f90abe33ab98f6abdf770051adb01fe5c6d95b85a681f32d2efaff80a91c499d87545bdc4653e695bb021f92248a257576332444a2eb3daa83b48130d212ffec1ad1433158f90fb805b378f4cc1cc3b0b1901272cc607baae0b5e1f367937d8d530f9462b2e1488d0dd2a2885b3aed26a0e85d70392be0277906211567408b6761817f12514db26c9a749b3bb865ed2bc18dfa4ce06328dc5cfd76fb5417f495523197cebea3236019dd601fe235d7cf392b50aa5d96ba65e502c62ffcd735217af0767700aa15b402fb30db3d9a9fd16051d1f6ff1aeaa7758faef0b6ca178bfb596e07bef8510e88691a6ff6fcb2a6722254ff4862d089a89b2d473d00651accac5e60c312918bd6a8153316895c9ebe64494c217c7bfc1f6f81f166865b27a541788111ecfff9bb4f7a77654cca59eb5b7004afe7834f93cf1b8670d174c98c272f981b21d97822531b3a6712772121ada3d92ba73d2ddd6a1417a23e7a65ded80a26f3f56814742f0ed48066c6c2910e2b5e0cf51559dfbe11c6b01ae887d8b1a4b55ae835ffe338f2f5cfdaf9e1ce6085a787a7431da8fae168ae77a7dfc6e141804e05ac3571d786cd5c69fa3dc9118888b53867d1ed789175af70148186504302ae4995af2035f6822781575407e7d5399fb29ca9fdd2cd390229a49eaaf8628b2f5433a4398616b6c6bf986ac27c6fa032c19d0db1d2e5e511f840baf858ababb9caf9e427a561887eb6e3108989811348fd05e623f70d9d3ce596cc12131d5d1d38043bf26280fd380165fc0a388add2b2b9d40bec4fd2f00fa936e473da385855c8a556244fb094da2900b0b22142916915f1475086a3e02f36cdeb1dae9405daf05100c76c35297f844506b52ee84cdf07e6f8cdb8528af8687162f1ac19d53bfc69d2fdcccd3ad32f3250eb125585f7e1134e7c5caf6e06d63e72b094d88e759e600a5744bf61f5ac3a713a88618a7cc53ce250d687179bf8d093d45cfb3825923eb4471862688434de63f12025346b6bb0ed0631713eaddfcc604dc7430abcb221adec5125e0c6abdb59b8d72e1b8974a8bc786de53f4e335e9de564ecd6f0ed681ff0271b19697609209a86d039aca70c086d80041eaa645be9ad03c41087f5844a7042d3d51ad24279831bbfaed23301f244ff85dffc609b7f0f69dd889148e2c6363dc7ed360f968f0a76ac9bb028d45429b45eb60a77991d2512af281c71423915dad8eb2115f0df4a0e24a6563a54a64b5e28d8efc094c2bb9e58668e981505394d6d050b5c5f5e70c81c740670832ceb7f07b25de89e5c65941dd207c179854d5156c4ecc82099b93a4bbaf627cda7c18a8bcbdb4820153adab0714e2cb88402bb87b1b083261f5af9b84e618056cede2ee5f8663b4405d6c14e77c4960fa0b6d9e824339a0850b613b83dc944e1349185275ba41d0e90ed693c8a38d62ce3f15ca89dc11d2d6b1ed1f7bda291957fd545ba21d0a8dae0204dded0b54a3b15824d206e394e41dc6243eb453a7912d0509b5223d5b912d689f6fb7b97f683107cdb5c06fde603535bec82064bde58be5c50ce207e9e776bc8052da121787895ccd991f1155a07af20b6c8d37295946163c6ce7e9086495d98b8c57f6f982c18972c870e4460fb6b5d2ad32d3895081fed750231c0ad55cb00d1e242c40119ad006d11e2e3330a5ab71c29b56cdcccd1d6f5466af12fe345b75cb4510f4313f9a04bba45326832d5e3809308d17ed3d957ef793f9914001cb1990ad191ccc90987b2a030f16f8bae26c7bee171c186fda3d7a3285967beb352720bc1e3e101232c0a1832f87886c43b91773cfac07887acd62f553816947fd6d73ddcb5937ec35177291405d070bbba4ac4a3f12d1a5a9ecd2511c077f25e2f15036cf36113d4e0f10e778ce25a782ff052a248b4e25058e40ef6bf113483389352ec57556ea1a447cbb43c93a15bd06f12265c888d47c81bf3b23bbf32be36563424e43c5dd4c99d1c58ab67c9e158e6b5b908c334103e22d6c4ee7b8986e0971a0cd336fc40c97a20fa29e141637087f0c621ac720f33ba7d35b87a7199240f7946d8ca81d37377092f9aba8c441651fc7563da85a94fa82cb5254b8916cf386fe3e5aa941aa7370e44570e474194789c29dc337cbb86719d78bb9a27706b802351453bac3a3018048c6c6a18aa55725cf586362e1d9c4c4d4a70c02f85a395c37a3a3e70b6fa415580fd40e02f84a3b918c5bb84a935e212e770b42470f66aa895260ae89240844a69ffbb0c73471b76f1a956e69cc354066c94a047cf1046f4f103a59a763b34589dc3e8c80714d8462b5e36652ef2d84c7afc07f9087cd5ce8e0e004d81bacd1061a4db61abe023ed522616cd71b55b1256b7d6b2952b4b2468367a6667c1850366773d9369f5a4cde7855e2f7f24a5fecae72d65b2b4b03f92610ce723a9db0a34b92aa475cf47f28a8fcf052f0ac3af79f67a197202b731c2088fa6ae19c3d132e2e85c1a518787993214e2249f33ea3b7037000bd074ba7004fe725fefb174644f9c1e8da23fa3866ac739168eee680298e04cd59724839cf57b7c0018df734f08023c15611facfdb640e378e44ee39eeb2c5ee022e84c1a63a65eb2a7030421c3756595153ccd847bc96ad0b4d49b65716c39dfc3ab35b08a6174897820fac58a46be76e0b7e89168a284621c00aa05865e43e218bc214920e91b0cdc0ee87a0966df723775faacd921aac19837b20eb4087a160ec46a5a00aa5d3bccb3a807ff341b0624adaafef2f21095e44d58f8df3201c49caca08b7b65700c32ffd0e048e07185b638e46b34dfbc87800ad97216ad4063bf228695e5dff7578bbc6be2aad62abdf9e340bf6e79642306a5518324e8c8a277f4185a559348c3702d1da167cfddd16d0ba0f980c3e8e80f1a9d24ed85b617a693fc86681b497fc1c2366dcad5222fcc0b9332275bc6bcb366f4bf73b176c01e5408c46df027c83768ee9c02a924acee21dae5d415b82c71b7e4ba48f640bfe5d95eb49346c94b19ea794afb3438f4c108d1a2c79051ded15cd2603217b1a211173f504a35196583087310a8138555cc3fa4b675093cebae6e88b957e5ec3a49d8a1d828b17402c1d4033990b63040a7356e987e2e226e3f7a6a32d312e330b6e51d62ceb2249434913fbd01cc1e67af31ea60ff2b46c376265ef5a014dbffee96017c14ecc7c106423d12be0abf6b11c37fcaad485924694f7b8b990700fd188191b39305f0120157a969ea4dd713bca18c68214bdbe398f61b3edfef6a0924ab745a20751dd5d50cadfda7173f8f45e7cb5e66a4edd0a11b79088134bfc94d4a7acada3e9ccf285b170ab6b44ac72c3b13824b68fef6437b11b54719795df88b1e08d6a100e09513b0520018b6091d8bff02dd10e3eecb9c06049efd79eea9b60060578bf00f9a62777c2eacff95ee33c0ce1348068b764abdfe7290b7a22086f2433c397591469f033cdb7e13f787bf57cf29da7781827f737175a95570dca3e6a87bf5ce25f6092ec046b274cb927e3460706800fa645a4072c4e03b5e30bcf1ef911d2c482fc4ed3d39a0f33609289c6c27545cadee40281a9817f8b29b9e9f478c6495b8c97637f3021534d6e47cd062156c9c79566e13749e5f1fd1471942f42471bd56903f642c2219b32acfb5e195762ebf7a7682493828dcda9e1959029aaec14913075d6a7177231d900117a87cbb5aa84f4d1fc9357b2cd840e537e97b174e2923d7b64c3aad5f2f9c3b47ad90af217701a1fd81c6193d6b400eb8409aae79c9aed2adc5fe3a49b19c65171dcf97444a700d30ef61537e6d75c644779c2525fb6cb73682565f9fda58aebe52fa19fbe06055936b8740b66a36451b6aa6274712ed23c42f4ead11d6e38caf079747803d761951519e812d15d79ed3ae21268b555352a2a357d76b8382e28ea6171432bf3103678e6c2ea84e9122f96fa37fdb95edffbb15f229bdd09bbd6e7ed0fdb8d22f2087aab709c109a96dc29ccf4d451b1d0981bb4d5779cb1d9c9d5867246d3192ea9655f482944ee8f3bd76eebf454a1aa453190c544b3dde7e2d02999e224a4c240ea1e1a7a9915a5f3bcaf49e2bc9bfd6665e351372428e6f73ef1c9f2728bcf1e8d1a2cb131ab905f09552449c669a8b3b933d7994c23687837930016a9b8e2c6f58eb67f4d6f13abc4f7f956365344dd54f76652a20ba35c1f1d91e8a45664182efe5aa41c9f48a142dd87ec1afc79aad83b489262768571d362200a0ec55df6c486087a3f44943099ddbf9fd8620ecb67f4b21af7137199bda9784a705807348ee8103f5079fae292f0eaa8ff650faba7fdf7adeddb86f196a77bb20b6ac88388a93715b4dbe1b14bf5e8b58e928e5ed8573e207c93e2dc6495666e5b649631f8d5201730225bf533925766ce6d8f6e733f43f041b117801f49ac72a4a6619c0ad9766c93733c2010dec6f6c1b31fe6e8b02b8f1fbe5d33b186ec9c5ce1e3715dbd4d3ef1e1392d4eb8c499ccfc506355ed93718f5186ef79a1c4ef60ddb004db1080e3fb6424f7f6d51c02d80ee006fc227b6687605db90d406401477c74a34a1d391f7ea5ee5cd69624981293dec48a513a5b244b0581293f484da743b4e9c8f6075685c77530a2aa1368e547b86d5b6d6a2ceb4a24a94798580810ba225b4cc9a0ca01f00b255d9b76262bc6a9089257f14a547f04218ddcf5fa437770d1f518310fef9cd0fe2b60e1d6664adb42a57606566699713be4ecba280afcc6a8742009c6d5e95e55a6d8c0fce959b1fb32b0abb1d102be57772d869c6c66ae0c8465b03cf6f6de76a4b46491ea421ef64b90b6ca03e94dd853029ab94d2caf2103f190e45f86566c4d0385a2cff0267129e72651fd2ccd4de66dc407b222c2ae4925f1f8e118a4cb0287742a083f5b742431feaa62d5a16be83ed73dc7c9521b76da6407bacca91b41dd17c549d09c5a1fe1e80b3d8f92b8c44471cd61af25fbb3bfb08f99b6c8f1353a3e2f6f883c36e90e77b9945c3f8fc1ec265d521d819c2d50e8cde5b2eb5069d3e25e3feebbb6efdb50aca4f4e7a4dcceeb0b49e3111211e0da3f2a90338bc0956be77c56a174e678ba7aba71e0b99f0d32c0e88813ff9b29c4429aaf800fa5d3d25bcb6b4ceaa304b3c747e0cd3755e6184ae6a35549a9d30f83843a9bdd869a80d0ac2b58a14560dd04901d0f5c948628e8c02e6731d54a5c3cfa30b437ae8582d45eb2a8badcb8e321fba1be25b0481f69141b224b99cdb7eb16362b4d208e55286e327e05ed3f6a779bf83b99f42db15c14c49c65fcf9f262271c1636307225e5be1fe11ac8b2773d0590b216365e913f1bd25450b0e67fe5f53b552f746e3e81edf64e01cae6a6f5705770d6ed6aa9fe1d2ff3e4e75adb8b519079db052245d0427a0a4192badc8c0a724c9d3b3399d3e4cb877232d96ee7d40cbc12328c51cc9e9164c809103c5e8d506fadcc12dfab0efc804075162420bc1fbfee55578d70eb19884e5a5dbdd3583df6494a079fb9e2729a24d6ab3223163cd6168e004a81bc79e47d64fe0538469ea4519c7816809ed77320cd495e937958947338c5380d9f17c0cbb66d15b53be7023212b1ae15c358b0f1b633d81e32385e722dac959c1ecb5917aa37f3a7aa3fd8ef8d1d989cab86070b25c71589df77064edb357c7e05249846964e011dd2a2c11352a9a36dc206092dea4ad06d0c7bf824ccf766f0238bc309062c0f2745494c0afe83981becb2f4c11d143662655f6c05e2b79ab56e4738b773ffa4b1d230f4caa84a97fd5aae1c774a5a0fdd47471eaf03ce8bdad74fcda5295f4ae84a9289b360eaed1ea4e92568dd4afee41098f5e8e5e87edf980c06647d0aad395ceccbe4a4a030f9980c1b8e69dedcc58a64b5bef09a7c0eb02f0b263acfc92ab7c6121b679a687b572dbd70c4d7738c3966c0992bdd4400253cc63fe3a5be76bff81b097cf7cb4acdafcfc8f0559239f5f47c52109c2c9bbf036ec030fbd8dcd6b413f0b02b9b639dda7c34c7e76a9c56fed94715183aa2a0fcb4b88fd1f5cad8321a6581a3aca22cdc086bbfb471d612dab58281b1bf34416fb3996677d02dc718335aea072c10529f8e753e4c04c8d2bd14ca372e0eff70495fbe3bbd6551925f449b5569bffde0bb47f715a5008179b9df24652b44010accf3711efb34026204f95376ea554d9a2716e94b5c7b795fe813dfec8691a2fb5ffb1d2688314ff0800a017f46fea7a9291739029cd15e1b4ca82bc94ee91bdda7b45d38f80718739c5b80c50140f09bd7e6df0ca886eccb4ee6d9ff40d07b157ccaea18b545d7106d3910aa712a18f054baad0dfa90b4ffafc2f33261bd1e072dc82b089dc2fe29dac764c8ac83655cf52f36dd80b5d222c735f07b8ecf4f7f4cf805d756b72f06c095b179404598296e30d6e60da33e3eb3e13ddc3af2af1b3f16e017c71a56ffec96527022cf04cf5a16ac99b8dde97f120675665cf2d5ba1db9d8a3939e2f826f55ba85d6543fa23e403450648a9fd21ae91876257a6c3e36989cac0f518948d5fc3a3c54bed802cf29faa0ed8732e19f8af951a521c838e7926752b352e4fd3ef0c19fd15256b786333e8cd80910cf84836b6368d597d82234e51344eb0e99327cfcf8fca4ec755e4da7414680ae018ef63f5ada99227f9eee30df21a59ba01088b66ffd3789f3f8a103b10eff1cb17d696cc267351ad9a494b45adb5434caf7b3324f924d9b05249a3e969d98488d37c6bda846a8f3373503f7e4b7e3718b319c3ac789c2fe44bd4857d811755e9168910aa1ad46c629f660d5677c9cd2f85575709cd877b3f204b243bccfdd4a1792cc9078032328c12f1261334957cf4eb1f6e28c1f3f021ae028d17087c052945a5916c4da92055e836abb5d63d49952adcc64706767e29322787a8fbdaea408aa4c006d04f56829c1716aa9180deca5857502a2036b75d0742b2c0b4bfae641d6a5765e5879bb066f9ea400b176e2030dc5e58ec65d50bb810aa0180cb5177625721d85358a66218dbef26cc7f9819165eb9989bc311e11ccccf716752d2bf495debe418a7327084ceaa2ac1e439dfe64f14a8efb927f17868acf67fc7a1574b962284e494f38e5a723fd83c38546b0fc0ce9438f419b17c208f8e3aaa2da94e0c95f5c183169452cde09f889775585f716ec770dab0e8b840eeda6e7422c9d02edb22afc4a90001bd829e4f19e438dd1dec9706c9e92b07f20f40a7b06ac334e802920d4ed17fa2364a38d66db2b003bc29066c817c6e87d24b06fd6427c24964a5578500676d71c04c44b49bec100b1298ee71e4fb60c259d7ffb2351e107dc24ca2793da66335e7346234ce9c9045d34c009006a893e86c7e35ff9478e3f01fa0afc55d01d8c9e39ce4f62f004700b85916b41f9406d94bcd78500bf25267ae7b660fd00d052a31774dd4cdca3d11723f089214712376280b4f290c318c541f1bf2214d9e1bb3c3d5b10fd1de9d8faf50d425768743faea9028c7453778dc5a4798723d7421f746541dac84a4915088e11c5f4d15435d605cfda69a9d2544bffd1854a4c8c5ac172c302c2ac3168a4a7f0dd19f8fe62549926ee2b56325756dabb53af1a8aae10b465afbdab747998b4328637aabbfee6448b973d9b9061f90fdffe6479631dbdd54af769d36579010bef4c7029f1d98eb67db0f7a36846eb678b414982e3c5cbc0270754471d42057e7fc217c9968959714e4ac342f2016ffaf14a16b2e55375ed61b7d8bcb20db6bc92381a13792191d201fb0109d64698c92372c0a064af221433f1a0e6c859d63670c93a565747552f55daa7f5b94ecfb1079b1f4e88a24074c9356191c0665834a09bcf695322433c10cbb07398e5c52df6dac248c6fbcf38cff6d6e94aae1a628774e38580fc89ba56074a50c3a45e37eac68169771ef3066c14fead752372d4371d4500354fcef7158f0a49315cbb8afe0ca9b559c6777b0cc7b5ff76a2a2bcb4c30f52be67c87980d50ba8895a845765c89a8f909ab54227cae4eecf215b217b425460d3ed241808f9622bb1c132e6b41ef02d08b7e3fd3df6701fc119b319b91dd9cf3c14a56c18b278b1d431236a5b7c626b31dc370196eb5501956ed08c47c30e2701668dfab072eeba92e20d975931fdf117f87396f74bc43c5e1025609e8c79b61c2aa81acd7bba0accec32ffff461d7a54c8fd61db970f021115a2092ffa99c2dbc0614a94d3eb8dc7e402581afecf72631db438ab13179fda169600d0716475c8a8c2711e6e9c04f631503b372d797de615ca01b18b5e1d721e0cdd9e55105add3a3e9595d78222f002dc0a6e45ff48d526c4007750f945457ef6237c89d057a2ff1c0f968371c5407dcd556bb39b817cb2c708cc28f1fa12aedf0c92af2cf9afcbce144146c883e74070a0a524eff8a3a7f4ea7b3e8ad52d4d9070628565662b0ce42882754044ea921aaffa36f2625b1c9fabb5309b8bfed43fc35d45cd2a7633099159dfc2cdca9cc6a3ed506793f4c3f0a2b5ddac8adf2036c23f6ef0ab6e829011da590b9a275c1b4eb6debca951c59b293e5b3ce8257b6a715cfd08719875d6031f92cdeb052a7697bd11a4fa702fef8bf86f6693d8dcabe8b41ca28b3f14d4506c562a3a40bed31f0067c1c7c99b908c6030b7e60853e41cc4335e59896f3bebd48bdc0a077076759fc0d5436d8ab322853301bfbd82cdebf58c87a09ec2232afad6afb76b12f38c6434722312482e4d88f8304bfdfe96eb5ace8dab4c47882e5753223abfecba28d6a16b6d87f02a1c4077814f426f95d78622677043871c3419f679b1f6d085ff153a8102e5d590fd66b30b4207fb5ff70e780eb7100b1f6518b2a507bae61649a776ddb01dd8ebda102e1a50bff74de625d069ea60f705dabc7f17bf3cf7da5c8aedbf7ed8bcc05bbe02eb14d6a9256c1238d0821deed1a68b8f824ad4a44dfba852be396c90121f777cb6d11a59d6abc7c47bbcdf359b046e8ec87095abc9423d3912a0bc40a069c6e0dc5429e9e67b2595cef5d0a500ffbc9bd3334beea15f0bb6b5c0fdf4057dbff7dedab3f6c66505c43d82fc37e777295add59644596fd3681be04ef4f454451dc0a605c14a1088a222802ea88a08d1ab7617ec71bce4a78724e5998bf5a00bd5d738ec9523fa5098abc61fcabb6e9a8f16a513c8491fe5322dcc6e1ad0f1f6190c8ae33ffa499c6397daa0c7f8a4e79ef053b6b732a5ee4ec07daf7d02f01ba000351f7e978a0fd095ee9202318f2ea091b27b980c39ae27883633b3d1d11d4dd8ed5ca431541d795f410fd784c0d7f1ec3710727e86e7778520456fd0ecf141ffe830affda42935061a5cc5f82ab706c02e29937eb9594fb50f8d905270fa5d46b7af9edf07c90122956c0e6a02a9c7deabe9c193b1163b1e682a2b7340c3d40497341b706a1633762974f4c343e342e34c3fecbe3275fee001157a1c81dff664cea484fa75e3d213c189f09758f34898cc26c8a671a2b4383b16a0a8945f733c2a6ba1aefce1fde7fd38a08022c456a97d0291c530d2e4062d1e8aac12294c79bd13ffb7852488a23ea7667542339739d1597e11452b635228c3caaf35b731959538288f1723e5dfeb73d803aeb944bc965d2d6610d6ba7b0e359e4ab27e6b7b5a00136238c7210ae5ed9d9e0e8c62a98e014acaa6fd9c6fa02cbefed8bfa54278975f7e736ced4275b4444522f2e7428f4f2babad06335f266df89686176910370a458fb9a8db34e80a12022b5ffd8daa4d5deef74afbd207001ff2d56b9fbb45e07b0e6baf975e902380f48b05f71665f322fa0c2317500e2a32f1f1b942747f61eb31bc83b4211dfed6a886c8254b030936ade33c0d22252c938b7ee4c2666a7c4dbdf6feee4e124b9a0f6128ee10b0449a9ff78cf07c5efb360ea69cdc9b5ca77a942d5aa6b217c27429c6bb6f8bb3b82e75074fcd20553316edb6249c3e20249e378fe802a8d4077bb46e6db4d3003d63e3fef288bda80c486c7ad16b43eee9fadf32bd919d58f4dc5ae93b7767348741f372d9fb8b21a83db7510587d1cc21a73332329486ec83acdedbafb20fde250b5ceb21462782c5c62fa8a4acaf9134e993a9c4a285a4b6ce1395c4bf6bc8a21afa19a56c25a909b282dc9f7e71108a612013347b87a0078206619919793bde38472808ac79100d01201a644e459273a048697f661769c00ba2c0f6109fcfc4a77725fb8e83e2d1b30d5b9295eea8330a158769aa284ba304b2c1b0f9010199195fc2d4797e968f5d05e1c44d337e31a52c967cef7cf5e3dd50f9cc73c0c4f83f6a597882055e9a264cc542de80e223d66f2e46036687cc420d327dd44ad379499155a03f1f5266dc230647aefeb429f2f888867d753ee24ad87e1ad220e8f05134fddc93de39dd575d751a158dd3816255f48ed0ae87fdae860bd8f9c58b972d9dda6da97696763cf1261950f7aff4227cda4213e53a8dc6401a3bff12bebd0d0ca413d275c1081a959623b680dccfb91da02b437bf646ff906f13c83da32b8b32e45a4cc1449d32f2847e6a5e9176803fdc758ac416740adeb5c1b1b62b58885e4e9d1d587f1f5d53adc9fe616943fd99732a22e70cfe89d9e4501f327ba919c6803aae190858e97714ad28925660b017305090f67ea262ea3b856ae40eba18f4a28c0134155d96e2590364a5e67db0989124f3f38326bbcde46e06523835fb87e8f2f33df22eba6e8a6d462cf7fcb44c3dde830b05f47de79e524e288d154d872cee0123fa04e57dcbb349ae4a432c51cb106ab1648a6cb29d9d6a568247286a88ba963c8ebb9bb4aed35e0e5dca00d782187fd628aed0af2d2037157ac6d9a0cd74f2165a15d3d3cd4dd9a1b3ac35b0005762722ebd31c6ee5ce25f5de9f21988cd99f28ff5c417b72a9baba0023e62f1530a0c7944fd680d8e7002b199872074b52559d00e6e7233fee6bd0158c4bced76baffe6bcc94acf5d00e0a12cfaae8ef351c8844258126d5fb5084d64a4fd25c6f467e38cc735bdb523bd113d9fc9375e62d20cd750fb049c80288573ec0d2fc96a95b14e01193a20b1e7a722738f0fbbe21376ca1d14580888522aa52e34c04e72d60f393fe733c304a671a76f93f6aa0b8f09c58127139f8578b55bedae16daa47f1c3a03b7e42fe149dd6a4897d2a7f5097ea5dec3c396bab1be2feccf7e46efdc002fadb93f9b70b8af9343081350b799e300a36790ea480225a97b1dae8f76bde3d569568b022a9a201cac5a3447801927c8c843f86b741a565d336c651f58131cb5107e569411173785a685a49ce72bef767d238e350e5e470cd227e6cea9e1b59ea4ffaec9cde9a04ca37e62921e61688db9181b54a52c966f094ab26df2edcfaac977f207a97f8463a81f9a38b29e8cb83e5ed252c620ccb849c3e79c088fa64485636367d881e45449304642b48e1256fd0250a08042bdc9424060c4e8f227b740481d53f5697a0d22706d4e692a3351afff341424d16611cc2bffc3b3a9db4c8f05cbf57ef04e1d678fd19b50850bd4a375dea59b8d9279dac276833f93bf05e9dc58a0ba2f50f485e7d6ae2c3d09678a5c850bdd724615f37abf43a2cb5f8f1faab437b96d5b137bee48da114f318dd4c86f7b7b6107279c7c49adf4009a4fdb4a2177f0b49d45dff787885bd4be08570aaacb10094d3b7419088f6348a5fd4945f63d6f95103d7a226c92e5ff41b316a2c40fc4621de8a381beee03e82151bda5da2bb03ffd1b2b02dbaff5a809d1b2ce2bc88def4f98bf08544044ec36f67b19db11ca2f50cb1e168e3a698a0c65d802f4809dd9838f03a2ae13b0c4d542d9bf7402eef37a83dd64e4f51eaf065f774e285448fe7af16001cd0e3a894d538b01b9bbcb2ed8f53d3600b8da24b03532437db010bc1cb7c817e2b8d44ad63de0e2e1fc27b131dcd87eb7034f3f7b02bb36483b0ffb00c9955349860e0c0271746cf09d9962ff6a98bb5e402ee897e6431a2c0ea54234839742e1973ddc3fa5ead4fed7b580cc2f4f33b55c0e97764e2d363d43c357756070c8daed7fbd5948e233f54ce59bab8786906cd8c5b019a3442731f163db2922abc1b139cb08e17fe03f640256d38c9700d38482d87ab98cd49b8ac495d2933586532cf7ca553d111ccfa5c705c1025678f8caaa46ed346b8f88eae07b8498bb1a64d3129483ef05ade7ee0edbeb70a9a2a347afd17e92e23ce07faa1e277d4bd3d570290392ef5d1759e0a084f21a881608408eeae54e29efbc6e23a23fa3fcd185914c5d9421b275ac31ca43a73cba3c12f40d8dbb567b3badaf85b252b613e4b036106b02aad15c3f3ca1544d2feeb84a9a49ec4647cd1c036d467dc8f94f197ff44c026ac8968d49f353bc04d9fa5a4e631e5e9cf2c5932295d1e884a180c1ad51ad91b4055497d6f018735537d3067b7cc9fcee4767990ddd1b639fad19eb8d27dedeb49a81b375a12767d26d3af1c8102508b0805c8f44d05797bf3ac2da0a2bb4556aef4562e85b47a46f1cc77ce0056b471d15241d95e99ab63ff454c5c39a658a976ffd412d992789fcc922495a01f3b5bfce8d9a40bccc9874d447e9fd8b0d5ce8245140af62c26ccafc7a90663957a46aa61bad17178c074e53af67f005379e9422befde2f9c57ab1c99ab6de7bc95eb081b6ed347f6d1d1684cbd30da95c24dd3abe7004eeabd524f2476a8d097356f45597b937dc7b808e8991c3c3a37d761260a4ec58f5254975921d955bb02166abb92ce30c1555f1d88e343ea95242ab606a29a01f9db2aa4f9639b545d2f399e415c3a18903e59d409fa3b441ad14d8091dd414103a626e37a439312dfc00932fa57ea380a351596c2c324b5f4cbaa73f854adc9a7530b930a630ec848c6a2b8fe77debf8ef591fb968923e056cbb2fcf0230d54e988417b87d3fbbf008b2a7e77b899938a13fe8c71380d2dd548f90747d213ade8d01a2e5b18ccdf193e364e450dfe110db6c14b190605a1b47156f3a33813d9241aafd6384aaf4545894550c1e72b7633897d28e76a259ad47add3d5c8c941666b0cc01a503be7215ea205e520d7886f20586d130acc1bbe45533aa435da52f98780fc343f96ec98ce574680ec2760106ee2833d68a61e21ce29a5e76a931d1361c41c2ce14acdd8ef3446f454ee7bba060f2fb91939ccd4b2f129a849e0e35c1dba61dcd8edb1330ebf651120792437d87cb281424b9dd0df61b893fca73773a184e1fae01aa56c09af9201be8be4f154e7626cc7b789b5ebb76929f844b4cb06582c4f609256d1144f4ec645652d30e32ccac81ad90113003af0ca426cb7f3f4ef525ef87bab4ada5cffbdc1077d494f880eb81b3c1ef509ebaab10f9913dfcc07512193ac0f67d7d010ae94a2b110a82645b5265bbc49a89d734aabe97153088796ba4c9f9e9ff73147391ac47d698841cd5ad74b48b2d8ade77282d02ce9c162a8c19724fc8fde227693611e742cd06962fecc5a71469139055567afb2a452a3e9e4e0f816d912ebc61f0f819fd61157587d3e7a89acc2c0739e48948c76b50cf3d5c0303270fa3a17ce23ad52d9e20632f5e34890076e4cd942ba657db41619ca15a6d0a2f8d84d2225afda744abfa41c1483d8ee822d034bffb335bee2c6f56cc2dd7cc75fd3995e5074ea5bca1327f167cfe40c50d7a28cf27c13cdc5dc8a633b0cbe866150fdd020c4e9921533deb1224695ced617f19b9b9e09a801b4408765aabc1429580e1acb0a595568920ee836142d049552979ff962d86524881cdd91cdf67d643349ddc35930e020748cddf012fc931127ecba4272e8df15f877b5befa58d97995339010a9b820a03994286243c1be33c80d95081a4d5f6a082f25856a936ab5b047e9ddd683da8c388a6c74140588b4222b31ca54e544275697c6e45e990a6042731cb99dea1831449c612fad089f700d500442f82c2857fd2cc9b1195094d614fa4c27db5a5b8bc84aef52b18ed70d3ddae1cc9cbca2dce3d391b9795a412d0bf12f796f9b337fb4b2947aa56a2e870f98d1f3ecfdf76c5d4c2e58c89c34900cc3f0849b470d4da38e87bdd8fae25728d03a57282bbf1dfe6e18bfa05b4505f67e66954bc8399081570063720cb2ce4c4a502594141e38fc74f01b9627efb0c3d8420abc9f897fc811abe2bcae569864bb1280b51fe9e6bce1100d403aa6515c5094541b68de1eb0f3eb5dc63754cc75950e4a629b49bab2cda4e2533646d2a8929fefb4d23ea642ad737a6fa5ab6fb3d41e1423721c0c79e6e5bb49817284ea4464854dafcf536b44e093a4d8807d8f96d4db371ca4b378ee60acd5f7b6820715eacaa598b1c756f08fe6d7dc2faf6f08d70dafc9b74efc91a9e8ec3ef5541078e4f1d28cdf91170b5620c7762e711a35c4e528bd252515658b010235393abc043030e6d257e91c74cd19aec94185cb7a71f7f98aeae509ab539ab958a79b2dc778d7b7335d6909017e7c48aa0cca25d435c52ecc9b382643d93bf9662a66985de586ba878dc4650b4ae2cb0ffc948abf31412bef5c48fb21d64f4744c7b80258889265dca6cc49e5d92695ddae47b028e101f22a985a06bf5c3c24b5327b5b2780b41d7243bbc566797c3783be140438ce0ed5ef0b361ee2d94df23fc091a48e4e458cbfd53c6de542b555d94b87b98e4d285d08eaa4f32ecfc1fd075ded821269b313c8976d497fca7e1c49f5cbfb6b6b1f805336a772b931610cc064e6cdd500ccdb1f386272f666b593e48509c4f022d9c6fd74bd812afc9af12bb7e7b9f0e58472cf72023a885946717f442614e640f1da021de723596f855bb16e17517ff9b00552de4271ce0be477f41c1830b83804ce309ff670ea505ec8b66313f5a82c34fee11d5836f391c0d2ab20bdd35f2d470271c00f1267210955291e3a121a5368d59a68ca1b7c8b00dc98e71a101ef40d8236eb2a095d14d36807d21d5f9dbc12b9d403cf57e7e94b05f7baee5b50ef4cc7620dfd0c2dca50b6e9556247169af86203907b994463b4f8639617be0ed32464a551aa508d0669a9175550a9358b58c0711653e81501cc454a937e7a0d8794fb4b4777b37f3ac752fa1296aa070191d59d855a9c02163ed3a3ce260d04758321cc068ef4bb69df900992da5cccb9d96a1b74ee3a6992d8a1e1680204774d45aff453edec62612ce83468a52c102630ad266369b9adeaf5763e5cb4cb1ec3976ae286625047cbdc5c1191713fd04ad3cd7bd2db7accef5cd67b03479ee4337d588d5379e058c604e16ef3dd388be4cc9e034f8dd6ca639b69a37305a0e96a4398f09afc323f990dcf3121d2a83c72d4abf701d7aa3bcf1a9fd609afb0262f8f82bb0178503a66868bbcacd37e4bec229c6c8f9142d821d5ee5e86ee84709185e5371d3271329ccc92e26c610cd6823bae76b0bf9f0a0d33dc56ff0f732fbe0b5052efa78ef57ba89af656ef013853871279bd88a0c99c545cb6daf779c40a7fdb80efe91fc5048107d4ac1ab17e6059ee9043c8352dc19968acf60788bb71f784680d7783629a5a7066b3565140e03ff84dc2406a05cb43b5ef04e431378ac0eec9eea37db213cd3c7b7848525bb3871a9f34ea598e62b6cc78f788771bd19994c6b8a582110adcfe62b6d60112e16a924ae5146fe503955797e3855d63663a388fb0e768f44f0f6391cdb241ae20c4abd3aeedfa481405bb15271ca154b2ae479678e5e231284bbec199d9ad3660f18db008d798421fb1aea1b5e52f649f0a49bee608b181b0fa850b04fa847f64916cc7a52f94fa6659cf3f0ebc596967232c1b12b03ced9b7875c5b83e86408591975bb64140045552a1e622f9cc29dfdde09bd86c0c775850ca0f134013ec3f2685a84af9e1f3fa172afd203f72380b70e2b5ae15f26d24ab3d0314703c8824710d633ca3bfcb87b29c66ecc3cbed6d6d606a61e9795017df6e1b8153f9899a836826f31189a66bf6427c6acb8d9541cce39bec1e26d2c7c84ec7e24e1a97cdfec6ac066093762fc757caadd6cb611aa0b7576f28e5310d25d1f0b00dd2b6d586bbcef73901694d2c2ca6fabd962fff34e8c7625c0908adc82064098631f5cdb78133efe196e1e969f0cf369b64840c2e1e7cb67c4739ac24936735513cd0ad9d1340fa547ac65a417ad446e3f632428d9562398a05b71eed2073502bc86f0518421c763acb759b6188645d2f6407e1916b11617a5858f27641c0f2cea81ce7d3a70b544f0d845d0cf2e2fad551eb6d02cc7305b3a1b258b3521cf83c1b586e4cdbe0e146467f7e60d8ce101cedfebf9b82baace4bd42f41c137424c436657051c035358615785f2fd946a6744f191aded9cc30b09645f09e5b106e636e21ff5c7b370fc66a01a65dad05ad48ca811e443f2d8504a3770df6f7ce22a311cdf9a20d904f5c306d696f56c4d20a0533724383363ef47ada5b63bfdc878bd1ce10bbca84aff01e5ed88c51ff5be1ab3ce30e9c5d940fd4b87fca37be8e3129cd6f295e578d5e926d57ba0c29c887fbcb5668212500f0794b96b761a50d3d874123766c82af9dfd9910b277f27eb08c31b4e5802cbc4221c52794021062edba0fcc8547de5c492b4642ee7ef5810e8ec39e27d1f1325094a57895e2d3ef5f989aeea31abec6626021e72e1b235f5b7ca889911c3fca4858f6286f6c1c3deab15fea297c1d04f3c54a2d107f6a2a091d61b7e13ca61e9d5ef55827890e83e6afecd67c6290f7bf57a126c9214c26b9af15d87487c580fba4801ddea95786419fc9caf060574b733b723bfca8b63c3bb5681956a9a5960daedf5562ea887f387976dfa09fb3cb794cc9ec823ab0ece119647314fce9b90ed7f24fe7f166abb1dddaa2bc3d89d095c2d2a867df94d630a8c8e7732573b8db41140529f358f3c2fec56c436fc5ab176c3942fd9b9daa8cc3f641f28b2f6f30f3f67aeb1c11b407b8eb9c334644a9a2ac25283956a4a0e86acdee6124f0d69ce735c7ec19e6256a9051cfd058a0ce567879fcb801e1b2b7502532fbc750b7a3369d95a294f9119824db55c9a4c57e19d1ba94f39bfc2eec81f37dc4029ad226cabb9d50546fbb023494126ac43b487c123c07a34d295d55352c90ddf00aa5534dccbfafa8ac68cd69eaf6b9eb63908a35427c445f0a7df433dbf791d39d256fc07f438d3ee56e2ae32ffac81b32252a8d973af46837809b7d8abb8513eb3b1721b8ac4a350d00dedd4a743bd7a65aa6f3ab74c8b339c3c3ef52972d2dde996a0136b2cd6f6ad0b1fcd0b3e019c4609c183f509c132db48ca4f787a0ed57cca2701db0fdbf717d4d3a855e6fda23eb8eb71f005f947896b13efe333362bc4ef45f427b7f900e3b727869aca8f753dd41784ba7a21a609da944fd7053b9ed2460750da311ff176c27e19562f423191e4ee459b094c2c699a4ac1a3223e1b9799948590b175ddc67a3d38028f50242d90d73fabad0a5125f7d92d3d71ae1ed5b16f094911209bb20fc46084a415f16f8d5f48116a23b73cf1a31281bec0458b00623725f985d8b598e311e8f8e6e0adc767d23ab018e3ac43360a432d9e3f0343782e16b045a1578e2d2559432f97c01570b9546b9c07caa1b3392b176bfe9fda8210d0f5441adcd28a84ed62a886baffc05b6763c998326ed8ee9ce7f0b6ed35b7ba5ca801778d2aa305f7d7302e13f8fb957ec205161192b9bfa7113041c9836f5d092c06cc9d7b772187ff7f8377b78640b5da168341ded3dc84a5189538070558b84cf7705505d8d671030a881448e3280afbfc5c380b5311479861b3d86aeed939cca85d086ce585857edd6a7a471d4896465becead9a073f7f603d210beed02c56a478d15e71aaf64c98c695a9844a4b57d0d7f3657fef3d9eca3d50cbd21ed853c23021b8c11343ec7ebf6ae17c948888c7362fcece6e143f23534d03da5144de83f9bfe70fc34ea2224cacd32c120f5b727c44d5d136ca3814e01c8e7f9bca8052fa8971b4b5cc267f961618408d8b4d86487abab3a4f4d36e2a3b08f605f339927540a64c7604b64420aceae22d5fc8fd77c2ccbe839b0c50cd8a7747014ff2a025c66e24d912865d272dbd4bd53402e5575ff2e3f42b1c07c9e097cfef43e3311b583f76f87db1b76e75b1b3746ec160980a26d212b0c1774a0ecbb2bc95e1be5064c26c9f0e1ec5ab4da07eff64a173d71e8a27f116a7867fd3f0712b740fabf41fba07509dc3f4ceaf2ca258206c80cbeb68e7b7bdce68c37b5c92dbb61975852f5136c716ada4a1a276f3e12ea5f7832a0151e32b1ef0a3457aad602c565755640aabbc00e6eec73461eb60bbbedd1a0717120e61e379381d02fbea556a5066f01f5610f9961268d22682c7bcadb20d9ee7b0391922cb28d58573889e706ba121b7c341410edbb1dfedda64a560422fe49a5319e62c21eb030138002bfb6b1e07552328d4ec3f87552ed7fd048aadf3bb13e1b94b0df6179b38596dbad418602b1b400fd0ef1242679e1d43e59568ce2d0e384f32da8440b64558cbf9fc24a0e90fc575ac45a4b39adb330cef7a40ab43f43cd6556e9c140aee7516e4bfe7e5d3c1ec8a45ddd0d44ca140856b5a7c880f6f5ec634adb5694403b6df573b96cba00727ac49f3db5746c71b28b01652f6c5af3a8c845c68f787620e94cae8720de5a17e7d245e5a3f76ef5fef433f254dacb559475b698bf0b33c1b1bb4b841fbbab830ea84d575c50684b2fb7bae4531af21b55e85cf2fc57ba62fb78ef231d0ba1160a5973742be29d369de21e5ced10d7bdc2c267b039a6b4086171c8125673760e04f55aa448d9dd581780181a472a01c5854e97a8bf56257a92038f0b7e5154f0499a62d6ea1c980dfe9a6349666739a0c6ae8c3e7e8f8c2d204d797e491c718b00c41a05e7036d0534e4de1b636274401e1490e163116500c7ef579f77ad45467ba6d66f364a8668100c52234ed76b984c7452f8852f4a29c0a539ca1fe94a424d27d7e8f4fa3f1817d97982f770f9098217c0026652ab9ce5f1aafeb4b3d9887b4e5d3629621f4b755b1d62de7477bdae8cc7560e0478baf7e1960fabe5a50e0d6c83f5fa0d63902cf47474151daf5ee640a24ffc260b2e819d38510beee8b7ed72285823920b198623df8eb4a0a31922ba5e25a9329dbaffd7a8d1fb33e8647d377d0f1cad6a347423e835004487c8e13fcdfe291789a18708a4f414ce4ebb300e6416d76ac221e566737eca956cb2fab679b81f80a381dddeb9ba4b544c51aa63f817836b59320c49099723b45af02bac6445fcd8132448fe3b55976c3eba2eb0e77126383049725819ba5a10fa6839c15e2e91405741e2dfdb2f1868ac8aa42004ac13693492baad37519d234393f018508db7bc8abd0725f36e15da2a5df3f19394745d00d8465f1cb1d9a064cca9cf49f0daab2e1dea867717596b3ab36933cfbff7eff33ddf4eedea0b40ae0a9644bf29a3b6f5b6fa98dc88e4e63a10f8a84e9f4d73106f9df17a4865b130c3784b156e2a944a7d3ccf3d2d593f3f5c346b4a09ff1ff59d4f90b2c21365204df1c0ebdb94a405923f4090a0785706398867cb1a684c40fa3add9055dc712b7023f61f52c55ecb4c5f22b7dddf666136f345011856c10122591a382f067f468835b450fa19609e16041a937379d87e5f7e36209e92c4c9026f8b1655933e8f096114a3625f260084a9e4480593306232b24bfdb61bb2e75aa98cc6cc1e9d7d2fd446a656fffe130b365c8fb24c000d64ad085200ec6e1405697e4c80db2fe6d1ba8b2d4f6e2bc426112f43bce53cf3b6c96ce5c5a0585d74eb3efc49aaa03b8731a38c85544f546e8a6b03c2b67ffbdccf040a9a7cc7f73ca17788b1d54a81a075bcd920e8f98e26b1543da35e5df8ffdfe100b45742a17abb62740da7cd2639228cef60b961a39fa6cba1a8c5079fa96caba6102818e8a29f549711d6e5f36f44dbee4b30f5d9efe4cc7715f5f0e069bad8a85683fc263e4ef1bb28da470308ee84d29bebad7d2e37d4b8a07a596cea7989664ed6a1a0e973da73d3ca46257c74ceed748405ead5650efd63a1d10f61075c21f337895ce3e657c53db8bd8b11ae9a0cd6f4f0caddfa8e3748f0a28c8fae23efa9f94c4b2a684b83abad1bb9dc0cba92d0b5c42bcdb309de6e9c5163fd35a432975f2e3d6f9efeeac2614605fe2479e88b3779846a8d83a219f21fb101745de5b5d24915d0788f6996906f66a8375c81e6cb1cfbcecafc17990d5ca93f28d9810d988efb7d5e57dc0a0b23a69121eb53cd5320539265edfa41a4c2d05858c5f356687dca23bdc54300836500f81ad445a35dddd567a6f853c6795f76500e2a075ad39f9ae5881c1ae248d7906a5dc949f6f084364e420864a9a6162f8287b3e908515092872a12f35966b4fe2393892a1ac2e3fa2748c0620ee54ea21a2aca1f18683563d90236432651eed19e7b4ee2cac96837fb52c697b9f8a8742af0d14ac811a6ff5bcd34c514b7cf8675253f44c9586feae6bd6701f5fb240354fcee2ab3597e643d4a92f2f7d9eecb9850ae41ddb684bfab07348e8cc62c92b543e46fb5e604102134f96cfbbfc5bb0724496934b9dafaafd4560c03c39ff25942857aaa9f3a871150fa3b143f607e34687545b0a16b8b20e49bca09697f4c393bf01355aafb865bfb75f360f22c1b3962fb258f4f8b9894e1bdcfc22c625e48611b3b00fc6713c82f3c01b4dac92cfcc2df7b865c788413b8e9e4998c5a7cf1e2243c396b6db040398d40d51cad4099fc40deabcfb9a54a85ef5e5e76c41f8f0113616c280623a8712202004860b0be66ea196184685c82a75e9c703648817822761f47270c5d9f0c90d46cdc6d499713a204c4188e2977df02aeba0e7ce827193f72393292151c58f5b238aa75a45ad30f56a63ccb2b8c1b7762b4f2cd5809a84b1f3d7d21e9582ab21369a29cdc0dd725fb1b56e28bd9d5a56e8d222b93d40df842fdc8e5c6be07f2790686a4fe39c08a3482a439816a5873c4f42de10fc8bb67f7ec6c3951310461fe49e24f36cc379c9d471226215f22c54b0d6d6ce660fe5e3d5ca996053db2626f3c168d76b0f78d08841f43515326da9b0c0f633100ce79fae9ce49db49b3687f1dda8029aa76ad3485f4f62504cd478bce3868d4dc2aa9d01f0b2cd1dac19905fdbd0bfbeeffe0f9400781259e236c4ad6bb3506bf129cfd2ee391b5832536d7b2dcbee6165d9ad8a393b15014cb91d1e2ed27f9a1848002bae84c234e0d0663dc2aded73121ce2e95c47badaada8b5728a8989eb28856cbbb7a6d826a17425b17658f6e5043dd57bcb0e956b1fd180952944be2ade6b24f58c1421acc78936927e8c09cdc9fbdca279f1359b2d2a3c25f243e9f0801934618532f8f5dbf1da49db2da7c14bd82b0589ab3a8188d995e0ec1f86b785295f2a1d04237be98021b0ec58b16b38f9303c41da2c0f93218a981e0c01096cc303cec325cd0d7bb9999533d7fc95d3e277513fd5f8acc4e8d1074a629b7efa3ad71a377439845b27f2bd73fdbe59e2d6f10bc0dbbd4a47e01969f6556d976b6c556f6b5bd52170471fdbe5339fe31958603c0fb58c59c8ac15cf56cad97e561774d6a5e36dea36e4c3bb5f55dd96563a9c2b66d1f93b8e8bd1a4451a5688765cfbece29cc908727b55e5e8cf4f064c4ccd695e81087d1518f42fca920175f4716109b7d64db84752c237a738ed58ae7288a137f07ab7d6143180b74c2185337e70fdcd7c2109b069216b76fa4e7c0660e565cd473a5c7bebc57d1fd85a121472dec417626c8070bdc0815e828a4352d2caf49856ef3d3d6b45dfba2c02c4f5f9ed6ad86a38a3ff718cb2ec408de436b37cc370ddb779f611587685a7d78146c26f4c0271df002e516a30eb7c47b12f68efc3481d99318d130108cda420bad7602d50ea8b93705bdf435a90e7abf6ce12e59f034beb2c5314caa6056052237617aaaea1f1f23c19a9597f85475d41ad7b385622a398980087fd997df5ac9207812ea41952c201b81dfb2b4531981b9204745ee5c9dbc7bcc665dfb6d6940bea735242746bcc3c0685b4140ab87bdb14e19a21d8d8e4f69dee8dc6c6e17e9dd096a0268555a77f74112948f01a0584bc59667ad5994684b4ba815e9222b18d073a130dd2d977a2005420526f79af2687e0f631e1a8d90e669db59a12e9b69d61adf80c2889e5aee5ebe862bd968109f182ecf42cfc41faaea354a0eec6f9487444acd28cb2eb59b145bb351387cc4029b1e6d967c4e433ff6c9c7a12816b8e8317708ca723fc1ab33f0a58c4443e9ed878998823d297b2ad1ac89364b0139dd59c943ea64e6f364c5e631714582d9381ba94d3d138d19deca0a8abbc0384d60a2fb11fac035d13073ea8e24b7a2fbab1ede06e4146189bb1ee159696abb8d33f6f059a1bc777f8cc3e327e2683bdc7265883199921ee273fe377f896b174a4611f97d84ec0db0d66a473e38b38106641b19bc391f5e311026b6de34fb096f77a8ba9972e1444c8155cde971b3816e045dfa2b324a7d062ffac926b4cd2ed12e5c40fc2770309816681dd98cd3add7362f0bb564826fa5f2a246b8816cbd334e3f8b5d9735b07b1f87952e36d320919b8e9479fcf35cb852fe9f12d4c136ebc881c973c9be88fbf3f468c0190a56658adb3540a2972e0005a18c0f6dde5c66c5f010aa0b55f9062e9a2b10f9ac149365dbcd3df2a32dd09be1163e4fd2375e38129b9dbee9d22a13303c761ebed71298483ea64c36aeedd5113151ff70e937b67737a631610139fc0e866cc9fc37411e993325457f83d346f2a1c1e2a613e73e7dfc5dccf5a9d11f7fe87791879bf7c1245c92ad8c452cb37516ef31e7cd7892922e50493e93045eb204e8df89b23a2e686fd428051bacc2ed64cdba6714120dbf8fc5021937ebd14119f0bbeb6f6c5a286c77abbddbab1233394c42dac037864fe5a3ae85c8f694b8b884f19a7485d03fe386c4190a20c4223ea30c8f3f823d8050ee9a87f6ee4ad0b525f86e9373e529efaf70813c23afd88b9f709fe395c7d9ff146b31e2afaf75afdf4e0ff4404c821eef2109393878a3102722c389bde5dba859231d74d7ecaa718a9b13e7e60bb206e8738903cb71e6a5310c3074e02d152808c60ab861de8ef53a7ac61a3eb8b2ffc57492af875fd99fbff64b578c071832b09b2c81dd5dc2d533f8eb94c5814720f844424297fe2d18e350567265b75d7e9f81bcd1ad1443d5089d8cf53145614bca6a43f577b22c4b70ad2d059524de0edc7ade550470f18eca2f0dfe4658d22ce82ea3405550fa9fe901c7a2de83b963ea99f23e31ae959cb72851d473afe9d7261bd691497275c9b88be1df58e0fbb19ffd676cfec73db2d70377d9133755e411e5875bea6c6ff81c04ac9d52267799aaa22efe7bbdc751cd3382dc9c2ab5e6d8592939650704b3f88925046b97a77a516b45caa0247fd335704cdefc6a4aac298892e95c4fd3c8fed0c64452218fc631330314b97ad81800583f93ecc849f61ddfff243488233dd584d5d6a3c5c26919e815b4f8cbcf821608d5ef5fd15faa40e3b6c15413f042c7feb6b6bf6363b54f13489844ca914d861921b53a012cc8f78d426462372bfe03da06d1110cc7dba816ea3afd8dad0f042a1060ad15c099bf8d3b13d878df33c37edd41363d2f8d8b0c2fc26e6ceea5e964ffb8e2b99b87a34a714121c66a33c5400ce7b69a920cd161ab71cd18a62f4a27da8d38071a541a2ac081125197a49aebb6bfd911698db01af2e7e63e42901ed38de6fe891fec327da6eadb75f706d0fd8f969552a882316e91b8dbc11c08d96be28597631ab7e758a2024b5e04ff0d69aa23a9f689d807a31176d89d018a800fd1c9535965e64c707de916c9bda5b2fd940235d9225fc424de00b6f763c8b1d05a838fee0422ef0913671f9d67600b36bd789d40bccde93050aa4eeba49e26b9629d224576591a9649ffce4f15893b2e8ba9d166787524f061541c6ce49e1e2716b464fb3836472deda79915ca09c97f68b899ff80effa86e8cc2e4d2215d695f7372bd12691f8f8c98e8ecc746de32daebe7bd9a2449c948c49db0e28623a1686bf919bfb185b1aae84c420b5dad4c7ddae5e6cdb469bd585d06d1af826703325e307cf4765b16ef43cc2cdb5db586e00fd0e15dfbe8760621b53d66ab256544921443e64d19957dc5f4eea2aa6d68d09e75d920ae5a2c4c2bccf0c185e96c8ff052ef152c2c440336a275e133c5032323502b88601ba4bf68010c269621b2d50812550d4085abecc79fc90a52e20115e537b9d95cb9af93e0f3b3c21ca27f6bad69827fece88ee964588e5d2e175ab4449b5544798f48b7770fa039133332fe9d9320dd8f27a913897566ff49929ce47a313c70e606515c57fdc1a34dbdb3aec01fb8b01c49143f3e9106ba8c1e59d07d66d4927b9c6239876f83ace025e39a57f31ce9ab620bb7ba64a04172181b4fff4684a82e2b494ba0dabc13fbdbba2fd976e5fdbcb5121aa1d8b1641cfe8d7255afc80c8786dc5bbddca7afbf941a102089f11a46f2945a2710310550bb40b4e0d777829837f54bcfffd8a366124e56ae03591bacc7633376b0b53b8d848d9c164c75f3be1cf548a6cbd529e2324fc838bcaf998314b99deaf0b633e1c824f6423a671cf25508c79b1b16755fda6c290169ee781748fee11b819b490d2dd737cf3b1f3a3f447db18a524069496fe4160d004cdae28635f058a0de3b7f5861292167acd72ea893b5a06a483980da7450fd6962bd4988dfb3ffedfe6639b41ee01ae69925a35d2980ccc6d0e4177298a42c0dfaea0d4149dad0cfca24e9562019df92394e30b3ec2608939febc490dfdae59fc16de6ea0c56e41a3acdef86ea4e2bf1ddc2b2463d1645f377223f5b29d2faf989bf79b94407b21df9d79061dcf3f7e9d6131c8c5e31c51d15434a212ad628ef0df88fae6ba231f79d465019c59c5e715ebeddefe29eaaa79a888f29f37e0d6ee24bc94502d5b9b23e09741ddef0f9d2a9893695f7c498a03844017e0918344bd39ddb035a7bc120ae5aa2cb5275ac7495e57cd0ac661a3b6392a398d5caf4dfaf2c16ded5db9ef719197c2e07fb5c88d8a61576c9dd15fa218b9dd398e663f2c9d4559f1ce9287d17156e5e7c633592ff34fbf3059cbffef10b89a79c7793d484f3450990a8ddc7d1900c4e4373c56315ff4d16bea374b50bbaec3611a4a2c32edac734214e7c77950baac995682b4f386ee72efaf96c20622c3f5d2a2aec5f73dc802f4b4464d1bd5b12ee10281c35d4b280844fc4de8e1a5593f5ed1061c3fda4d395b9e43528dc306f5f8f758111b6c96685bfc0cc17f652525efb5adf5c27f6b5303ca5ddce1606bc6932af5481f5945de74c85b800ad4dc5b6844f67b2f8a5fe89063356b9cf516fcb8caa5ed286870bdce49cf9c289b2d8b86b284e4e819174b5f676a2fb2375643e2835fa3297041dedadca79d9ecd845e312647330d8f4a1f841665d3406ef20df574699a7d0b264b41038c88fa3571eb9d93ad1abdb441e8506862484b21979a0433d6bc7d178f8af8960854c670af9bf2dfc37bd1b3a435226bc78b5c39a4dffb80521fee86e565a0a5e32b1f8b2baae51995230ec85ee2b3784ce9f1f73d39c2d3ea95644f9e04347ad0396a709066d385cd0005eabc358b0dc2d8cdd51e64085e81bbfce795458f54eb7893b0c9ba6362b27d130746de6b32932f0f16f46202f3b9db9ed3f92aa9b1785d009071ab9204c4f4bfd1458ee66cff8a6e041587ebed133bec58ec24211c82bf18b7b5702fa473a5d01c117186a0bc583f58dc1199f61076c2f788b350ef4cb891af6ddb20686085e592d3cdf6162bd66df502e9db277f227a87ccce9557c8c581c0787beaf440017302659cff2a6b34ef5181f1a28c701839c23c26b1c04f25e44369245521be882556aa0c27e991972c6bf7c84af45d97c782b6f44027529eaaa6a51d940d46f421082c77f12a771383abd4ab20b020ef978cb3d5550749a9ea11eebdd544d5717513b392b5a2929759b82633cba4a65105a93c2bc6650e3765029670a775eabae6badcbd3fe21b98c25adb082481d00efe8c7023ee7f9b913bd05c001fa45a840c5063f16dd456e051c826a5e696b90418635cfdaa7c233a22228826f46c6f6d9c32c48206711c806a046ef1ec4637a3b5c2b76f33393ceb65f092eb701f80de52dd87af58132222d125207eb1bf1c46fbb1dce4388501c3a9ed24b9899ad4a87b355c09c0f358c42c24e029e4b350b3c0303811c2a6b098a11230dae2ebfb09a46247c9d6a3b4dee8f3fed9a07ead34e5c1d0b2a4af198539ca845aaddc3ecfecc3f5b015d38fb6f2f5ccf24bc92ca00fd85d31a537e74adcd4fab3a4c1d65690824042f5f2632ff5b3ca095c9f04433c5faf8f8ac4251552597a1efe7477b697339f2c4d2982c4d1b50adde54e3b639849bc3fa346a2e318971066f0a72a95489e29e6d069f0e848c30f5a290a2ec38d0352fea3be2f50b3447821fdc697d55ef27751a1453d5efdee3895a05127ddd17a7aa1706dc5d25562b2cd031bdb7e593f6256217906c282ddb6d449cb45a469ff049b9dd46acd8c5fdd44896517cba9c54e5d90e69b95c0489f67304b4af5a12b2e4375ec6100d2ccf2c3a7f834ed565d72acef1ebe172bb9822336ab024561af5ef3e34986d97780d1e27d2289712e63398648cfc0b658913d0861277f9b347157199b02c1ad99f1320db042ecac38b71b0a7d009b12836c6e0aa654e0d09a6c417f6d4ad63c7426b86fe1500a47f8ec67658e02c86fc1707c5afef2858a0e30db9ddaee4c87327fdf6cd12e1edc7862f174bfcf0091c74fda68818e479a9478260f6051167ceaca7aa6f8b1b502e613c5ebf08e2a49e5aa3f4414539acc9747c28894f4559f49fda0999098d2f5e917de701ea8422580560a71e1bfe7030627694b2f3e51e99f8bac3f9ccca1b1dff310dfd722df01b72178f0aadcfd7904d8351c12b667f439f9cc0b150d12aed45a769d8ee5a2c6951fe5bbf09e1156f644d62c44921c537be6f060d17e5d842e51011a98cd3ab104c6937fb427a01a5033d7273cd41a1af58f0ad4ec409632cc754ec4a5d3be4b519ced43c035423b1af7654d8126bb3438cc9d704bcbb71c8ed0b2471e7c9dfdcaad800a092e872c66422af1ce675d87e6ef59c77213bf6bfb78e4f84b99ccd95fac461e56a952ae171fd8e5c12ab8248d3c96659270103ec5b753cc7eb4948a7cdd28eb9ad0bb0e2a103f49bd019a707a1c6c66dd5388f4f35ca7f6cb63480b3e345c4bef75ae31693d2bc91eb69e4e05012109cb6719054195f8bea48f13fd6d69faa6ec260c3c525dd26c9ec410dade2bfcfc009c6966b302f1a73c014c42235cf93cd0f2f62f803ff4d45aa099d41bae2823afe9dc590a7e4fefe3151d736886255b9270e8aa2214c74651136d09541f6de122a1b0409a540bc6fc683e10e3b12c7c6f11056a66fbd26eef238f3a837a681803c6dd1eca321dd90aad2da9b531ec5a773c6d50bbef8099753f6d1273bde492a5c8eef49ce27b3b8aecb181a2b3bd463093790a64fc15d83577356655c17d3cb97cb61888cae28af333eb6bad5f87fa56741fbce4335d950a36f0a08196723824ba46ac2318c3fbeeb94ff88e24e542f6edbf887b74e19ba9759c2792ffad9f048ab0eb089f59e9ff0f7c9cf4014d33e048af973ca36a31baa459a189bb738b289de2979e20c15398259e4678f14c23e36156356ea80ffda54979d9b4b28e7c94999991efe5bda8a4ea34116257e22fc01d568be3699a71a8ae685a4db0ecd491519724b2466c5e1074903705a1a5d7103b062ecacd959f087e713f29441e84287e4ce523b2bf662e1f11202f3cdc13991c2308417fb03457558690d5af7f324883a6292dbae6114c563c27fbb8db9d6da76f2af770127d211d8e53be8219a43fb242b05d9ecd2c2099cd8145dfe651fdd701f1168bef64fab9746224f3331364e26702c9cc67ea7023b3322eb480431310e907331eb36395915a780992d85723e662496e7310d11a29246be4d9400210521a9068f0098bb4bfbd53675a68757aaba173e645ab6b1a0adddcd2a8d4efecf6150fd6b0919a9230e2c0603c0fd5ebd6f4fc656cd3a2f20532e9d9351c71dd25b3850f3eef4e15c703d4e0440709efff3df6a54a3df72b31b3cbf690f2469cfa00430798d70de3d241f8ba868731baeaea127da667ed6c0867085e431129f9aac9f8d6b12922ddc89a657131a0842aebefe19029755d7b2b8be94809bf4dec6065c42527807d9009f6af58dbeb3d2addbc817e95ae5486c50ce933d5c3975ce6fd6612ffece24655701a51bc2042ccab3b124c87645addc6cc38de61dd2cbe79556fe64bcffce0de3b85292784e57b2eb368e7580064d7a535289455dce7d4e2c20c0f1b65badd3c9a9e0574205683ddcfb22b91907022fd145c3df2f2537435ad23a5be659f1629d849573d22db4abac8e0ff06dac31551c7a1cadd82ab29794dc8e2a02208e05089f144db48bc5f89d77395cfb0a077d67e9334cf1af3f8dc8dbd842e868aa493f11fac3a0f369a95999b5f00f413fbdf47a611e3051f66e188a2994cbe9b990d10812dd310057b7b764b911eddb1a6ac8eee78c1089e7f73b25f676983f99b2b49f74094c8d048a454174469bf3301dfc5b9c557a53e321944d3b97751e4facc9a3343fae4c7a1292d485fa3cfe7a0200f88847b5964c1363ef7dfc01e1393be06dacf3d67d9bc55a16c2c05c40b5fe18748a9d3efbf754cded9c09313601fc1898d8213618afd3a2214ed497b37b9fda2d13a5731c4efafcb48d36cbddeee1050e611c72e6e4a197122eec1159e645dbc33e4600f7ed52769890429b88abfb5e1de79798f8e1f44618cbde465aa472baadae13103969cc4e4380b61b4e8ae4a4ddaee2613e294c86f71a819ff2757a6a1135a8038ef37de970b29de4705d7ea5cc9b80436f120140141df79939a8ddefbdf874574f7bc156f4743d9ca557470c1516a5af9a6d84c1bd25d539e24351e86cdae3423a1e2e660112bc034ce2d7ea6be333c044497dbff0b09b8c3fd2952921c03f40989638eb7bb31ef70c42feb93d7800ada0c04206b65479a405bef28df8d66af5213d27caba1c510089b9b6b2b3ec20df8aea9f26e2836bdc59bfbd0fa049605a1b533b5e15b9f63360201f292340801bd86a825e846356a7c9f3277cdd934060b0590728c7d0e3693ac126778f7a28ab4d4162a5e4a89fd127bd3d58967b8c79f11d98f5501363a9e134fcfd67ba230d55ae7a5a88ffbda6374c4120a296c18e9c39185fcc661da5d1a9172c3d70ff3a5cb48d74121639cfcd708344c6165da4d95076220e7ab5b310ce94122d0d70483c4fb9ed17ad03951cf907fbfcbf5c1d79c2e714be4d2906d7c322c820eab622ab45c920230bfaf182e5c21f0bf30196aabbf72dfafbabc6b25a5e5151904a9c701bf6827bcbb7848c99632546dc29237b7a0109792ac4688977ecd4d421e879e1352f5a4efafb0c2fc069bcb8e9d83a4641a9eee65d71ee295d8488e8bcaf4d84f9b354745e990548fc9b6bcfc1a649f7362a0ee912e525662b3450edc7ff34033dc3bbe7849c8998b9407d89e087f385946d2aed38c66c273077d20a7795ca0efcecb03f6e611161a673d7f74fc9d2b084a976112c6eb6fc41d5a1e1f01ecc69ca977d79f7964c18681c514c85979c36563b4da46931528501b1d7bb3f31d62f4c867ae60977f92c3bfd0eacf3fd6a439f2728be7406233a7a662e4353aca7423519db67513e5a805ad5030a81fe7d4ae7288e97c82f931f4a9e4ba11da4cbcb2008d8681712efa6b23cb6f7eba52adc58772ceabf3060732adc8411239164943d84a08124e9746aa47ba8a7ba404b874558aaf388d9b0a5d9451413dc36d9cf0099b54c10cf04a73e0ca40d9a0a3e338f26992c431c6a5b5e59fe6eb53ef6df1080a8c3a680e6777f30ef27929c8b7784986b2a7355e21fcb73e2815affe44721ea17ccab4169736bae55b5b7bfa1e8439daeb9eb3597209e7535a79ed6f1d893a9bc766be9e77507b14dfb4db760318303a892d299a66ae01e3f20c713cc1f592fa32b20e209767ed7c2ccbc37354daf982907ca5629f7fe79a93cadfb94869a848411e00a6962fd3d53d3cdd8c90375a6e04c0a643d5c7c2ccd3072ab786034291791850e37b06322ae73bea14ecc22a336f7fcdd91d6fa0383530bbf711aaf9bf6c42a472bdf50032239263ee2e5a21f9242c394e8dc0556eb271ba0841b41ba01482d24ff30001963adc7c957f88e022ddb4cbb2606d6d97471e74d8205b997951b316705257faff034ea0cf4068127bd33e116f6c14a9acbcc22db274db40fdfef0ae13c0df4bfaa1a6fc59a25a8a724547b093287c274176d5fdb99f3f8905f5d4813f5d837002a2a7df426514dd515a8710522fed4ee451dd303b125bf30bc9df0c1ff627be3a25d829e11d68148d14dbb0bae595a37176358a13cdab602391905c18722bd82901989ad546b558930219c036399aaaaea36611f50f02a763f95e608f3bcc7b0b8e4ca517bd186466f81612207dc0d5684b3d917ed15787266dd50f6caba5550619168d296b66af34f805d714f34e6889e0f19fb4bfcf0061cc65694d6b4afd67cd904fcaae8ac1ec45387c60928c8832a5374fa741b814d7f3ab450cad25870b8914cccf57c6bbff9825b9345407f923d75fb0c59b2dc3f7d48821407c6af8e9c0c668fd831e8ad97295abdff18e2b62a9372e25bbe5b3e529285f2893ee5c869424d3d1dcfbf92a3403987ba6ba27aa96e3911de43b86da504cde9ab1535381469dc1539bb4073c713d46f38b384644a40f547159b28840b50459c5994fd25b7fa071beb90f56976640513cbb0c487328d0bca8f0c47340af10f2016c9ea41c4af6fc8d81f4763f01bba4d2a871e7a3b081b072b96f83592437cbdc6157dadd6fa67da66689f522cbd942034b75c39397f354fa8db618f8ca3b18a8092b8d7af4f892bde5bc8075e1e1667b04eff78419477db88e2073e80e78f3ab14f5d4bc07bd182563f01e5d9dc1cca6ec3dbecb1a2b04778ff2d093c5d4b4435ba808adf5aa10ee69e46720a07ff05c4a70edf137f9e25deb8eb0ae95704f3594e2a3e3eecdc415b90919caf27105ad0c8328e08de0d9fa0dd827a2cf8b223c3570e3fa8790a203c5a7705e901d0517ac9924f77cacfd21f9a98e8064e331549c7975240406f035701521982036a7249cb946665105952d8d59670f39261af7ae88277ba99bf899ac66e3e865f80cd9e547695ac6184508d944bb2a363e3ed647f5845d58b51d7dd05f047d8042e8455171263d5e13d8211c73b13bf106a37a7ae5d46e3ced1f3c446bdb5c0092b78d8e72f701ca8dde47b481d5d358501548e1722320a149f3cdaf5f651eff5d9bba208725203aaa33560601d30319a07f8c95ccfadf9c79eee5948b9673ed0b59ee816cab8e1c9afae8721bf4aed68ebf0b6f5d99cda94479cbaf8849ee9b91bf98f024ac82de403ea71cdf96478cf587c5133a7819a69b811b59f45243866c5c0633acc31564cde6441723cd22e363ecb78b419f74590115af2fb116e24d8e6d38fb35d33e5899e0a0387c8a0f36e4b3167c65ac4812ef1f6ac708e98878e1ed417500b2dd57fdb28f244ec6bbed10971abdfc52befbb5970a90a415f4e70fc3fa2ee2996f30a7866b94743c58513c1ea18a7ae677d5453f750d6f783c8156cc584c2bbb0e82b63db14e0114cb99137af42a6f82ccc1e8e881123985639f31e6ca6bf79ee12e0d87f40839104c451bd8d9ee6f98829870d1da4d1a8bc0cb4f0d6f940333f94e9f4d36a0543301900355fbd0eaa0bc3f5b4f6d1451864447019914f0a5a0a470b126d88a38407f212f5dd7ec343f0350c9c438d79af39dcf59726767276e3f48c6e4e0b6585773df707b593e7fe2d1c49f3c638232c9bba6261aebb865682c133a6d254d2870fd7e6102b56af38e2f1b9efc0391c097176340d1035c4b5c56d68eb309b1f88572384e12ab536150b6b2b14d3b85656cf7ab1f7d1da1420097832e8f653a7f394a6958be5361170dc1e9f43846aaacbb7888a52456db50364a56efe5e764d6cdcced02e9daecf0e2763781dd3894a4354aef1ae9acce38f39b24462c5e645ee17da0016108a79b3c61ac405d4ade7152ff8c3b4ab66dd59326c34ebcdefcdd1220d9241346b1a8a3ee78fb93b661312f6605aa008f363e7ba00cce4559414ed6f0519343bfed7a116d74ed1e29f721e5f13d5e233a2fbd7c741ab3ceb3e93976ce801fca94fc05572a35fe338d0bb9075a9249360dca42903cb1a65c3b3c3f201baf80e6e8d0df325481d8a1b9ed2227a7f3033d9fdfcfa05597fd6e49cd0aa39f29c40f7f7cf91128708951cd0d805be4bd38bd41387d430da54bc558868590f3702420b5777fd17a041a9c29467a9b53a50daaef29400ed87ce68358727a9de154a171975c592027f8e48e92177651460040d3f5a3156e7a777525c58956177947e48c617f1767037013d0d885f3ecd25d50c9746072e95f6508d08d91d8855728da49501d53a392c5f4bd74760a49ad90647a156b41009399959cbda89387fbb0601d9088893f6efc08da1257e8670513eea4cff58694ba2745b7b201dee352b7a911c28ca3e6c584d5f77e77d863ebbc774c1d4d035e6636dd01caf92ef29e722863f8137659c3a0502a7e2ba9aa6a7ea5d3afb5cee6617f4d03c3345db97b58d245b1b4237184efb53923a839466e624a667d720600c50c986b154b1a7039642dbc3d6701e1615f06d787a84b61de7467b345977d372f461b5bc94b6da8f598cb06c3ed9ffb8aae31f192ea4b6eaec585bfef9052b55ee90003d1bb4c280eaac66a373bca31a249ce45f7cb629019dce5a1b32120729ad0d9b0c2041c0b189ed7714e8e5b030e6db669905c86d94bf3e1992aa5ee643bf518b1a95d6db5b02f740690ddca585c053cd3c0f3e0e18dc5f77b4f866d0e8f831553c04d48404306c260010c796e52db306cd3d911259bb746eb9078661177dd5fd86083674aa980db8af9d985b65c795bd044dc8bb082ed3b4f992b5af43640a6fc78f6c759bc7a994e7c69c4553d7c3abdf65748a3c0ec3fc68e1006046d09bad8f20fca5a74ee42b4506cd84a8a6b183bee418879bb6ab5fe8c0ddb77c07ca0fbe7bf09ac00d1939d042a9656d943942f7393c103a554c24a1e5997294d87f3ab53b885043a63bc17b9a04677fce7a0f0e70f08fe6dd63dd873137db4dbf434218a0b7c78ed24f1c0172241598618f2584a880c8280e114869b30fb1e3b92cd53089dd0af7d08f414230893d214cf5629209a4487787da56047493447e0c60de113cabad5898a77b54f6e7e3216bf7cd6a83a3037e7460e755a4816ff49bc8963426f6ad6841e87cb3f7c814447c5f96d78adb8a26f1ac583661ab5452a366855493ce37343704c527a25839ead9954e765dd3e64194376226b58cc8207d74ae8b6ef06133657e61f625fd84b7cdc51f9128829a66ee8b594db2f6b24145a74d7d6c0d57722b00508dbb2eb31cd75bcc25a21629e63fcdb4c930567414590e42f4ef15c11168d2fbd0e70ad243392568f9faf540701c0340ab70298c78c4e90750c37754a8e4c5ab8b7c69e3c8bce442678e22a5d7bbf29c9c3808ab67ae569c3869b3eadefe4d1992f0362ebde999ef03bce08c66e5f19b8fd84e29924a9f6d5dda9c6637e5c826655464db13e1689bc0b0b78547f2d3bf379eabea992b79c7b965f1939b1439855a9c5f82f15d0ace3feffcc196643529b5583269e61acdd869ac048de92db6a6b2d4254fd70a6e2551f3c47d14b6990958fd4d83f616a50656375168df411640622133f868dda6329f0dd36ff3ad29742312dc58e394c6e23131ba0d7f2cfce67cc9c2f3dd3a1583762c8a68a8fad8bffcd51fbe338e95f50047c2935bb01a98721a86571247d583566a20be5bd8e5575bcf905cc8a6920ea4a34677245a366936d094d4434fabeadf25f73fbdf8638db557e84994eabb8f03fc681c38210202ef3f61bc3486e9329312c936c6b4163ad4f624bc98eee1088ae3b7c47e93983e803cbbb44b90fc2490b75f36d2b419dafe27269c34f9f5ec6eaf67266a5e132dd566ce883edb7ac6efd40e97d388444e14de2f855cec5bbb10c0fd651deca10e8f9fda972a5fcd330dbeff7718cc9648dbdc45a3a949a1200588d511542e44d179e2122e014df45a2a14aa12751c5ec5fd299355e52bdef3d06af7a06bb452ded55b8303f4bbff3eff014e6874d56ec7fcc6d047db3e2d977cdfade03001e3f717d7a73647628f66c866f328c498b9f3ac4c48c20d3f9847fa04c653974a9521ec886d4bdaec36b2ddb76585725d37083fe7cb57843e91d44245ddb0b82dd21d738ead96631d7e619fd9cce58708dc46d75bb93759be0be9cde745eb4c710f76a93bbf32fb25ba21ce31300be1eb702d8958749c320c1536bdb8cbb9ead5df5a9c6256c150b6d5505bf8d2022f8b5bc6430e17dd3afbf5782deb3ddac8aa97323988ca0b200671f2fc0b280b2ebafd64682443fc64ceec591c7f9f92b38f57799122bf26cae64b33262c52f5700e4459507e12f408219c672b32aad723cd46cd97550fb9d2aaaea13e5db91ff5bafe5979a90e130ed6564b6aab5b9a326bc93c36e598ac176021ba10a812f5f1f92735b001681ee4658d29c19cede4563462a45c148a826285ff2ca9e1a728a94df78801d4aff73c61996bac548039460f9d8e2bd2811848baf973c090c3d90a5124e57f8e839d8b21cda7269af2d22c6226f8ee56811eeac1aea813c998f3b85a7aaed1fec28b87d4a7f1ec23c05a1c6c9ae6cb475f4444d25e433bf10ed7b4add3dd5f1f4e9fa2cdc6ef66acc6bcd8e02509c07dba4429a78fcdb8a71517f221e189213c51813b8c4ad01da3c6bd143916d76c68e34035c92b623b804fad28860dc8df82514ab35feab0bced799445c656196ddae4466cebafb4f3abe164546c53376d71901cd205d9bd371b6b25676527ba230865a8b7a2c8d17a4b78bf008f657d8436dd3df4dd4c768de9b6dfc036d99cced6b4bc434b3d35f6d4dc744e1765cc8738f827d587aef58d7f542a951a09b383a2ebe30d2e21bc409ac902e191f340adbe4c0c38f7411a0c8e982c54928b3b9b26c0b3340f1cfb285047664ba155e10601fe1abed1541e07567d7ef232f71a9203ccccfc400f9c59f4283db40893b717a850592d3ef069122086303d2f38663ba36728ca6f90170c3f5b8dffce52f832d5244fa5d4354e9f32f5de3f4a288df97474449e2f62e3d3544b6ae845fab6904229ae66a4d7a47b163b6e183fe1cada7222f2c8424e2eb094ad993cb584891264541717c196442cd583ed811c7cf2d3e7f6e3e0e596bae497caf857364bb1f771667df634e7f91369e717a7721970774b722fb1aa79aba23d6425a70b2ffd95ee76468b1db3c25dcefaa58240e1870e7d772f1a9c6dfed63bdbd146bf65ebfb06841ad5769451a905894062badf6541d0fd38c9e78523dfb91cfa6dfd143bc193e9290edc9a8205f3f6525845348512cc895f4d34d2d3e7e398b832f7e871f032723a421191223173c10a61a47195479c93a2c6836bfdcd9192fe86b173374ba80646ed68889280ebf68fd9afe16127f81abb65aa31681a74672553636a337e01dacf508f34433989034b7a9fbc84d4783fb79c7dd8f37f3a481196bb607533cf56db592e6ed810f2071d4756a6f52eebfa781d8cd57e16539ba58d89ebe9ca68234deef4b6c375808b10d716d66646f5e7575c7e8b23433ef338971e943f0e70a6ee102e35dd09ebaea18ceee923be8a126dd660b375d5596c09cec833da5c36f0103fe6cf0e9d01f89f7890d1f42f3b3d972696f02e3bc9c4345615828eb5e7c681b0f08716f26f56933835c74491497ef83552c448a191067d4cf625faa66baf2967fd97dfe24d0b73aa29ba709872c7b6139d350342318bf4b3f075a6eb9cbae0fdb3810f622e1f6ee397a7d3fee3fa3225b3cdd81f1487ee9e9296aaa217ef6717e49522a61cb8b6e0c85f0d8c86d3df81c155e1ff9bd5bf0147afc09df8b1bab10ac3f855202362444d706de91300630cf49e88f4c75ae42214433c5d323f015a74615cdcb96c7daa59b5d495afcc741d56b54f51f8220d753535b575f2dd0a9e870b0eec7697b7b3895fffd7f43661f07cd144941edcd7c8cdf090aec13bae154231b8d31ba568d915abe970db2ced33a5408a033bb85a3532b79bf1e8498ac21cd6a2517bfcb7f95d88c38d028615241e51cb0a61b7eac28c513cc97b8d57d320d7d9c173301494c77cda76b052f6e03289dbf8a05a3b56dfee26f1667afc2c4b242177dbb75fd61db4c22a1e61c19488c93cbd87988a254bae10ad25d6a8f71fce2f38706efdb13609e674ec59c55c7fe770da7d97a4b2724fe5cde3a646d6a269e1cbe7bee973b28468aa5d836913858b624b4061e2b2d1be67c6fc6207bacf051c8dc3719341c96c75dba68acc2eb47c4740fdeb831e65b18ab2d7dbcdab719bd08124ae88ee865553729becc81f41d78b96e3c6e50ad1f3792437ff2ce66e507264054955c8f27c1970853f26ba0d4867557f07305cb840bdf41eaeb70a6a8a7ebb820098ec2424b45f6b40d0e663fb367481e1d294703dadae226b2192c945fff8a08b8002d3beb494cfb93ae5ed2f5f2dd8e2e4cd92b9eeb1f6df9e995e2d117cf25051cafd4c2f4b96b43af03cabf99981684cd1ec250c9ab7c3606b4957d372382a890853be7cc34fefc25213a0fc4e58c47bf86a86e560f0ed5022a69da9c1aae8c56a88a727aa6ca95fad9f109c2412c5220153929a021642488c031f0678757b7a19d56b549883c1e641888adacef399b3a719ca92c546e73447971ea2dc161bb782748a8748344f211d097d46d74686faf4456944827f8789f328e05b09f0aaec5864459a22fb29986dbac215e8bb95e004681126cc1cc082375aeabade7083e853b5c9cd1d24b65180f377fc8bae2bd2efb02d1bb74013df0ee2606efda8509fcdf20c0a1ce78adaa4be25c3e300c06e94a9a3dbc1693c5ffda514179ad2a8d7e316e9d9ad7b633502fe6bf058da71a4423579a40930ced856f145aab69790fd50ada6c0ffc1b802b2955fe0b73b2a596722974bf126a70ee46fd8a6082eed2076959cb8dc43ad101b562d5cd484bc80c91fee4040a75c8d3cd24151040290054d4e6c493db36c76539ffa06d3d7ace8525daa3cce48fcce6100b483af9d15bcf7d29b536dd7a81af6d4db9bcc6568c58958ce48e0006980e6a25958f1fc5fb036db8ab2746f70c4569e8b4ea346fcc47d343078005fa88d2b9cd47983b2a58dccfcdb65e46e2c8968911d221d5337a8d33ed884beebee25d10144dbd2e4dcba20c67091cabd7c1abf99a4d69f9da3ab70e5318e72511f272ab19f422f99138e62a31f3f144206db5aa198b24f020c241b2b0d79f38990ab65ab087d93e152d9cfd61e89f3d2c73cae7b0247077e72fd2d53103e5ea5e773ef709846acead5fb36e9d46946c7900345c1e8c57236de314e9d3a4b30389f57881931b1e589d132038de2ecb88f5c7cc67f33532f4dce26a69d60f64a72bac3c8c5382cb9fdf24a07c60933f34706f32007223828e7f3dc960bfa1fa6decf4844e005116fd2480a584c31cfc82c840d3e0183fa80b5f648f562742fdb78ee5f448ca9117656f830d4820670479f7512aad5f42e330a4b81ef8f47c27a62d57dd77b4b7f9b78dd963447f445fa4a8aa1cd9b1e43f7b98ce0614771720e451c107741c43be9e8f4f153f5948ff4bce68787f1d674afb5d77b548282434b3c27d03e3e3d8b95f160f9b0b209a4b918d06de040078fad74e4e25743eb143c25fa73531b81da1acd2c757278b4489c45476b578fc6ae78f4854e99ca1bfc4168bd590e7161551f436a9493ceeeb0419097696117d93aa036bb04dc5812dbfafdb2be2913b5c6e3ad8f5607a7a92d64e40de5079d991f561f144d95cb1638dee37dd230d074f6cb1b19bbde1342690cfdc45f74fa85f3593a6eb69e7ea353c7e0a5be9bae2ebe4d974b37cd6944ae6ada03d92ef07d611ff4a6b313c78e59c630b4e8ff35eabffaca9505c7ad179a91ed24d97364632c4a991043a94aa10730a30e8636bbc2458a6ad01318aef2a457e2995511d0899b452a61b6a16453f17bc6c50a6f9a1eb0694b35458afc25b9fa042bca2638718133453848a9e60fbfc08587eca8d884aa74251f966b496e9dd0267a2f350d0ca807afc1e803621bfe6986b72b27bc72a693dea4d13802e6a0f422944286d7fc671f91d9f98d5c60618ab4cb8bc1b06b22d7244034cf4a176da9002bf32e8fc051cae43f63f164a2320621eabb8518643dc44b70c897a8c1eca5da02f3502d9308428570518b35f79c96ff4f50f9c857830c5bb6ec86dd9978a3087ad18822baa4811c0929925c0596466d55769205c805b5328d86819b21fcb9bdfbcb541a0c968aae7eb55c3c8873846ef2fb411b7db385acd0493d8b8f23488ef2f33dee8ce23a8f33566921a3bc8a3aed393310d73c8d1725f0e63ca11b2c20c15b2624726871fdb6c9837bc7f4e09b87ca56b4df0540ad6d466782a15039e36efa63b0f9cf2ee1f7e56c795441fa402c66a2e0f07584dc3a81243dffc19e076d0d5e0da1230d3e827f05f445f5500df19ae04e7d3ca1633e65de8a052e18afe482ac0847f947a1e41dc3de0606a19ca3cef94221c92c470aafc6214cd36a6c563d8936ede37eaa634bc006d7ac0f2ac96d9479b882bb4fc70f84a9b24b12787e7fdc395443d328a29746d2793e53e5be6e50c82a5d4827a9bcb3815e2a84ae936fa9d585ef5cc718fa279a97c3e13a57609b84f3fc547d683fd67231afe192907078c675e59e457fcee3fb36394293e46f22b986fed4d216956f94b57e3b62ec52940810d7e51aee55918484bf0843da2566ab7f75451d8843b145b83dcdb3f0bc7d0f155911e42304a9ed022b3e9bf25d6d34da0388df68fcd6941094c07bcf8850218052440995f56e7d4b1fc7c1853e6a4710c81d44ddda6b0d52b26fdc40c9aa2195a8ea71a38b8400b9091cf69c3b9200b38ef1c3a673e87b81d970bfa4e419d508a6c3386eb98a5adf07df56e7dbd25b024f6e609164964a56c438ec8a7584187a4dfdf6b2f94fd6a1337a67eb75a89fc8096069666ba777133f5e74919b841ba32cd577d7df3570635411ced41f47b7f9655ef02d7865e27bfb8743b9f12309e20ac1964e05de818a93a90fb954edd2e37ea53deae3bab435fc4c83a3dfd6019ef8c92d35e59294a52a3749b8f78e5348b3e6cdaa437333766a54987514c503580cd7025df131b6e2490f3dca758eac24fb4fb63be5afd841d1ece39d2d1e7e48e3118d37055af4673b50841c88b8a9d75aabfc418f397f8d18daa04a448fa472650fa31b4d07c54016ae285d9f1fd2e37dd9ba8fca2fc08b19984e722c1449d3c3f0058d93f3df72a6c0c3d41b1393a88508cbadf7e5587619825116e80f71f3388c162008ae4546a765603cc7c770daaa73547ad7f98c6fdc80f89a775a0d46a3b1b21b206013c1711678260bf7405cf0e6ae8dcabc6df99befb2af7ecf8104acd883e957a5861bc5a2ada0c8304c08ed3c1ba0dc1048e8b98b7c485cec3f6857e4bb54e3d499501be0590c240d2757845da7eef9bf2a41a71e5f41a227afd7eab61f413f9ad0b5025065321b088e62b13c998210172a6b12f26f1f958ac678e10f9be40ae080fc4a49b59afcd68ae46ae7d69516917cd12e902620a0a54a347cea76dc914b13cb5313b4539d2e03976497bb6162e53ec725f1d7a6dbe485526654ffb6a7d0c454a8f8d2b8cf3ea786f9e6a448d80deff561e6978849f05809908d7cfb79fb24701414f56814533bff89ec8a70da867e255521723c37c5cd1fb84eb72dd528c791e47f095ab97c2cc1b84106c22aabc1efd164c271568f14a1fb09bf093d597ae44bf17fcd72a212de5e9dc64ce22c17a171c91051c965d86eb9a610306e9601b458a118fa25febbcca5e13e46169b24c3890ac9e1771bd49253bc723afef5610db5f823a0c679877010260a6a6250414b592f3cff28708d73a19b2c7ebc5b38bc267e6f3671d6e4df814897f198a6b007c9a8207a7d12a838eb22d70d167a9c2d9ce96b8b7ef6ded97b1ebfacb7c64dd51ed5a34c9e51865bf18591f8791e74504b393dbfb6b30dafa8a33be62bd669f2706b0f0b455c9265b6e12bcb6aa054e10a460bd3c03cce7e3affe9b610bb9c768a5c96c5eaffb700deb125182c57f56df92622c17841eb8b441a4c2ec5b00d6e90fd2d26b92acd56b80c6ec5ac86a440749b6b8e3bd7f303e32caf63fdea86135c89773f4b52d2d618cc56db83fc2d295d32df38581b2e4e3454504de6a354536bbf751c67425970a2640e4eaa35e399e901dd6225f20dc5c1dd887bbaa2a74590d292618b50eec3c72e08b1cba94a1b694bedff656fff65d539672743fe33bac6d33dd8df1b08956d3b73a676b86195d07543c90a1ae5c8ba9368f5f51759d0d9cce82ccd703cdfa0582ad7d8347ba3c256272e1b667764f58a60aa76f31da97f8cdb27d976ec9c5525c9f658e484f3b1cd5201399a8c5f6e2a05a33d4a368ac3305c5831c071a2d7d448f73d5fc9ea91a3ca09e4b5cb8bc114fc96cdb5421af062f99d75a14a0b450858ce4701ffcf2b325268dc09d12f71bcda9d65a479e3be60438f1a5f9ee95468e087e26b6cced0115c86fa7146cfbc24552b6ed3f53dcaabe1b02cd86a4f82bf8e4d1f168ec64695921a16a2bb0390459a822614ccba8d461105721c5ec7401833884cff20dd708c8c2a6dbbc240bd393549266ed0705e534bf67f50de045029a6b0ee26adde9228490fc8a462ae7e64cfabc08cd37150b862468d5a7a3a077f982957ace45e339f90306abb1ea22f4b081a1262fb95e64a1c631f4e61df373c2a525cb82d1ba5386de800287407e3b505fc577970b02dd9d03c36ef8c6c7bebe19da7e2377f4e3eda309d3ea1384eb43548a0ab0beb7eb0b690bc1eb9d453e992ec7f43556203e3e483a54002959784b49d94e7d10df692e4b26c8027de92307ac24ce21db3dd4299877e20be9d74373ef7f5327717b5f6cd5b14d9d9a726d60db0f82d6a177fad04b19c01f449ad8fa8c60909b0e010e1fe1b71d60b4e4bcad42e7a991c69b9ed4513b6c296802285b1df61e0eb47b28bd80121f6c3d394e62e7782223722222ecab2758bec0c7bdfec6303f257ee162af541ad5eeaf5e54535d2ba37133450cce363d35c4f026b65e298548155c394467daae6f977b9d0a5d151386ac8f1df51c59b70d386c874ff9930af0ab329a1738023abbf01b7fcdeb38c725a18e4e4751c69d5f1923fb0a273d5365a9f309caaf9d69c48d6fcb7505cfc9b28edf88ccc677746a2b7fc50b6df1b16e975e3835f8686d292d55ea85cd938c0028c6294276b94de1eca12d4a96cde5d97b4da37ca2b08b2a0a046d4f0d467e78b36d738ddd1c8b47745b3e87eba3c53704e77ddfedc0bdd5584f081f8782c546b254f8c67f47860ed81cf02c197218c5c57e0897fc835c75c866f281b1c56991fe82a541b89a208cb85d45c3291e3f1c53179f5b6965a1caa88153f51ebe58fdaef921520832a96a39751a467988cbb4d1a6f02e1832b3bfae8b86eb7d225a3c62b5944ecbbf3f9c0a4e065e4b9c8fae725b360c6661d34705e79d73ca65e97c125f60e8012ff7677d9ba4dadff2a480b72aad078c934ce1405c38c4c6a01bf3d72116ba3baa0d3589641b3bb6f5df05bb82ab276051739e255a2c689f711f59fb1f06943baf2f815bbe2fc9fbcec2b13b8d578f39598a06a2a34c9606a79364f9bbf8dbfefb846e621d087c13c54126a5aabb9654acf6c3f20322200f860dea256c2649885c77ba97fc3e8e4df307f3c41662d03e0ea92514b91dfe1255cfaee05716c207d62b496ac6466c168706c13bc96271adac17a9ef7c2693606eb93ca6993be8f0e9863b0f0634bcab744193e97225fd0ada7cb38bd3f299ead93786e6ba235d583293b7412fd3b9b4ea3468ec2f3f6cd6e0b7c02504d4d03ce6c6c70bfcac18fa40a41efffa4b879109d3572b9b02b6dbf6af724cd98598cc59b8c1ca9f1a9e88a7f3440fe775e39fb79b6b3b6f778e5c88d74f5caa2ea2dca601a11c515c0d5826df043e679cf6b112c21b89d7e81f59cd17f9b71d7e370de2992f1eae25aaa62151c0c441509e956714e62c651517bf83e2140bf77e95daf10a9b599c0e1d35f4f4f643b61d62ed7f39623c10b74fbb3404fa5453e274d4df3c4b3bfdac6b4e15c84af2b34e9b532ce3691539a8bd165a35d71de312356da92f3eee8f251c3625f44ab128def1bdf3d0679aa0e2330c922b5a419384607ef33605419b9379c49fbf077ff87a85631990bc9c0e42406c3fc76310ec9bb0c2c70408373ef7e5d6a4ec0bb2b7a9a5caed3a734e1398dab022fa6e67f7b7aad16313768eadb0ddd6d03167c07ca33d5ec9ffc7efdc24a6c04a20e9b7608aa1b10ced12335518961b4ffb87e1914ea9d0e3a36483ceaf943e2cebac7e020b63fa0b7d9771fdbba8a4f513e1f54ad7871489f96e27e0274bfd43830355f0b40439ab9298c2cc69d0493ca7cb3c3763b513031f4e30a72a78ee056c7d98396488f6c6d06666d87b13cfb37be36988196a5595500187a4d8ac5a87523c54e7928522a3b7d9d5fabde7bda06b1189e7eeedd98d4c3d8a9da7a30f266aaea7535a55580aa4cbdbf769c715add8b4c1fe8e4bc9e9136773f45438a365695ba31fb9169304fe46a1058d79bf36a0811627f085ce1336046f8ef6feb4829f2e126eb5892e64bea278472251daab919be453807337f9d9698fa9ca6eb4ac04f1063481e863b69526ddb25a1e79302bc4cd4fa1240b1d6d0ce158bc3c4fb3197f37a3784ac7b75124f1a55d9535dd25f9330095ec8a23239c7c962769405e9df9e24db98ed835f19eaf07651fe365c53fac52d6dcacfc90dc2218620d6b9b410a329f10079f17e586b41abd3c216ee5b63dff7dbcac44eaa7e9c070fc0141f8baeffc42e9c87946f88807ff2776b49b0e81b92f974cdf6e084df74acd1951f2d0b9561003a8f84a5aeb7460a2e51fa4f697851869755278b56c2d97b8ba890eb79515025d91d4f51ea5924a3cbfede55c89032da26fab4e612cef391abe7e32a74267f3191862c0ecce3bb6e506fe207a224f0b8ff40829a2989a443a80fcade77f86b5891a87bb82e11e9e16cd2bd9b0130af37bcb8806e8ff6c29a99e1f8d3160dd8f0ccceb8d6ae8af934bd7f0e186fd3ef5556b09663da8a87b25e9ba5b68bd93381a158c9757493225cd7ec8c13a79d3239cdd52d14b8cc231ae1d4d89a143afc5e025f701b544c13031c4a21a4f5487f4b2e13d6e0e6ac80f4ab1997c44e829416d2727974b1b1b162a0cc9ddaf283b7fcb9fbf5b71192f37e2ef43a2a6f70e7dad7eb1abd2787c15fc60b80b45b2eb18e54a39ec7716ac31dbb4147f42e106175123747a4c7a406a01cd15a2610d66f042eb75b11b26db4419667dceac07c2bb0565b23bae21a9017267c6ded6724652fdb98afb8f07dbfc0463ed69c7ec99aad90348a56a860143cfbfbfd0b3c68765288850d62d8b8d0ba82fdcb4ef1904d10ec5d148fac1baa6a82bf0489c056818eba6518877420be4ee5bfa862653d7b77af8413d027b7b94a9a65268fd465292d535fbd8055bf3c0e90a7452ea3d33e9fd33ef1ab66ba78656dc10e375df90c3308470265eea83e0539900d02db4043e98868edbe2a7ac0957a8ab29f0f7a7d72c191fc8be952a31496ae627df96a2a1fabf1d44b91365ad10677eb400a8cfa93e8863e118749aaf2780bab13c018cb629b6d399742ef7bf93fe03207e30b4ac3fae5d841942243108e797a6e39608e50ba113a1012a5aae846760c808c4618f3d5339d2d7fc50871ed8b8a373c3f3549de80e4eb561f18415b9e0825f97eaf4893d2af13091e79767975b22ad337873f05dee8a863cbc9c140f40af17ff0e017c1842a09be2bd3aeddb2727f2ad5a43d7730779c836d8ea4d2ee0f646e00222d00ec1cc0e77fef63f03abd210da6ad86b392f8c2a17f4f2458222f40978f401e79a8d6fc6a0c93b8d3ad0a4cfcd6d4f53140e086dd6a3e6ed9e0f65ee363bb22b4217a5ddbc8ce731f1c05839436b9c16db5359fa7c29811767f3ac5de0265a88f0b7e7b01e925e510c15633ca02d549e39f008c60f1d24118d7fd67dc58b5e71e32134e450b60d13dbd6b92262aa96bb8bfd6cdba5969e0274e3779d3493518d85057f5318e05fd4e28feeff05e530712d38aa5dc306be6cdf47ceeb4f1efa276211f5df849bb9672adce5b61b2ce538d38e6b40b2063f1806e241785fdd470b4994d48fff5d8aa1e4aba9542f418dc515eb59d885efdc68b92df615316829e30983353a313cb07d27e8a159a02eb6a61d622af5af18d38e128c7589dd94edf0be6b22350a9557fa65f37cce8ad0b66d9730257413db1eb5513cbbd1f904f55dd5e1e196d79d4f7445329b81a05a5ee9d20b524104fa10ad6b126af1968fceca0f4183b8a0a03a93e7c8b535c9c620d34adb3b1f02b9ac4d6b8273f076e56a31bb0dd52cc4ea73192dc9afe124a382580ef02378c8728c2e4fbb5d9637034e49e0871e8d411385b37aacf60a5e422094c59c1810bf0a2cecd21e907d694c018e370df5745be165029aa40d7f76c869b4c8d0062f105ea0001f72bbb1c6f8f6cc375173885edeb01333957a57a39b90fc15dc9ce962fc0a0c11824bf710c993bf8e0fb144a1b3e582093860344f8f240fdaff5cda886abd1c6afef4e02c55e3e524daf1203651ee4441efec69750592f5cb0a352241b5d632c311a1cfad6d57be333ae9f89e084455b2260d5a53bdfa921f6d4dc015a6604145ef46d181011643b929743f113559beb3c3a17c6dc5127126e053042b02160df824ca815b9c1138e7f424456894697840301602457c1cd26cdee28fcd1dab1d06776cf92695ebf58b10df964c72bf35c8522a0acc9ecb48aa6b72118ea5fbdb42a1e394989c7134ccb11f89414b5375eb17d8dadcc301037df25524ebd0167090c0198df332370c8c14d9e48207417422db136a23d7deab19751040e879628c69ffba94ba8e91715ea84bc0312c939ad2c70ed47f687f32d7a05c2b0d1d4872267b73b18eb99a679497679b25ff53361310bb9ef365f6c3af8d439fd2abb860d7f18d49e0dc22da5dfd2286ab0b21f9af7bac7a949954651c330391459f4d2e7c65a0d89ae038299e7e633189301b7c2ef5dd11b5f28368281f287bfb0431802dd533e5d2686097f1990fb2bfc0c12f7e2b60161f949c92727628f5262d159e08e6dbcf2930a0be12dd7fb2a970ff2d1be7b3b03079db4730804bc39689f010e9eb6634b2ffe834eddc7a145d29f4326ed08b8d9d97faa47a2a12b139b67592630f413e29b1f01d3155b405180a9c179008993f5042e8cc0cf96441d91e672d89ddfdc15616683e4adacf2342c4b92aef16e78368c63a21b86302105699790f62a372e476c7812b72aed5f69cc80e6449793b95f4911ac3966233a7b5bc2a3c14ca5ccf40bfe9974622f82e295a58c882c85f2e378ca8d2a021d63d7e7b0570a8ed611f9a0e1b5f7edbffe292ce294c6b460917207163b92241c670f5cd6df66af1f79ef3230883f077f459f0d26c7c8448f3f9995088e4475a4d228c58104f1373f9768ac77da8978c6bfef9da3432a33af9b6cf168f613a38e9070ef7fa4f2dc2e283dc1577b41a5c551b17c651261ffb219bf10f258183378e9070ff2e8a1c449c1be700120cf0b50e17de8a7f1b85a5546f35bb02311023018cdf4bcd4dc9636da471ebb21da6a95fc9f46bc9b642c91aed1dc33ccfc1bc232e6e855b675b3b90eb5302fa45ebcd44afd91f3fe00893d24f0b45b2b26b54f57d01f14e71459551cccb3af623e5848f6a4e69f083beca54bff05c7374fe9d94127f9147ac60f11c3aee61e0ce82296f9e6c18953a7079c6b8e42486a4107ff79c9d662ed0f926947f0a4aab9cf42d2adcf9c3ee6c6b64e0f51f9054ce4b70ca1c946d51fcf0283d584588ac02d8c0e89b28c4e332bbb8f6d72d1e54aa78331f05af39ef8eb1179bdcbab21350ce9fbbbc7dfb9a4353fff192c974e83537625a64abdbb64fe115fd1664a25b358a1248fb936f0f5f8d10e5d60ab9ede789b09e741208e1d7f0751f0a2eebddb04476d35c5941b0c399a938904e9810a3bafaab8d128a75b003639dbb7629e9fff674dc7bc44df71c3c02dc794fd7210d944e7a57bfdd22fcd0b1d6e056758af40e29199124a552f2ca779dd72ace175c7ec027cdc2486d5a56521f9e5ada5eaf9ddf49dc9b27cf4db68c9f41311136b89c132efc8fa8db1b382cd6fb239ee6dd0e3040139d326ec3ca1b159d60348b5d77a47566f969a71e101ff1f98dd7d458645c3b8f789f485bca5c99a9ae5a4410d8f46d412a79de336904708b912696d9d40d3e3e040d826f953670b3f27e1db65c39b1d26c3dd2435026f17c44d6867e69da7549dc8352bcd2f7198f3b1fd0100b3729e1f7669315f8fa46946760b3e557eb711007772b67e6344c86911c3bc5be342c863787b847883de2fac43acf8112e9ea145a744b34d3c65129d28ea009772cd539f3d9ca506984486f56fad7526dd197895f7a24afc2690bec6ef2386371ab7aba33b7d7609315101409d3e07931132f700cddd3f19adaf16b0e3e50dd16cb2ce930a2994dcbb46eda732b25467136362fc4fbdbd641dd33e87a41784a42eb0a302b8494e27bbd9b50aeb438ec8fbbf380a1a119ab347ea22ebcd0ae85edf7b08ac16c4e19fc65f7cbb6f29e74ac23823405a5dbdd87f338e402cdda52440464a11348c978078e15c9b4e4af7bab36108b62cc613a717336ccd0ccc4bcad905699ae9ec24284fb8936f8e2f6778dddf8e82ef9132cfab43de3a51c74e4aba74d1ff826c9248988942d01227c4c3d307d263a28c52e6f9375e245acdaa06166338976c3cf6d5f59b920f659dd3bc52cbaf65f5f71c17b835abaeb7c4e6165058cab0e7a88fb1efbd80189b56802d454c1c824fe4e5ff905bc2702a020d4fac3b065fc2c487b482f78fe8f28496949a2f98c6b1b80678fdbb8991b735cb88488645ed7d0a9a711e4ec88f6e9ec3ef4f9a92ae0ad343d87271c2e40fb4a7c7aa7b6f2e69eba5f0d0fa3dba72433bada0f9fc827c5003be5a2506ffa0695e0c59d374d87071504e76ba890b9575a14e372aa5deb684210229511b146edc762f9b5e8e0c335733643183fa265ed3a6b19442c9a9eab4b53e0deb315f7faa250a1dacff842891fc8effb426583a92b3c2a9054537e1ac0a1b4d12798ae5f8ff352adc7af010c30744c5f28fb8f2a96170588ea14bcfb441c4db3413b9c4f6958f4cc3ab42f38ff6d1b0ef6f23d7365cd4fd02e66a0fdee7238c3f81309396c25e8daa9ef6de097868aa5c523258f0828e7fa5e34fb3a70ca2b148fa0a1598a40b25a5975f1a37de7f1a3b0b3122f134e860859637b2f1ebc62efec2172211f85fc6302aabc2efb3e76cb1cc258d19b0f77244488c330af5c1f4dbd0ac4e9fda698aaaf1bb61c220224753d0a193f75f13481e63dc9bfedbb51a70673780f09c092986c406edbf6fe32597523a1b97e3052a64cc9cd01f4b0bf8a08aef352ec2c132cc8d8590eaf9fc072ed8015c70a9cc2df44bc7ac1975c689fddf95e9daf35db9c395d9ceb72230a740088549a94a7c5a7db5ffe4b5be0ac1703d5006e386aac6f88ac92536188d75156d315805a8c2230a5821ba0d9e1c470c550dfc736c58dd8e28941327103bea1a46709691885b40c37bf5965bcf60d65a7c2a1a4a89cd15589485846361fd2fe4b9f0623c46343856d471b4d53221dd766b16e55d552944b560e00c1f18e55957697b11a58c863dae57cfa0d568bf49b02ce31960730a034a72020a649d9d2851f148d0fc26717fb4c5679c6e4893e44a6417592451f28ca8a5ab3834b646a1a3e31140fd613ec4a700b54b7d8a9d5340a6b8d0ee8f60f32b1ac1c812779d6d313880ac60669dfcd587bb9996aac7389b1fa8dbcb7c248a454270c8d374820f449016d98a493c178fd95bad6405ada710011a06ebc2e7c59afa126a3d9b2aaaeb08827f92a19c8af124cae99da94bed4196375898696a4c8ead37ebe4ae8518646d18d3ab577f51f0a4adf1a8891cc971e6392710dc0ab45264354fb27efd3af65cff83ad6a28db46dc0667875d92c117ad46920509116e7395e7f7fc698c0acc30490dd47f68b284fb5bd31315ad7cdf3f68ff3208b7f238cea32f7832b93da92c1fb1cd349d247a3ab932ad460dc6384b31e170f155f6f0a7c3e46a96ab03244760e58e2f2d53bdfa4d91c7c20fb328809c9e606a6604e0b536630832f66ab377afca90032f0e010acd8122c3f7e5f75b1374cbccdcc3324b63a417e3566799f43874ec1c8c6b35c018faf491800c2899695b4e8cde4d7292ca9e944e58cabf8e6185c44b72a5d7508487cb0c01b8b8515dad14d6ee48be0debc588eb2b2035a8fec52aa7060c60f5291f65bd7ff034cb6195fa615080c34468e5ab0f23e830f6d55956741d39018ebc1ffc7fe010e0e3bdc795959b1bbfc7d4928737bac5ccd53e50799a5f23e99c01eea1b5a6156d2ac96a7fe31ef86ed588d9d46ad5b0e081fab3368952bfddf441ca2f6fd8376535badec082d269a13fcf7583a1f5d943f2ec517fd62d17f4284964d0223a8ce40fa0250e9698b88b4991c786721ff9026f2c0a42830eb0a8fe79f99ddea1b690bab7e76d858fdaf65fdf9e4c5afa22d3725737b17ba3fb77ebe9b749eb0e1b164312e07c06a20f260b7c46bf31930fbee3a60de08a1fe69b85a28863842181599f1eb38e7a2a698ebbe3134245bc68c41c88e5ab7f720965cae82a12e8764dcb3df1f7e2ed1b26bde563759e51538bf25bfd5954b4e34c8cf5eaa65b2d423b545755ab7f8b539c4ff9eb200ebebce2659921d8da37f865d343a1e62a149e138d0a73413be9d88431138d2b84d96791a15ecb6b4ccf1f93f8234f76a254b4ca5ee978fc322765631e4a786962db90f1339a6d5887ccd10230e8b8710224c30581b5f30efd5c7d2cc6f7bd6c7364a216a74ea672ee18f02b3119f9d51b6fc580433338e7d8ff56ce0dd51b9292e638c959be71a6f151eddd83ae26d1a28376a2e37df91092b75769513741212c02bebb8e8bfd0f662cb5b5f5d9ace8e015d3d8fa6cdf3f3dc69bcb1e06218cdae6401c1243870f5d3d188c4ab7974f9abf77c79efe25369cd1a5f222eb5afd725a81d76956d4ea7742be72f6dac9f3eed160e837d045812d52152374999d89ae94f6f7be91e625eab1c07842c797e8ca085a30d9a2893ef3bbc8aef1dbe44b5ded9e3ca6785b03217eb93a9a5294298ef70cdb8ba47a0d2e6ab7afd3e861c5b4dcbac23de2215b5761a19ebd8c49c85b23c5a6b9b7d520a6b3c6dc1cb5c9fb46ea6c05a19d967d49a048215785d65b8b7f00c351eb136bc8470d9b680ce9844c44deb0a0a0c3454a5c9542d08d7f2a5ab71da2f1f09b1e6ca61c17ce02dc66d51fd4965e2cfced7d5abffb5b0646af085cfad9e5a59a2022487aaba0ff7ab089ba0fd98ec015a602951746aeae0112ab51ff30d8e1ff82f587e41df16b68b8860018345f40a90309045dcc561403806123abe9ed62225f82da6ac1a3672000bc715d93ae479b0e6e449ad5f53c7fde3fb428ecdf3323dd4a202e75ac07d5c850cc5203dc23a68b508da215b1df0a8b1831fd55eb9166f494380eba2b0584198f0036deb87a9610a098d3d983a7c62f2e645efb674c72c41682fe6739c121255fef7ecfe263e6551c88bc3310a39e090d516e04df910b7cf6f72345315a0484b52093ccd23878706be6a68a740344ab4a89fd3f0f53aa7c4bba181fd1715a0903eb8b5c643a90ae8ecf79a769a6122e17eadf98a26981fb572af988d8ed7945700d0cde450082f8f4878be8da77527e064eb547c4c766a3681b6aadd3fd381ecb6e40e5b9128c8832bd4ccce4bb9c612b594f01ee1028d77efe9899c5807924452b881e5cb8721ae4084be1c282b1189ee5c77a4f80676ad29178c40a99dbb1b1abc9f60a0e3d6c46fff89111f8b5c20e632d500d2c1eb4a84b5ce910db640afa9708ad4c91c28ac80d15663b15626b8c00a54bec9d3331ea6d355282385a860e02b30dccd20da4506003e2d1a85211663f57a46d099e5f8a762aeef60d1591c84a7a38a2e4ef9952b372cae07cf2f484a016bf2c9bc3bcecca44dd23687d37cee7a7e111617fe866b45cfb95f9eb648d8f6168ab64c0d1b4b34171af0af9897c6d0cc8ba79c39191037246cac8d9a3260b9ca99b16870ee6229edad03637ae3b0f0dc50b32c98a7c0addea77ddfbb53cc3be82e692ded83b0904c40091da89b595f5cb2afb034018d04b6f615f57a7dcd718d608217db8852db5c39c13453ca0f6c4b619482449635ab536a7388e8aba61844c1a92e6dcddc3f6fe123080f403af4afadca5f57d4afb02fa042870f4f27e5e3b01c9869cfc4192d2a1807481e2ee77de01b774b370dcca01984efaef4e42e37b8b8c6d0cef45349b9106e621f91bddec11fe935001b662c4e195dbd17e2064afc5b8fd0ba547bd5f5714a51bac42290bd011d971e81a48078799063cfcf71652d6547a57031025f71e7b7ea379b7c2aaf25cae5cd71488acb35bc18377ed891baed82404904df52e3f2bc59f28f74b4b24972071bb62ebe860b1253ac35b73d84aca69a7d0690982aed49a0b85f5bd83b3daee9ae65b69b58b94c1146bb1206963d7465706a4fc78d9fec1ae3b67df0b59932230552b8a50670329bbb6b44e144bac0e33b3715725fd333b45394e5322858feaf205a97e11a196553387535a77312cc47251655a33fdb7a85f5248ba493f0f874069331fd1fec645a9d2b99fe7b99d61f6329353cc3059657ad10ed557085583ea95a455dde7460c97b9a433ab4f00b598f9814b5e6a4e07444389ed7d12ecd9776a94a5c8c2a5cdaf238b8aa573fefd65b07c46cbed2b260a3f8a2192c12c217460da1b3e82166a76cf5f8f6d8b548d77a377d9d1b17567f0fb0fadbfc4b0783a82350d88b69d95c14828a1cdee708ac62e46ae2d96ffaf51b6bbf0a8c0ac939e688da3e3c66d1db6ea4af29c4180209201ab8914331d2f0288908e7e4b1368e5e704c6f8960b6728bfc2f1dc122dd553ea7b1c354541547d34653e3ed7adfe527ee9101ff6c0f4978a6f5f9a8fd80edbe2312ba36dba523c866cc6a3f367f41215d37d3a45a822519e5ced69081aa485bf8a37007f479e05c9a31a22c9a070189195b679c898097227f73bea9ececb8d8a05e1add3a88f7bf319ad9444a4419468ef15fef6ac1878c3af936e00b2cbe34749300965699d75b1d26ebc07ac5b317ec16f840c1b3943b176b8050db006113f5bc2c7e7a8221c4db99dfdb85a906ab1079ab0c42ae3f23325b4fec5db58023b7a6c52318e0a54cee559bd54118c76fe896bef58d94ab5d76500c73f24908622e16355cef75c69f231a44e88494b351b48a26600b0da830c042a2b046d42bf7446f9b7a165271ee02a90121b395a1213589c2577da07559da742c1090cfc2b918e8d7dafe0052ee247f10f8b39c557e9ffa50349f3564ab34b50ecc2cc690357257b39fe16e04d475d708a4c3050f5b53c574a470dacda72a6424c93e590eba160fd83e786fb4efbc988ce046ebd15e6108a574276c83fbf79027fced131e64c11503d4e1144575398617bcecd229832b70d99b43a8be8b1b622120043533bdf90b373b7493ed161e995a307365f17d9f7ecab7c10034e4f811753e707a87447f45e9b64b92b599fb773168446aec1b16bb60cc10260ca59125da131a48fc9a3d63c5f277dfe58f8b0c06a4121c6ad2cbf2a2c8c6e6c1b00b26fd18cee9eac9342193e55c59d4fddade81cd6489913f9233d91544cf6647ed56edd67dc158f01594683c3850bfbfbab9f78085094debb0e54d38131ae5a1340f3cb04ec47d572c7c4c3979e7195960e4ede4be66f14ca56fd572a0dd090be59c68f7f7f32169ecd152b08c924fbe5f321bebd23018b506e70691bedfb675cab6482c1dc75e94b6356fa5ce794c814f58ca4f13ee003819a84234e6ad5d528dbfcef900618a60f556270487b43cb16d70d5dd7099a36014b05b85f28e789f2d5f988d1974971e20cdbd5feba2fd7736c2e746e5a70b58a03dc5dfda2e369b71db9eda123fa3ba423523a9d79779467f7480a6fc25672d5fe19fa68a02d8dce09b1086397868dd44cb25fdfa66a8c6846c81e1f35328587c59ee92d583781d98b786eaf359a41c1e9e3ce6fe4bbedd8decef9b3226dc264171e3693ff0178179bf44523c51736eb3059fe28bead402c22a3cb68d4aed29b2dd3760d71e589bbec02f66594b811afc2e6a9cdeee11e8dcaa4f15ec8a1f4e59e40508d1d3d39d3511a6790df3415d45b1479eedee497b01eab83b7ddac075beecdc02f8398c16c0963794d85daeaf200a4fe1c6c4db94e2e5ecdfbe9b84dd2f83769015a994069aa6f4fc5e3389b7b154c3b4f1704ae6dbd3590eff9a810b8374fa9c4492098a0d1db614efe1e2b0ff6f6a693eac9704746ec162a5017924f73bbef59fa7b3ba6f637c8d80a615845f859e82d0a9892183221a457828f13aef3b96df57e88977639ab370b3a828095af09283bf4f0601433c0ddd957eb202a4c7b0d31a0c7b6cf47b572898a172774079dd2cfd258966d556d6e351de4de781014a5ec4226b9a465a491a862791f42eeed3db39db39fa18a4345018e4289a5fc781715f7d984eceb505c0918b39b1d0b1e227e382f01cabb3d71f0ac8dc58b86548bb247b7030e4169d8bf46ee665d8d98cbc02a997f6fa3dffcf2f2c02ff5ed620264cc00fb7890f93f04a3a5e60db7200562b6df2bb68f9065e0a2ac7d8883296d2532db7304b0ac0a9a3aa89557489b7fdd6fd79f922559c980d1b944acd943d31d1e5467f80ab3972d657f3f87cea51916cb8e27e61532dde3e2cc06ce9244c8e100df101491617a367f95138d0ffc5ebb1b6a1047d028f61e166c59133d99128762b9625433cf999f2d7c6f3e9178c0546ecd24ebfc608ebec3b6a30fe40cf6cf8dee0a1d4b1c7514a11d22a8a0b62cb50329cdd8bbbbdab5c3c7da711aafd4c5904a8aec3efde867ce34215cf7a0129fc4dd17d6db1697627496978aa3f75e193e69ba0e297d6184b2d57ba72fd1f471ac9c662ed52bda00a89cf71d813e5d6edd7759ef529b25af4afc928d25bbb4904b5657d694ef9db652a9239e29ca03f6c5284caf4f5ac8fb07cd8d55869dd41a63c8ab13133b1943594a1372399e997fbd84978d006c0a8f50e91bb8cccd24ca73af7f09e7b3138c2095b34ae5674585233cba9ad7ca989e6f09683f0d50f10d9eeebe6febaeccb2a3310131a6f1da5a9b5bac766c85c5762d57382b6bb869849eb8b55b96b5769f0f4a25a484c1d65e86782124308a430309ef530edbbd1c045e173accd1dbfff5bf363cc0b3de6ff462024d219a0084895232c1897209f9ad0ba50792ae2ce1fb4bc4b9feca69d6f3dee3c2aff8d7096d1c9a248c88dcb9d295b632677ab9628d32b6521100d40e8ac04c19631127b4f2e5735486ba87cb6117e4b20af585cc31b96666c932da5feb8d639296a985274c79a769a3a229c9c7f59c2f6e5d2c3c2a651ea6cb4482ce2d1a5f830ed6b879035f0296f1f10fe7cb74aa39d1f60f94644bea132356489a29f8d038f3dd4d1ac86d2303e4e24de4ccc3814390698f58344f2291b93b261d78cef1e0e8a4a5082b56c5abd6181e37967e677f412156fa0ab1d8ab4f1fcbba2acc474e6e9237de91ad6e44dfd0e50187ed54489d9f6f7c843e2660401f5a1e6a46e53cfd538bb8c02e04316bebadf808d1223d083671c0482672a679a57a8f1bd0760d0f4596b00be9fd40414f0aefac614095f4da58e77e1faf783a3532127b4612b7ed298ba59ee7b13414bc43acc155e2591984bec3cebf9a70ad761f109a68e4b20191e841d591981293801190f00ae146622c125f119de1594768df19e145ac5aae8ab35dc4b0b2d14fedb613e87ec67cfe4659ffebb2a91c615c533d66f074894fe3371e3ac2c7e4d421e48bef98f122b7a7ffb6856213dcaf45f33afea670840793477850eb45f5771d5d1b4c4431777f0e950a097f4bea691f626877cd3a60eebac7e3fbe0352426e22ca0da5963182d33d8e43b3abc102d56bec95fcd15ecd4157efb8ad261aa04d0ee70969b451e06fbe255751ba052b2848152098584f8c67e147b190090352ebc1fe70e3949b11a662bc70d28bd5579228a99c14b10646aab76ebd17f60bdea08bd937e8f9a4fa802a8478625a5d5fcb8f3a6a5659601a19c9ec781aa5366720c648d7365ade4716b1b15954884849919f7a2e03b8b289c0dc3725db10c8e205ac96ae85fccb2eb65ea1cbe6e5808124d293674f62f189f78e8cbe2a7798caeea6a1769321deaac45ee15f85e9f66ca72a32eb3f3a558c84bbbc8b04eec131da19142c332f8087fd9710f6e10b069072f57661bdccd73adc1eec924c587ee2b271e9fd9a208fa8cd3c70bae57fb41c31a96e5e8f1517fd6d76858f4e32f09be92df8b6d178178e93592b2b1dedd145e8ac0ff6506f563d9c298197bebc0d677de4bbd1ddb0e130a3eb51bcb82363a4242e3536cee8286473c66019d42dcbca3cc0361baf7e83821305a0c5a3d96dd76fdec0c9e7c737844bec7c33cc5a36d105b6c261f11f6c23ea1bce1416928b73fd7b03ec511f90771ff6c6e83ec4ed31c7bc4c76c636a79c5076f52d4b95a318692b320e9148a00dbde706398b6c05f37b7018ac6aca7d5e199f47ed92cc50878eb2370c4975bfad1c675eb12862c6581db3432f1d0d195b7e5e261329a8f890316092c1dec41607c41f16395e048fc3bf16e16e36482cdda0f755a643d189b64318a831c41bb4424516dae239b56684bdb030919669c011c5a73d45ce113bbc6abd81292bee425f4a5b91f18952dbabd10f669c4f440f13a0535bd0eee20e368705d9fb3e6292d8b7fdb75b2949b20d6e903b48eaade1a6a35fce003a1937b630dbdc3e21ad6b34a119653c414483ccbdc090b5c4f54a4484044394621828e0ede7e714eaf7db87bef16323ba5f16315034785768c8f31dcb3cf893997a7bd424f88d6f1d76f58ff4528295c614a1668f1cd9f7fad92891d4f4ae26ec5fa6f0e1720a6f55f2f925d04fc402f1564f9ab32d0f411136924bfcb7613d1e6dace51ea2d704b5a2f6e56d067863701cd2de0202e338c69ebcdcede8133cca4511f5f5e20483607aa0151401fe7a05f67800d6cd5d8e4443089986c5317ae378ac6264314313bb23ad38c2ae34b6eead1def5b0a5bfd955cc9217be6e33120bf7253726499663749f995a584a21c139b4889f26e7b946f0bae2ddbb94117a1c7f53be2b070bd6b9ce17bab3fc7aab73436ae2b3598c069a66d2b1fd830eb6aceff5a6daa09869bda48899fbe7fcff6a6423aa334c04f3625651df7cc72d7b94baa5fa66c1caec1043235493535a7782735fb312d6d12641460e88a411b640182b2474359bc5ad3bc554591bdf8abd3974d4b74e5f6e88c3eff2b7075c51d99395b78915c5a60335a6c8e31ff57e88aeb822bc6b5cdb2ab11549e31671370dec1deff8346795dc84538e5a8894b30d29b7dd1152f9d0ba33d47a0cbc4c672b852e9c321f21566d3480d96a0f805e1ed5f6404f1cdd5a2156dcf9ecd4549f8ae6f3633e33f5b7c4f0f6ac6697f4fbcd4dc3d1209f9e89b961482652d807b10e0f778a8521562f3a1b8e8f5b22cc1fc6480baca3d4358dbe9e84fba5cf29445c4a2f7199151330b94f119224b19a4fa322f0553157f3c76141a31503d5314005a84c4aa0ba1b294507cce61e445cd307dcac285b84a6177c64cc2da5f24e9b7a7ca4b6a6c74ec267d1cad6f9b3e0cf7236811d1ea53f759eed407c65ce7a81c83640118ffdc6e454a1ed2f12ab8ce515bf3173484ca8de5bb11cb731f350d9866d0fa7fba4d25697cef58df0fffc102c3c39d1f08465b596426b1656c6a02377491c2508ebc1761b62dc27a898ad7d64b6a963c21255f837fed1777d324db4aad0108e231e5bf6e5d97c8dac206e44eae27b5d702341b1615963b9d47b46f945de082b5bcb681c1c881ef23d85748a7ea2a4c6c30691d374c93cc25edb7a790274f6777f19b0b30715bb11d106c2cd631a14a140801107ca4dc6dfe64f0368556cc8902851c905c084c793d48834e0cc7356e4bb89bc4135db80cf443f664ed43ece25d87895ec915055708e61bafce39026c69789284c995309d3e4aba7fe87efcb9e76aea2351b3ec046c10c5508a1b3b5ac3e458011fc5d53d80e81e88ee4054aa967f22c202d94f180d6e9362dfa13997c30129fbe5a2afb9217bab7765dbfbcfda124f907787577a23e64a414f22b142f0e5e3842356a9673ce4868c7462d167d805e9f979cbcba91bf12ea3f55e3b94e5b4e7139ff4a5af7f149fff6106de05ef1e77b49082a094627d782c5413d09b2e8c129179c469079bbcd6d46e5b9b1032229ec19b7960d43b7404ff946745f8c2d96259b5057dab043f3c4c9efe244a52ce9b915c2c90e380589107282f337734ee8be18d4b37ddd2766ac160b019b02b4f033c6713a21daa1d66ba0e84fcbc1705ae735b5523d132e4c72631b856496c35d1022f5f2fd77746e06c9e4a7ab2322b83b0d7e2b2039faf0766bf4d114f15bed8fa0ea436aef7679a950fa213aa861bbe56edd528361a31005f76dd5590387e198e1b2daf768929182717c81bf383f2c1299011247ecefdcb628333840f73856f947d8e30e1cdb27e65bd91760347611a6580ad7539fdf0f844577114fa4847b36af93ca762630d0830b3ce5de39435290f047d3f7848b10e3381ccba48e512d2c96005a1573577ab3fc55519c0b1713e30147402f117acea75c3f4f890e8f3c69f898b49c5b0bdc4c4a15d7e4dd1eee992acbccd9291faa8deaf9d7c4abba44853bfd9015f3452f5ee9c7f4230f0791beec20d61e5279eefbf41b6234cd42042b95695d5767615bb55b6d04090843c99f8f596d818807f87bd610b6a0166e2efe78a8347b3748d3d973fc07b1d55d5172e94bdff617a65ee5332441b2608c6bb727630b714909fd976cd2a999b3ed51baac381b068218df6586efd5049eb1bf2c35a922e09008a5ae4ef297e243aea7dfc54dfe9a659bb7317717d01ef85df7757b5b8c17f21c7f813b3609c1fb512beefb46e4a85102ce46dcfd28ed3d51f0f595b30cd0879cf9fe6bfd6fb82296b0c367d9474e21cc1fc1fbcb86e0726dfdc8148af06884eaebf1208902e16da73756693e9de0dba0fbb2a5f2342a474526a51a175a56771195b5dc757bb15396c1d20a0744961ceebdb2512caf03c73ee3ac9726e138537ef7358351fbb58c4e642c65283bc409513e5d5b2eef415ccf33642ba840d0c6a8d3c20e92a7decf5d8b4f05c40eb21da0c299302ab86bb5bb509b5bfe562f25b35ca33667937ead4b1abbf1d76e80f209d12823fbcda46b8a0fb0a7b53afd963d58abb44955f8d61c706c5ee2bfb7476c2280ba8db911e3139af2499d48837957c3460fd57317fe7f88c68e94b5510bab358ab5db806d4a914f26fd4f1493ee8093d8eaa87688140fde652abe67855100ec38bc63593c84ac7aedac12e81e5aecb1f6a8091d96b6c3fd012c63a719c8c933ef1a7a7f19e3295c4070d100aa78a5216433701f3c5a6851dc5bef42f94f111d674837123e108f8d6ec208bc03df795ff41cce9829957fc8b130acc708b128ae33df2ca079a21cc35200c1b58bea71334bf0af1f661d2be9fc6d7aa2897a4a00e447ba7462a47539812ace0dc1f123ae9175175854327235532c45d7925cda3aa7292f31a4f79181ee867389a03b4e3c6914e3b88160e5497aed2b6c5444955e4f4179f08ce656dec7b986678f3dd35c0ff52c906f26bf86eeffcaed5e2a3f63946a55729968ee926dbc1b0740b24b6387d48850f84580f5def559ea94c83d388a388196caacfb5860902f0e4c5befde4ee8cff66a3aa4d36ec51347157dabb83a9aa8af8980e86ef48ffe89da5b3831cab88106b01d17f5dbe7ea5a25d80df786831edb9cd065db522f678577a739b1c77d991b30dc4b9413ce72d33a68f25e6fb5ca5fea7cf9d388da38df293b698516b1adf4f07ec8c662681a75c24bf41ae9b60b7981992d6ef0177130305488ee5169313d692024613ad3640a485d174d2f1ae6f09042837efd8ca47652df0f30c789754f9cdf772ceb0bf418ba0fb1b025b6a213d05e4032f8d696d2410a1433acb4e87cff0865c3fa9a44ddba88c4c5d16618818355a6bac0c07075c8ab9562a4b878ec49bd9797f79956153685920e559b3589dbbd1931fae490a49aac3eae624b30d3a027271fd10d46ffd8b80211226dc36fcf2c0181539fac10ec2e731942830258d8466419abbd7ed0b896c59064e0938551bd738b5a1423a7b1b5523a6c1eed78cdaa71c25c46847b7cc2302b86f701fdd063ddb5adcd97a307e11e2453ecc52d5c59fd1c65ce4255bc5ea1df805862f2d91b643f2fdd682e60a1b47c1bc7c9e2e1479257cb6c7a4c1db104cd24516ec678fc882cd6c94d34d37942f2000bbcb039e380f87c2ae94031b317444070b3ca5dba992b3ff136c8a34ea6e375a0dc4e6259223413ccae518d893c56e974428ab39e563cc14f8e8569be759aa87a646a99c7bcb1ba1985a49ce46fea2f2165b371c4f346ca55181c1bb31b69e36067225dd6e96ce6d4cc09e4c8384ae78a0a21780345931572c87e8fd7198457568ce8dd0383d89cd0b838e999eaac305e6620d8a0deda005a9ad808cf25a9bd70e8de005c1a01b04cacd12f9796ee258aa4b213e1dd593b88ce4ca1ddc3097e603447cb9b8b50914829d8c35257d3061fe2ab37a448891e0676dc64b9d579683b4103d9c28af936685b639adb1ec855afdbbc5777f10209115f88097eb08e0bb631dc14d91bba5a1d5e09c913b3849cc9a97c716c7bf7c881edf23347d37f8b55c288cf8868437454ee3aa8334c64264e4cd61f1bd6c0549defc39e0447c44c3d27b146893fe0aa7a935febe803ddbfa934922ec33e39476a5ec3e005dc842b8237fd26fa072a12bb3a9f8e3250943876061553ceba8f10fc0fb4696b1c7b5cacce0a333d89bb1ab176c58ff4d60382706cd726cac5496b684d12dcacac954e5290b56addbc2dcf5d492f9f2599f65a8e2d38593efa0dd45fff2c950f93a122525be8502114133db5a88a70d34e59b7c571c891abd11b2b1b67f05ba6f0984ffb720adb8c643afefaf81022a00283537436bde078919968454191a30eb4f2443f4bbc6851fd59eab370ae22301d2c2a4dc475696a43c01dd5c7e3cf2d647acbdd82089f88874082eebc3370d565fe17e70f4a18cb8f08e7736ac4c85518a50c1b46133b003c4a19b165619706e4d7e44e1069c727686dd74c75ea70016772dc5712bcec313ff343d652c857dd40b0b09858184c59730e14b8555d342ad42754a78c5af5be810f79aa2830f6e67ee3d03fb385dae086083bb1f4eeb0fb03fdef298ac95b55ecc7b5668b508711beffb3cf9c47e78e9e68223ab6de91dab820e7b27d716149c9f27519968043c6d271f0580fae7f76b82d083f4b79c88551f8f920bb6811aba4ecd059f064255dadf8dfd4d981f5778bc9102cc8b782974b99868b7d40db17a378aa37cdd72d7a768eacddf9eabe3029f198c116b2e8831b81cb59b43f752621eab020eceaa66ee39be5122aeee63554615e5b1907da899a40fa06f2c9fa1f1c41b3f1aca9a1741a9a9db53ca7bafd6d61795b9ea42a16dff38a8d1ea548fdcc7da574cbeb2c54f0a179dc032f9f5b350fbb36d4ae65185d965681fbaaa74a912b2222188bb5fff9389e54c53de8a37150262ad829c4bc0dd0410ce941e24d57f09d052da7de420584ab3e468106ad5e2a0e6f2cac945942d65f40a4bbe5549c2812e52835ef0b39940340a6a0bbeccbe9e50b17cb85e18b97b6dd2eb14dfdc7b31419a5d020ca19d0e30356fa95e4f57494e65c9d10e05bb327b6bb1b2c336badb7646e457aa0a19de07a18abbc774024280449f272c3325935902b8b008c3c63557e479eba1776e18795da8434c27822f8290f50301f44217a6281b6dd9b1a6b42b1ff972b59f83c2844d63bc1c0943e02bd03447e238917fc20f80810335e57dda431186933217747c53afb82991f4d30a902fa60afc20754a77120506c718a94f9690afd2a366c6aaa6d22767e849c710d9d30f5c181057d212d2bba98fd564af70a57eb15892473d044ef8ce945fe13696aaaf7cb03d2b122c62781845a9827322033832002b04431127f1f24e5b8cb024cdace7bd2873f9c10ef42b8ae607d55276167178eda25592bebb2d996f2aeed3b41fcd884893ed24e5bfab671e5f8ed91604858d3643cee5a66efc8e19c7242bc6fd9d02302195bdb26ed47d9be5fa9a546144c8d186d069f7f1dac8f5aa4b5ed70f9076b9695fc567b6cedd78c6a856b99099796ff6aeb629c860ad088b555e40febbe7680d0fb4f1d5c9d19bd9813ed2b1beb195f59044d36841f70cf345cbc961bcc484eaf0ce18b8cf021da4e4055c6141e71a7c7a04e2fc61190fed44f6e18902b5be14d46b2204e65d2c8cdef975eee95a93c29168d6c5e70f7f0c28dc1b1572f4c65135d78d212a8cd807612b89d050aab1c7456c973ade1847ae861815585e040e5b1a09e969bad8cd9186ee7c2fcb7bd1bbe329c566e3b109eabe34096a016289bd72a1d6afd1bb278c29931b9d439098d7771238f45dc4be8953a45abddead047bebe2c11e445a84640f8671482698ddd3a2ccf06805c0c027383112ac6786d11306681fd88058f2537ff00ff180e072cf961a0e1dd509d55ae6db0f7544fbb10e61b9adc23ff2d6a446703823c3032e12fdb0fe345cfb8adcf62ae038d1bd7715e4be0cbbbc5565e8515c64bf4f656022455b4e32e7ac2645c15add4677d32b30b990086a2dfe150d48f7bf1c24d316dd16d35b384e87341166944135117a0b8baf133d893111ac6d7194097d73856ccc56a031255cf3381c4bc238f76f4ac34790986d135ea173e102acd29984e7a355d710ee5b2bd9fc7039655c457ae678d985ea822a93cdca9b6de2e0772ea22f7b817cf5712bbbfa1bd28ac9f21e40865ed01a5632b53d165dd8da4e6ee92c9d47e59872466248f37f038153eba6efc3158a2f1401bb45e942b044f4dd67deb4821668a89fd5c147287a1670c057d068361c5d119cf7062094e8b4bf471b85656032eeaa7cb7bb32ac71a2937b0341d56d56cd3d711b95ae4f9717f30b43a3a6a57d1dbee52cb93b6ba544aedf64a355c58da8fa6c5deb30e54f3de5f78fad466c8b32a15ace070744db166b9f71ed42bbe9d7dd626c0e47172767f15abd08ac343f48618cac931cab593f871eab2cdedded9e431428ecfda6ef9eaaa00d948fb06effffc429404acd059891f3faef1ada745687f94e4f66b2607658e011b4843215ac48dc5f0e2f512999625724f63bcd7fd3a482c9d436e323e0823b66e22a589d549fe9bc49c0eaee2889a0104cba3298b1f2cf399a0af56d56ca06755a6adfaba7ee92b9124727709936a734676c4949770af1d01b55597284ee16594154802c61961b751f749282fdf9675d3fe2b0ce6cfc317abbcdd0402a18890c7c81633aea06588927bd924af99db1f6f9c06ee2009110b5fd1bbbc2dcd0d45b0f39e5df2904e16d5bdeb304dbe329cbde63ce2558b00dcb6bd72c21a049dd35873d2fbb220f486477acb4ce9f454e15d5a627f073beba4d4e82845efcf911b28fba878e1698b1c3659bbc5165ab21fbe06677f8121e923f4a9ded472ad2f4b225ba08c4bed2dc7c20d4b8aa7f80408eba1be3bdf5543554e9ac3fc5ca2af7e7b5cbb684835b3a8762a933164602cf7a6332b7f7ad67c76a9243e185921ba6d1e742086ead60fe920da45c985e1e24b4cc79d94fe7b4d5cb7af82c67edda573b69e9f4e926cf97745267caccc782b3c03b75c63545571fe6cc0ad5f694a8d633563bcec292dcbc33834f74ff8929638590b7c1177d9c3164dafd5fddb879480b2795939917726175ecd7da947a177dba18d22795ed1e3dc0599ff20a8515f61d4ceb93c745c8cea720cb126a00dcf124d88bfad8db0a8d6647768ebaed386ea11687e316836086599806031ea7cb01a9a9a7991461cbb46b28101f13d5c100d1db3b8b2ee435f1ba50847046b059aab479a52cb38a9475939ad96d83ab395dff81f373945602588b09ae2b0a6f7ce4c198b8ce1f3aca8c39f8fb0c2227704ee6fdfabc2f930adee4e7c5b6760a7f77ed1bafe189a80366651a8b6a931d49c5969406181208ad059ee9ef184f58bc0bf8049da265ccaf87e62049f1d810a2540f6386d55472b6f789282d224f4f5323a8163e68059f6709bd74f1a53b5358597b0b3faf5af65609dff2c18b18c79984dc5dd1606f5c89d74811ad434f98f36fb9e563d74e17051f046eec7d451ba740b74ebb009497686a290e8d451229a57b4fe7f1bb8b403a6841a265f2cf3066475ad954affb96ae504efeae773a82c1317fd1d22b11929e422cc1932a4315523ba4423463785ce50ff937c3133f4efc15bdc1d894577971c5177084ca4332424b23bad4ae9ef370f573a9a67126882fc740d99730f411ef9b38214547538f520bf8ac14e7246b828011c549a1dfb5d8238a530e98044d5ebef6417ac6ece9555e166e24d100cae6adb0a2b68e0d641d591a108fbad30e2bc516d29e937734f44799daf38e6f18e03c62127fa4bae0dc4fc4de599fe762eb2b270ff900b5cada12ca8e5c22bfe5eea94d02422b04b77498ed7b87ed13cf8cf34cfbf175eb71a5bd02bad7456bd25ef8beb54d2228ed2d34a5f4eb73e269a0737c20a0f6fdab12f68244b477195ffb2292760339e5972123ef782c4e703232cb898e3b90586ca3d2c6a0241df9e14233288189c7a62011045856aa41a7648d5330399506953aae9fb92a6b56bc0974fdf19375b3b4bc6355fc6f89d3ef7d3e6edb62963d9497d5d66bcf1725c2e69de9117bc636958116d0dd7739c7f63e41163257dec92203341371c87953c6f5ea0c3d106123fafb5b94ce54b945fdc6eeea5bab9b899fcf83540c33f27f83c306183d110525af5f639cf4b3e0ae6e3a134c29b9eb13d1b2f7495d8e99b3c1fad7138dcab2a064428e9efbc83eb4908b0a189951a501bc621a96dff361d11f217915388ae935ef6bd16db6e8e55d4861355e355ae2accd4a18cf271473cb692b34e262f205676e242a0aaa3e966dea408141feb0356190834dcaf842c4d690f2451de303766394f74e56e1df8e619bfa239b521d9e71c80b4934aefc74be9d68c80c6e3e5df96ac32311e93a018dc5cff0002f7dc6c1a574179cbd9cb6fa26f517ed303304590c355b45098137948f830938db56344741e17763c2f992b52f13c8be8421eddaa01e4311729e3b5511278cddaa2855410220e73a124198434a80d06afeddaacdd0004430ea5ea91d94bffc672605df12e67c2639356f5913975dfc035d271fcef8bb7b3df50220ba8bddaaf85c9c3d08911bd2755fe61a61de2abef08a8d0fda09dc79cceb5b3fad0d8e0c7bb864fd31a85f93ecc149fe744306b75f15aaea4230e058af1364b1a0c8b8f98f27409fe9690307e8ca8339a3515eddce99f754268ec3128634b441da18a863e55182d455f20cbbfd0200cb7145e04ae239c68d81d384bacb7b3a426033a76ba599c7cdacefa2cd7defc053929429a1de1a8af20ae99329302db472ad88c40f68713917f25c5637691cd0402c08c07a15fbec929c12b78a7b80e1d3325ebe953f33910998044fcb365183d8352171775c0dc51087f840eb5a1332b6b57bba0355b6ad05695d65d26b35d44b60dd045aa7d555952085152af3bfd160cfbe151d5a3bef7a5e448483dc9303c32df4eb361f6ce35661e205a999f3fbc57291060ca5221a4cae538f65dbc7207ff3b0873e23803f2d3ff4eaefd3737a556d4ba587aaaeef742b82908ecafdc5e055463226a0e83de1b94d29f7892324f7b01c0cf0aaafb95b13ff61c7e885649454045b35e0ca0a717d794e92ccdfdad98aea72d6290d3008c1b66bc31bac1671931e9bfc36bbe9af62ed67b84c03585669e3a8c868ae5def5e489e1c6a4c17799eb641e414bbff15331d4cea645261c2845b78a79e27cce7686eebfe1860eb81870e9eaf76d897a71cdb99de93712208acf3847f88894e375ea0c489e0662642fa72490a0f20f457dc2deb0041f546f19ba8968634395d26781bceb7acf9b61f179307cb582dc7cc4157ff2e0c4561e99211eacdce135bebb869bdf4bb30c05223c1921894770dd23840116688625d9a3629a2fadc8da618ae4574e0f4b59fcf0deef6dc783ff0c272b88557e51957fb9aaf119a77f7d449b772a4e1648f4a9770a9ca06887608ac9f2220ca1381c7a20b7dbf7cd89fa2b6083b3b9fbe6001304dd9e213a93e47316ef0e657567233018468963806618983246e2e05bea38d0a72edae05307af9a8a66c1dba551b84ec097f76257c64fe4f705a1615afa457ec3721e7ede96f00329de5db6800187de171b94c98a99251b7c20a0fc0489aa0bb025fd4b6cd4fd7cb1d462e625898d87c94ef39deb8a862a5c2b53675a42a12f550bae06922bc1a3c17705e98bc32b672294a0e6c903019a2567d6d5c6845cd65562a30ea82441b3376100030c87d081d07224157b6750553f282acfa579411f45af4537c9834d1386632fcf5a7388cfe200d84f4c01090967dd79655de83d6b44b51bd4d5efefa4c02d9e704a7f42c2968842fc5fe41c4865bc0130509dcb0946caa8092c37e428110aaeeebc4d7355b18ee246f29a74d404e3338c21e5e61531733a5b34f732cf92710acc1703d5071bb6b07aa04049f6bb52bbd5dc7041947a8ba85eda27e51b80a690b3619dda6b5b4d8cdc42f6d345401b50871b8faa60ca091f813935a320e5e1909b32bca3d417f4da1759934224edc3f6e370f69e3e8f1e52adc5e048300cfaa27886f704ee38319fcff76a9d27e96f5a6b0d1dc9a65d20d837749e9967e91fc678312a1edffa1b69bfe7cb2601b088b05b0c1a379dcb0294912009505b48cf41b93e0959bc785dfb5ac911a6b3cabe4d671dd580796609c965890dcaacc1eff9e0f96bcf292f92652e224efc62822930ce61ed72c464ed7a39271c98a23b7fdcb37b7cb83080edf1ee2cde15cd3659f15748ce6175fceeac214f809063ed1c47da13223c825ae3b1ff35a2c41fa98820ee88f7b694db3c011a10de15e612f178dfc0b90815ac9407cba7b6e2c277523c17b5b71f6b1990d4d0a4d78b6b65b310109ff1269cd109ffb4306df636301ff47d9d7b761b6ffb714f5873f3d88b3fa820993c000950ab900ff466e0371c367f5d649ca2d52c37f4c2c862e09d5c4cc037c617104fcfce66c85d964ff1f805ed7621c11fe1ae9d0b770f370b6462cc96c90cca7345fa082d55d15bdaeeeab6646cfc0961fca4c959ee7b467e3f46c6233a04d8f30977dee9dd582ead36ffcf2072452d07a78ddf501b080b50e4ff590bf114dc7bcfd5d9f7863755b869bfbc0a251bff182e53c36853b2b25140a4e5940bf5f8dcc1f3c82f48ded3b7f874ff7096645b527313bc7353e984fb52d486f19621412648501e635292defae0e95e82f926a934bafe9c3706574f10ffc549e3269eca2bbb8e893f178734f58517ce4196014fc7b4d62a69e8e40450694d8acfea832caa57cc70732484528f72f9046b8f1a550af705bc716852eafbac09236ee8690b7ffd5a3a92c2c082ec7d02cc3d14d9c1a7c48842f243cd43849a14f0488ddd0d937a752f96efecbd079ad61d7ff7707a6da2428c08b241c3c1b7dd43b254b93822fe922102d78d6cf6dcc11578d593cd0b042406b1aca89744d9a86f8f9bc9463f2197caaac21d4cfb7a8ce2885dcc73372339f1de99fb271c9429d91a547e365d297dec6e0e8c1478cb63b6a78e8d033bc4317dbac524c053c2c5cc2de549c1b32dd596adf49ce1ee0b1808aa977f041e225012c5a2100a6c9d6725f0b476a429537e2f492a16290be449fd7f7476a807eaeb6231f46d58865ade52ae89d5a6222823778df26e3071de324aaf60021c79eb6d4e80088e02d5d61fe310351dbe27498e676264cdcba1773cb83526464dfeb3306a534ad94bd72443467743718388f0ad7ff4d9beba18c5def4c29de96f52c26bdb8d3415825aa0269ced26973d329d1d3c1377e56be71b6549d05f0362a35a8215843c1104809e24d521c9cfe851f3db2eb681979ad45bb0d39f1a6cbe32efa94bf983e04e72cbae9897fb949cb5403f58ad522a0a1bdab4582ba4a53b3950cba1a871a67c171c944edbc9d96d3204b391bd52415df391c0cb366e394deeb225d2ef474d5ed783b69417262277d7eaf952208b0a9e787053143bd82673c560bd2f247a8a72d80587d3256b3f2be6625663ea97e63bafe5bd8fb01409432bb2f6eebf1d14d155656063e167f82ab13904c4bf7c5cf18ecb8c6dd40fc73a02e86b8b679cda5a4f5abc52016c42f82691d699d08ef9a16bc331c66bde142417f684226d800ac15448a1e502d2ab17b30611b98d9dd1f8bd756f05bc9fdce6dee06a19a82fdb8ac651ef8b6baf43cb0b63ea0b77e3676125557d650671c35eefaf638e40e1c538ff44902807944ffed422a6cf5cbb3cacecaddc455527fb63dcb44b75ba21c3f08eb7b752eaaf84edb1a3f8b182348a629d63295af7ba392875c97f1161c743e9350ac3eb06b0427aebffbb68e5325ddecbc4d024f8d497fd71f0316710a40853b0daff38bc28f2c2ed5ccec79b1422a3295c1a67ca1b5cbe8c29235625fc89738a9d00e843dc6f95d773d5e8ddd490b10d65035d2419f5bb0d2e4e3ef7cdc3a8855e0df6814a1b78adfaee95a8481d156147f897a0f60f7754465ca644e932ac3bf9039f32f5a3b3af1534497d2d8ad5a5286c9b7b5af640fb5ff523c9e3328cf762e67152c3bec27535078881e272885d472f4b8f03ee4fdca2b1889c295ba2d5206433e82495d7b32b0fe33dd118466e67491e2f50a711d2c5312265aa86ada1bd6ff71cb658c5847b7c7751294d193e74b7572217e6ddbfb22fe5aad034bde600ec627c6a2d863056e11b7ca014196a8dd3c813ee38002e3f439a69cd5da81f501a12981ad8a6c3d4bcba029e8b6131c0f3b2353e77e0629327400f1d6803a34b3ba67090c0a275e49ff277fe3b617d5e814b7afb8dacec95c1db3fbf06cb4f1b2bab3160dfa78a3be2517bca8d6cc844544db184d6bcbb03c172d49867c47706345197c54b10447766afdf4ca4f2adfda47ab9f1266b52d1025877c409006ce5439a7eeae533cd2e7655d8aa4d986d3330b9bd3b6daf9c09d861cc26528a8337b915989c4ebf042d73655ffdb4578824e2a590c511fa7f928ee05645fa09b0b319ed93bf14c1af21295781a55e1b573ef347740716ea01de1695ba885a82c98b086435c525d88e632b6cced50906bc15235dff45fcf15b915485f110180a126fde7369a7858b172cbc52594b6efc519ae3e7cbb4f823cf2691a1776260574f41679e6336212e91e296cdb954979e86a87ed6872cc07d6b8b12756bdae2a791825ebc45c6363c606dd02c62b69359706bf069a1c998c2e49b5a017dd78d83c52ba442abe01f7ee6b4c384712b8de42adebea26612a45e08c25b5597298e8a0fab5f1d416517d70978ce56abc854d149151e192f4b2a64e0f4f5879b6ab342635daa498fceb77abd03ffae79b0f5b755b94b6946f23e2a658c928668e48e22ee9d2a755639a885bc0f68a02e99b86cc4424760ec3bd0151784eeb6c4806a977f876168fb5c5c0c41b1bf926b54b588c09ed18597e2637b47086861dabf94d96a2e9e2b97f00e58c2861688e2af9e56e7bbb0400305ec7759aa11b792e1776d6c8c15c825e9df53e0e5eb76ed51ccb7f75cc4a2baaf785de7ee8b1ee7ad57609889b9aef6dd73a96b5800f12172570647c8279d4322dc91545aff76c4aecf7028992568e528f3c47cb8d65194b90be7d98974f73b5b4bf9694183308d6626991e8a63509f78353e2471e49f3244464d9510c951a431580e4e67cc347f2057169961598a6bb50decf0a04112f68323a9164103225e9058ad558671e13d4dbfb7ceec647cf1a896fced72f210aebe5d1535021d6070aded7b1d1e334e11b61b4d459c83e618fac5eefff75cf5772fff9745c7abcc5cd3524aff4825706e37a7b80b9d8656bc0b3a802b5c4e77658210a210e3be345e5c013f8916024a5c44b02fdb25e184060570d76e4e24872018a011c195633b61f3f5ce5c47c98a9f83e70593f5129adf00cb77667d6c4ad557f9165e261694b8ca001e4f045df946212006ea2e833cca115b4055db23f7c1ed1663f3a90b06575cedd0eaa75faf8f4353b057e2c209f86e802a42ca38acd01ac4a561df28034aba5e3775aea0040fd24b8fac23b9d64fe619d5e4a70f29fed4d9dc33ec5c62540e92dc95bc0b5265aa5c7cad586684b1d4274700418a5b648bc51e79a13664368b69fb1d9ae9ae69aeac6b3887910c634bc9f745a8ea5b4076a7ab78ee428be18da9f9bb2e6d149edc5a4da85d3e8d9d8c75685c0d18e0f4f91d8ae95c905edc827d68949800d4beac9eeaec79c9fef61ccba651552b072faa466d476d8731d606c5c9782aa4569bc4a015ca0d25d78a20d8dbd597b93f71dafd5248baca8996054aba498c5b22ff8d7b85a0f67ea70568c0502657d343eb7e08535067a94e4fdc197dc65ab9279fae45234e32f82d8f5ea90fd254a5a30a841ae8214291a5157a6509d672571390a9e08a1ec3f2e320b519c4f5def9bf5b6d1bbe40c90c1085e2bd2dd2ff03fcfa2afaf0a895e70eb39ff0782d2de8e1962d50037e0dc1688d5b1d479cf00ef5915209469dbe2f641f51c302c2ed9c13e5b4dae70b504abdd719e27c2d133e546af07c3677bc5672fa4dbdc2078c59995618bea9a2a91b8a33d2df954b68f9249bbd96f685138c8f97359148ca3b80564f4025edb259b0f7397fd561829348f03e2843cd368c358d8700008deb40ebe3dd4f63b1daaaf63080778fd9204ea7ae645ee794b14eef7f5f881dd99618ffb7f187cb21d3bf6de1bff415ebb892732eba0db582ba4417251982250915c0f3ef96d3a533ee6bd93f55ab2a0097b5353c0f58a5efedce761012840bc5f4b2b007c076646bb4017534205388263be0e521ef65695c2a0859e1651de11505e676b449785e433e4deb820e86c6e76f899be7cd0d830a3ce88ad96c95ed0919f706decc5ed2fcdbedc6024885a13a616b09dcba3bb3b70192713ccc8b43a975acc5f7c3585ebdbee171331d885ff3eeb161df404bbacda371fb9787675247fa90425b0d76da58ccb788b26e29eaaceac7ab4528cfa164ec53c7b579803d297adfc332663f3f198a7da571fe2c9d060e16d038530cfb82892c5e97006b789089895879391a2d8f2759ebf0a92cf3b25b1201235e522eb8ad75657e2a9558bf2b8be948831dc7dffc76b28cb60ee9a16239eb284ae53ca376575afe94b1863c1f488048106552af23e85a690c2425af08342100e67af4b1111950908a79ff7faa848b63d2a4ac12016232b47a4466887cabf6dc92e4eef708c2db23bb8706191ca330473cb41337c6bdc9eae9c2cbde6fb7757be7207c920f80cf438fbd2a347a6597bba1418def2e589a8c1d80ef3ef8f34433166edc24c7f334d7682a21113fabf1142dba8c2b1f8c82f44dd326a1f5602128d8b21b9f4eb57e2215ec6fa5c98ad098dcf99aaeddb9f955f3f627ef28db8b8690d62eda689bc25714a22852cb6e2893fafd738726b33838b7b6e7c0ee7777b25f1826f563ab4c98ec883ae18f4917d3e06031b2b2a375d1025d79eb048aa6ead2c0c093030437e1a6eb07fbe904845990dbc3f62c521fd8ef8a856021a2d3262689a9ede98961fa04d126defe3e78369a0a9dac28f8df0566f89451ee6e40c1c56bc239f418bbd474c2edfddd680a67032c6f919c12ab7a6438233e3dce7097af74e97b7ae0df339759899686aca136d5a801809c6f775f5ed41fc1c8211c5f01594254d40a817827c4f8cade34c503f2d23c98fc5180d433c8832b467629890b1267aa5f62a04b771b96e66386f463703bd4591311ab27d64d5910fd3ce4500380ff9816908f0592057c6755b4a13aaab4c1b8928de97d88c0fa4eee52809b04199a60249729b870c7aa386943ffa11eade1f674e65ab6a70cedd03bc39a232cd20afb34304b173d10115ff769fbffb8dd02711c094e12a50e8fe038dfc9d31d0ba5744d335b48db4bd556d145be33dc63603adfa7dbac31d7cca58b310af1995de745a200c529e413c3c8c64023fcf4e62ef7b9ad7698bc430f9d791a12e5b079ddd1b2abc2bfe4b0a0f160792fcf9f6306cfefd578828750e5af27b96eed3deea4c67ab014aae7755d9a80255ac7cf213d61d3c7bd0a9ea3bed8080d5105551e7db40636e1004ed8603b81e149911a31bc740c2727817e78f8fba40400763bd37ef702b364f78c90d57844b85ce8a2a8ea21deacef402ae06289c9f56b1809d391f77f3c9a17a9c6615b1fda3d76a82b717d620eead672fb4140ec5ea6ad51ecf3988f1fa9b488b404528755245c4e9f5e430b3bf2ed5ee3eccd79f1d480905d3250e324da970c0255adcbb462dbcd7812a779b4befa7b549b556ce62c9f86140abbbd9a1e23fcfbd9d6c935155253f507da7b1ec0a3a3bb27c677c97e0c6babef97e4f5c4d3329a32e2cfef4b5772cd5c174a16ee6f0cbcec8d58205c0916d3da6de8d633b2e6ef8326fc92a44e19ee9217f1fc6e85c4040c8eb8b4b86c48e9a6427338d4f28deadbcac91352b805d7a23b953070448e3f5e1f6fc64857c40574ff132141121d395f84458b1e72fa537a7f4799c631bdac4f9d62e47f08da47693c8fc6eb3b7503379014fb0fbe73403a00c540c0fe4eaa9c7486dc021c5474a94c98da39804d3aa76b1281506c3dbf3da92fcc56b7cd21eeddeaa6f8371f3dce2736242e420d95533a6344e7c07a47eb217fda4f5d40661fa3be0abd7cc0db190c237d83fc13fe72543f2169344ba52d237609e55bcae28ae84212a7149e90e43f47ab68ab0339ac55bb1e7ba05dd6078ab75a7e3c6853ed087dcae9a2bebed58ef768a2b5db63c529a60b1ac452bfec1262418099925727d568f47a8e29ce0d642110c9b46c9ba174f6a61ca8298d14f302997f88fcadb71c4b90a66bab02d8855e794be2883537e0c47d2be6208223dd798e6a72cafecb591d423862a2a5d62c5e25d1a58a83c4d2ec973deac8802c33ed19ba96856ffad79cd3cd3f09ca81b659c3bbe40099280821ae7ccb0d506cf83a2cfbcfb371ca23ff4a9c8498175be2f035f1d157b61f045c2b9887433aba25c57aa03d0acca4b55f2a6f6e2dc79e9169b5594edadd692168ee586d4e9bb39efdab301eac94c3ce5c884a3ee40be232040033ed1668b0844e58ee690a43d1950662caed026e06a5e4b84418e9bda96bd738eed2abe3715c15fcf148f64b4551821221dd1cca3c4625cbf1eb73307617a45e66cce953842adc4e0edba5c1adcfc37f94351dcfc0f1257631f7650da234318417932b0678b6f35bca708312bb3deada7695f039299ddf24b9dea5fdde291972e7448f25922c4e118bcf61a9574a44e881b7f779cf18d686bf1a4db4e3fac2f09509baae6b39217d8252d3fa6316a3829d0998719b0efad1fb89c9c73a43b43a32ecaffd3a120dd10f6e61ba1c1cb4770e7b9353dabd1f0aaa102df1a596cbc3305879355c3369b6dd8086b5cadb06543b548e024a3d9b8f21d76c62e22be457ba02bafaa3a23af9092e52af8af45894d4a73db1f72c2891ed5a02dbd55815f3c013699401c65e76695ebabcffcf47135cfc228d858aa1843b8d429bab4579f687ef73c2997f0231da5f209f8e5611fbc8fd88afef7d0c3710a6179655feb82b2bb64d38ca8ee1c96710a8ccb3cb5dc835244e4b84bde766f923045428237462b21ec12674d97cfee2dc3adbf254659edd32127b9a38e83212dfdaf3e07b910fffd2744f23971d8c0f16001f8d25a709fbad0d3783dad1739f0c3e89e15a6899af43decc35adb701be0ecb146f432b19eca326aeb586f7bd6e4b261f7aef2e0a1924c2f36b611bbcaf98a3bc9042a9ddeb7e15d9801ae61420a3a0f5c8eecaf8047c5a4afba6a5276221c85889657b93dd677b722eb8b1b66df20a7b28833503ba3217a2f6ed6f7dbd685e46831401b352cc301a58a7ee1a14950f83ec9122aecd5994bb0abd3b6cb8036bc9703b4760089b2eb5f54bcf1db5562d6a96a4d855a5d09f8518184906719ea8f2c7bb71a02a7039c0bf008af519dc02af1530648326d7b0cf1c1f81adbe4527c89522113abcb6364bc64ac32d5cfaa8091055f290c3e4f2b90cb882cafb65a50c450ae6559db3b0b0ec851f7e895e7e90a0daebddfb663136b5101309e6a234458209b630e10b28193f625b9471d3b7789c97bacdfd0b1927705758cc1b69e2695bfb9f75e6cfe3a57bebb2b6c54abb7d583bcf4228c6de12397392dba7adc0f46510498888767ba37e3b3316c5cd083e468e50bd55c6df872012b14115338ca18c33455888e1936891b5e265f1dc3d48f6ac2930ceb42810162eb5f7783e0b293f5ba04904c52a3bcd4e3aa4a8359a49473791feecdad5c69d17365948e379b082c0e4d047fb6559c696eec82be2fd1b7bf9b3b4fb1fcb173f86f2bda7282db5c48d4c9ce11f0b806e72e5a2b97ab9bce6a9895c75f5fbe05211f9fc473e0e72e230951eeb24f64c9b9cd02cf460699f5197cd84c0204979349ccfccb2e0b8421daff93f849e7f498f6246ff8d615559ce21faa51294af6c06c7ca46235a2164f59d1e2db308a07e8a5bbd8f40fd8e92f3e39ef44a875d6b344b17506ece8656a87143875f90dd32ca9375e4406367e4eb4e68bf7109717afb417b1fc91861861521b4926562463314b1545d0eb96a4ff6f71eeb0b5b2684e3794efc6ec95260bfb41a48283bea5f7cbc4344df67174e02cd5211c6e0ade908baa56964f06a3483c1998bbc69512300ae52bbcd517323a68e44530a0136beadfb7611003e36a1cf8915f83e842a7910d981f2d2229d87ca2265528508930f0e0ffbb74ce1c6cdc418e35a10e20f0e79205ca66b8c2467656adcf6e4e86fc56fad015365796639b7eaebc06561a2f137fbcb9128b2dae0c5d996aceb7e6f8491365f2efd7dd5ca7fc18aebe786148c00e0e6f602b38850b0324b4fea0a2b47bae4e9db3c1c8944a149c927f8d45ab866b660d2be3dc7ce2c7d2ee41017d4400e667e8ba2c16b38684164270c5cc7c447cc75fc5a0b2052d16f36ee9a88749435dca48987e1d86b2bc06e66a7d28cb60e60cf8d35ec91cd1f2311416a0b71193036d7864f82a7d5a9275660d0e608c88fadce739cf9414df2a6261c7593181493c4b4703a6614edc9b48fdecf1d5784518830c9407b5f9dbc2b82d6aa97ed0632ce4a397d95af7d3bbefc2bc0242a435a0fa2c76c846ac72d529a7ba005546f2c9a43ff39776b8ace39f817f7ff42ed73f282f1d6ed2f86f6d74c43286cadc35086fcff2d5390c7616b56ef1576057a9885d38276a638c528985434b1c0c57aa42fb11a128992ceeb01b278afe97ff19ca4d9576b63e33ba707646820da673fba8a1671c3d4b6e2a0632b221f6d7be0403141adeed29cd0fcb8b4ddebcd2faf430a6a2115ddb185d58d858ae06b10223a07a49562c62af5a50e1c62c3afb994e1c6f671619af64b82677827e406cced0424293f4bb008ebd6660dd12ec7ba40a70ce10aa8c439183faae6fd71af661f9015450e68630029b9987d750dcb2d88658b833266cfaeca835b3b0834473073268044356b835183448f5354751bad326659b29f0c9467ce0e74933dccaeb05165a396719957b0d92d6852c493e8f567f99759323ff6f4c67c4d803edf1ec8b664ee585c7a5fef3320f63215dc5d607537d11f371972ddf7e0e566cd672a6723fee4e97fc53e97651929e95d8c83fde9339b09d1c9614be03f036c9d61838e4a72eea490721c89f06d7429e026ec513b3fc1386136d46d04f521355850f046d894ed90887b69e768ca4fa6c5ad0c86e5192f7271d5c0ba5b9e58b91483848edebed8f018966d92685b213f771ff521ba8d33c02fc85ef2809c664b5750718e509d79709ee0d03b8caa0801ae2125d02b5801be0697aef9b6a038f3e6c0afe4b302a2e85475181654a2a48a6d084887dabe083d9a5c231a3392d04bf8d6e4a1596623822778b82c86c39af6930ff7802becd5f0a7cd0fdc8c824fbf60410d8975de7394d5623892b35acf1e48a12353fd0df67c7f071076cfb292ad3682899ef91bd19c1c9f809e253d84c52f4bd48dec105969f4d59e652666c248dcab54c33e4b3ef4ba38580ddbfc2466ce7d2178222b2e7d70c7efe7f480ed156b5a2003b915dafd04fd77073a8e4cd7f67851c91a4b0df03d1fb2dcee9962f6cd77698ef509d94cf136618ee15ee5c378cad0475305c83909e4d9d9ff0e9313e3e4c999209333cf33a6ab83a157b17af15d38dcbc11787c2fded8b4ac09b4e2ec60a9564155c462280d146cf982d29dadd1ad0b7a38beff74d1d42d4b6c9f9634a46d3173d2fef2e50cd3a7490dba12bcb3c29aa24a278af59722909ea13da4295a27134f82a35a3ddf62d3011320e4ee41a5020210d873484084acc089933fbfc62577e0a5bef87a355ba322c1c8d081a2b90c691a66d0b80d0ce29a19655a1650422263f6830d7338f6349334dc53b8765c5054045cf3328f52bb6f631182f129c33afcaa2e507548c40d8f3c105dd746b97e5cc680eee1d77d2741fc9d0df8cd5c16abf1bc97900948110e21d0e57c3e4c7069cad6f5ba3155dba07daedf79ce692cbca4857e91f1cea5f0f0b65a876659b9f3a5cf6e3279c0a0b04e01771c004482799f14a0f2ef937be95be71ee21b7ed4c30b76152df75b141e9647b4a4a92ceb2a70342d03777b1e261a046005b8c1347442b06bcf6ae4cf556e5d79a2cbde6720120b27e70de8ef9866ac83599a5940b691fcbd862371292c6fcc615107cfc97caf46cba3972efa139ef1923c788dc01277c5c711213bfe1a6a97686210436b515cc87166070364eb889f8faf201465be9b8576503289e23eada24f3429cb032dc6c07176c7a3a0b936de5a89789a19bbdfe85dc680630d932fcbadb3e754052aa407403755b6abb92f611ae15dc4952c851cca54870f122ce3dc2cf5939157ce31feaf770e9b303273d1299505c87a365112d8494427ff9348c46f1649d9e0f5e8b6e175313c9aac816b2fe84ce275692375c17da9d90a46cc5bb692c73796c4474d79024239cfe6579b924e2f059604d526ba81e3966a0791a7c12724b8778b592cac2f3276ff7d7900a1020b7c8953b33ac1e8ba545f12fb93e1efe66f8c01785ee944f6a8f759cec062c058107be4ae190f5b3cfec61d419b3ee88579b10e0594e9d160f89cdd408abaf72146c3ed1de4dec60696cc2982730505d60736a110a18a3fbdfe806d95c03481094434d1430a39a79d6d428ac83bb822876dd0d11bbb1b579a400b714a66664f76d3dbcf123df327dcfaf7f749e12d19394754c9c08b601a7b59f9513d061eed8884a94fbb1b2a14b53db950010ef97a7217b3ef5eed0d87914b0b968ebce8db15637958d835e49712834dcd8df67cbecb74ef3e7b51aeb95c04b2805d2654a62311b91d5fc466b65991a05642cc3b2c267ae77e484e934f314a40c1e8c8455ff0b09593f4f528d2cada1fa6b5eb26c96c9e6e991ed1d8d302f0a1a1397305605c99b89929cef9c79a2dd37b285925965bf7087c605e02f6bd0fa800988acf554ba185b912ecaade766b5f6e7f749c92be45452066f8884746adeae8b3f1d7b81de97d7be7f6b31602b4ec4e0af20dd3f1c525e952547ae0c62985214b61c3dd6d0d489357da9ca7519789df2fd226e541ba1002405a746e74e30c56278460bd47d1e1ca65788f3d34d26f8c4d52ceaf9cb742dd274189c6ee71231793244a7160afc9a45572b1c9fb2e4cbdcae821d7083300baa1ce25b4111136e7e3c5253314bae00efdd1d4627a18762682374b43734823820aec344a1649834907438cbf2d10fe9bbea36b3be79c9d9ff043c62beef2da785817f7034448e9546479d44d23e9de3296506a54f394e954485b30202a5c47fd71c013c00f15c7785654ee422e962022819a0fb679aa6d5fe8ac846945d00f6cb8d16a344134971b86b350b59843b24cbfc4e60dc8a5936c6413c5fe9fc29f88ead55dd44d2fc41329168d8fe54cb75b7926589dc601b44882ecab0fc8bec71b83724d404f57e496bc69f1b21d709df5a72b1150cca57ef0de8e09940f4ced092c026cc4b8154af0c95d812c19213604018e346d38ba0f8abe08e048eb998f475d7d6167533d03857ead56e6feb867611bbe4f826ba1c9b170559f3d4b3766ca0a8fd701c8451c8a204ca74c8f17eb6a817d3ac6c5aa5e2d67f385ff53302f69403245d99f29351b336300057c076e538ccb621a2f36772ab06e5eca04fd0205814fb86a4587e5766a10332ed199ca4558e42e6b8ad5d9d7807c612da4504921f80305e9e526a05e9d1eae9e312874108e4d8c288e45eae098bd4e234af88042ee95989b66ea8282fc76027993b1ff5b817994e81e3318dc1cb765f46736948573fa5c489b606447dbe17f9fc6cf1c0beeb4df8f6c5787f701c059691a16357390ca2572f33c474484f3867720bee249bbc9268316e8843ef8339b8dd23e179ecba057a986ab5c886bd58e798da843bd56672ee717b8d1a80e19db96d97db851a95c849d7e3af8cc2a685e8f95fcaa75a8fbbbb4ba70862be4f03e2b885a2efb9974400d10b380593b2f1aa6e7667d084368126510fc74f0375f459e182a1df1c486ef55cb85145180a3a48985a5c5a6b487fd8c9191ad1b98d47e446c99b78d1f6faf1b62e39147c7b9b9ba9ed2debbee9fb30886f7f8ed057e8817cedc3f1489ba1f4376895cf8ccaec04c5e71b93e1d97ef67271270cc40a4be032f2b112284d7a1f6ee45adb98e42b32bd66d3a027f7b49e248ed137345882ae8fce5f2d986ab9247fb9a4109232fce23dddaa08c9dd3eef40db7c141cb542ae11349ce0d3cf5c807fd3e1b195398cf6f9d2f863bb474a2710d9c326bdc1dd027dd6d1306b86483b9650bb295c744318a9bd8573f47962d7808ad5d95f133dcb7fd823a95b0b0598afaae76b15e8a9a9817dc6b5922f5f71a42cc3898d479741fa572cf7da530760b9b5712d6aca6a9241d395b007b145e892e94b28894f46b0d05bf45e5ea50669cd10c637a9a0f32a8a2553d7117945df4544be6a0a6286473d646fdff04fee3951ab0a21d29aeeda6e8b5682fac3e2dc41e0f1a33a07d23001ccba266e9f09c566a7ab5f53fc1080959dd66ff6fdd04d7cb29f90727c4a8cd0fd5c8c888c0f831b97dba8edbc080c03e6cbc67af7eaa16b00b34c4e1d14dc9744c5c2dc8ca9693f9626be3400d76caaf53d144165c693973875a2ef929ec94746d547fb66a65878f58ace9eb35b5282ba6080d3e48c7c2ffecf395922afb01892910b4fb635492fcd9587c789e3a45c917cbc8821aa82d20546fda5fd4c2cc0a25b0016fbf8ef1627effef13a8c53367b7580c7fa65a2a3fecd28b3ee452359a03256efcec8ca90f9474a3ff5ff2d2ed06656a14c25e744dfcccdaadd2314ed882673c8f04f0a4f24c49006caa970f83134cb5e5b3dba26a9457f66d263e5febb6bf70ac4f6c10f25bfd7d4d0310513129ba26b47d39c323a23f4c7bede724f80dd9a3c6017bb189df34bf4d14372ed016c87038aed4d513bbe8bd9761b211243966ff9e667fbe19f7c43576051b1c8be5c2cc748f7a11e2acab285432f240645120be95dc318b7b357c18f7654bd7676003da9db2e05b9ca3f61720ff8cb09968e3a1c61e71d5b09c0fe7007089e88a4fe0d0a0d3057c3da97c4526e10866d601e5399f4dc21f4b79cd9139b5edbe96289f31573e20f092c4a9155d5e7c99193edb47cd1ae607f3387f4790d26ea4b77d46d5c7373580dd1dc57888e389727d3afea26905a97155738e9c2f69ea5a0961cd429ddbf1d315e770186a7cbf32c2eaaf637cbb8a8715c6f073d44f56e0f62d082bbb7e251ce9760a1625c7b10b8540bd35b9c70f3d6c0babb7054988fea706b1abd12650102629ef4945ff20bbd8798e472df09370f52343406ebe4169989ccfa126dee963630fd82b959e8ef9dc61fce609e1542224c7f31b3c19c14666d31737bbfffaf4a4b477ee7d9bff1d547eb045a00e888443559b77be35f038124fb9dd4ef2cad4e0af97d16b2b596e2e6b9d2c20cfbc09ac0c6e23d2fca3d6f3d7764f0ee46ff838d362d7cc0839cab746b4ba6a1c10996bf48a6e504da9b7307535a684f4940cddb89783d5a62017ba1a0a8def29845e758e88544c14253ac64bfc1cfd8763d718e3c8ee35955addd95c95a9c79b0364cd8bc6daae60d56c3bd61f2b937a0547e20143c4776b53ce154a0c31d32cecc251c9d6cf0ba7fba51f7c85c0fb59e5817261e275f8eeb0b94d13039488ad28d110f58350f4802ce3edb752577764df7fadd602e97d9b88575f146c4df93ea807d02bf6cfa17f6c8458d676d3b6ea54dcb21333ea1ce63862f6ccb833750d27d7d6a2e0d1bdf9d7794e553c85cf38abc2297fadead1fd490d216fcf5cb89c5ca0240646e2dd0935a505883432c584f27414534faf3be491eeb59b19e7d92a2bf32247e6de60d7c692961e193931548f6466cbdab6976d83ea1619a8bb4c57d52355a9848b4357c1ce8c7ebbc3ea87d9b19701cdcde326775041437a5f0a914b3cace313049c9c8ee0bbb501a8fbe2b7d9524afc6b5ab65b311373a455e75bc9a8906a365c8f2c67dd1e8d62a3602380c604faf7ef4405036c0a857427a3592a02e1415f41e68c2dee2b5e145a4c57208d38ac21a008dac7f80df38f2dec47dca28888f743b64122674871edccd6032d4711571108bd70926c80375ef79a9ae0f63f14ad5330f642bbf6e5de9a9dc9ba1d1b785c47709aeb0a704ec95973cf65847b777333106612a070d1d001967d182dc10756b82ea1365f947bbe73bfb8cb960f083bb404d2291e9908e20c223a8e8b6a93e9a70b6635036d76b2036c8b14f2900a825959a4226af201ddd83814921bfc85d04bc53e2dfbdceec67f75f4d82314aa679ba8c3658fdbd54d14cd63e795ec729bb11e5f9004aae5d345677cc2f3d8a511825faf438787512bf1af164fe20b4748184948af7420f31015b53a0ef6d529b9845e28772aa99da07a26ac76f2aa645d803153d0691e83365d9247652dcaa774b44c8ba6c6fa925ac6d7dc38801f9b3ce660a09515f4e97ebe935be73a76ae87236615e44b03f1ea9525a6ca2dedc83491e5895436e86438e54b47da4e1621d92b5a487f8264909de87c8b4161370079f47b201c06b394e370ca37f2d9b0a290a6e70af1f6058d5339d806b545889df022137ae32c7af1f60cdac2fad3584e85d94ee1ea0401f33e40c232368b931eeba8af0e78f8012e333892e178bd8e285a37da7b339fb7d9a9a28c5ff09a0a61b4cd4a9eae16cbf140c8eeb3d3a5fc5c559df17479438673091f4e558ca50c4f4b79a352cc2bbd89c81d98416f96a8db27fbdd450e59fdec7f24f0e5282ba3a2b5e90bbf2fc1fdf476ac91bf95961d38e2892329b31d5a78080a48ff4d443c48e9ae13580d2b0617e30ce12a46c36b4c1f0fc584f4e2314bcf1c0368c2c7e916c0679738a740112b029a6a8075d20c8be061f0c8f03f788d234a08c06364b7219b2b64a3ec0098d137bfd3a5e3f029009501b768faa26b40d4644a2e4c7ff1e5236eb90182e2c8b107439b66839085a485f4126fe35a3981a5964c7ef0c5e1878c6260e6054195896aafa99ad682448217026095c1569260fff59709a8ebe4700719ec0a1e6717c8ae8f0fda10bbfe7ea000b9d4143601e7695e9664593093b8cd7f02893f7b5190c3fe9878353f9ead6dbdcd0a89f84ceac89b1c5cb503d5cf808cf6408ab9f7edc3324ed199141dbf073d062b19b9b23ce56af664645622b67d5404388f026d900ebf9f78391119400feac715616a0a7c2dbe826bea091ab8f934536f025da4547fa26c28e306f7678e2a59ebbcbccdc460775dae5728af2c00d53b59292ef0d7cdd93132a413e5f5884bd92486a570b2423ea4c3d2a82aa2bfca8d7f9438b3a20808f9ef3749c3aa9877be66931d1728cf943cb8a226e0c237dcf2e929a50d4747b8f175173ecda22f73d1e2cab812f6dd47e10a864080b40f6308293c3f848e3351801e7df122301e27a8d65784721b2453751912392538012f5b4b0f71255f72b030f5a19a867766d2a97385a757a963f5cedeadda1481a3bb6acb097842aa1d799aab28fa1cea00c1a4b079c60d52386044915fa07364b4ac2fbc8ce330207f7a6b36f4c9a5df7f75ab552575ee78391bcdc37bd923f41b3d287c448fac4229b0fd3687ae7ed371bc0c21ef214ee4cd0a11a10b0fac793429a16fd401d77a7cdeb5b34d15a7a3e0206e88465f2fff0321de15827d85fef98696d035669a619c8685cd1a12d47e727ffeb332c4f4e0b5c5238da57c412d9852564d5f2e65289b68a78c13dbbb13ccfdc15022a086ebea2546c90caa716b5e084600148ec5455590e63f133c54fa5c48f35c1e792943760cced29bb8f9dfa5b62a16e6da040e433a1fc53c315e215b8195190ac3a1c7f8de43b505f03b628968b7b1638bc7af168b5e2e90bcf85954a42edccfcf0b0a2a6a5831dbdb2a3b0a0deecf52af15127503a24ed949eefe83d9cd9ab2ee0e4af9a404cf1bc09b4264d8405a070b5e0ac8db1881359dad7350d2c489df26ee5d3814d368e2c2e50c3891af7bfe95c6f46c8684acf081e0c24551c302fee1e612812435d5cb7885e3c8c5431ddcbfc4a2446c277b8664ff791ba84638bc319937866ecd6137dfab344107628ec07be72336942380427facbf366fbaba8095098b51d52effe959ca4c5cdf159317a97897ec2d4d8fd58389439ec768f06f9b815ff7e600110545a0dfb586f78ef90ac6453c21bea4529f5c5cc89442c381b06466fc1d37f7627ddad6f1b64580a34d87f24ae890057d2db4a33616a026bde626094718523a2fe3d6e221c08af6b5574430f4212f73bf01c4c1068fa17b4d1090fed10a3df0a6ee33f0f8a5bc7331f2ce9bff7014999f676874c260377a4d1088aab6157b1640a542ea6865199260dd0d230e9be12cd4ac19e66fecc5493f13199061b615e57dd73c3e5625bc72d68b5f1056a4c449943091ccd9d033f69f0c4ac3e55ee34b74c7972ac2b8113ea30dff800baafe97e7edc38a2490f1da2cbd8d891fba27bb28ce3a1955f7dc7d4d7c7b2fa74b9f7c6cd689753a91cc89a22ddc1cba8852965b73af763e3a89499a4634e44d4ce7dda9362b9738f769643a6d1bc92b099e94a104a969ccb6663a6c6ba9dd9008e80acb6f543a776ec18b093d145ccac68a8f5f59004d3659c58ff550a6a9981a4e566014c986bcb5002f9a01803fc1f0530fcd6c0f68d5f390810f07dc8d74a2d106518b07bf54e31a5de4601fe506a95295b161561f9f82a09f9073ea9b53aac257b42248b52809002b9743d152892cc72ce221c34db079fdd8891b996652e7f4037cad9f671ca8fb73e957f0cc4e659d6a31360e6a9e417cdf24fd99b08e96555b99cf5733837526363744338263119a5bcecb2aad395202c03c8ab3fa347dc263ec77642c5af74eb5e253234d957498363c7be301a1dec7de514d58f72042ac6d5b57fc46039a30563d7cf071df2582aed7028e2acf9698276e5a2283e7aa38da192d78929027d06e11b1ee539a7edc33548a076913b654312154326d1f89d6d0178c5803989f5050e6896dabbd683206696d84b28699b8c3cb8af58f6c70fac87af82d5a545eee370c1ac4b3fbb7023bf2e84670788934f1b243a166bf8415f5ffd193f10f5a1d5ff8c541016c9a83d51643096f1adb6c4311b4e900fc84c97a34685b51d694ea7dce98eb2c17ee96dd80178eaf36896609c2aff40ba3bc5d108117f3fa5402398b23c4adbb8896d02ecd94c0e773e8e1e2014b5aefd63d591eb80f64d010439b77a430092137d5dace628de6947436009a13c0ed5e1e32c5ccc4de5606b2f1d7a0a4243bf3e23dd96a467189cdaf78d1a5ccf4252ac3c313ac51e92381193e1f19b815f1cc00e643b11d4378685e6c44c001701aae1d60fdfd25614fceddd53b77fab4750b65f798ff76e0ec253064da5bfd0e028168d47acc48a1d112ac8329d0df3fe1ecf9505f574720be78709e9b4d47415101fa15b75f126001ffe7cf440c223a660dbdc8d20b9154c147bbaefa60199534d8e802566c21353ba18c9441ed96217cae558cb3f2f818c61310d56980522f32e5b37baf11592e24c091bb92a4f4c947e8125bce5ec754a5702469ee7ea507418624b313041f972b736e2d77f279413ad85084b5e06b8e2a5f78d5faaae8eafceb317d83d2c784486a041481cf0c3a85c50310a4b40f744ede708a8ae2d4a6e180b2d1825bb24cc4915b17047ac0dbd3f40695295933a3252a3a31fbb917b09ad40f55d8a713861cf266857c8f148a902b761b92c8fab4b640e96d2906f1f7d994b3f8adb537bebd9812cf1e6b70a47c448f7f40ebf82be8f510a12f01f1481aa792449b776ba98e72f71cc2c84b68ec0cac96862161b87d40072b65b61f6ebd7c756eb9bf1a95acd758d0f01d9622945d624f316fca05383b7a3141c6a62b374438a7566d12f958e2e619cf8ebfc9276f8affa872e0852d9792ea2d66805f8eb346be1e9fdf28e1ce2d881d70254ddbeb48a82ebd4d9cbb56d42993c8146a433d23a728b2ed085d8a73aedbc289d00d5a6150a63845ca5e2b140b10b206e556bc1cf02172dab6413096b25aa92d5fc03dc14e5d5e82e3c2de6599423452bec4236d12bf91917d9085de39686a768b317c532a5fce1e7e7526d5e00edc4ce8982a7d1249ec3b1d5a832918689b5f0f15b7467cdcdf2d61fd250bdd3194eea7772c708e36265cf61bd9fb0167c7fb4dcea3ac7edff616d2ba1451db9faba8e5fe673a524f6612a44f65d2f71826d577d1f997d77aa633d6ff6558cf94c5a225665e6dcea8a340c6cac25b99529e7bfde212a6d8152155a464659bc362b8f1890f6da66490668f74279849e5cf37dd40e73b4572393e25b89bf6487248ad534713403475400c7dbba0cd3c1ef67fd001874eb92f8a123c1b5426dd7df63cec292f2d9a76981617fb1e222d3aa63efc9e987d2038303f7ae263667abb27d38e7111f55a791e8bf7c26ecfb16566f8174759fc8264801e8abe286b4a167240f94f29fc414925a460c3aa2c17c9cb8ecd9ff800c1db0dd3a7403377b1ad773ef31d1633e233757873f81d94326caa66162a8b3715d8fd3af08037e43433b099e9376035bad4b1c984ab25a8863c54aa47c3d13ef052c3335ec1830b32c94add2c21d8506e430ec5c09acdb92d4dc7473778d1ab74769f80ee6f8a4a9c3d2c7fd10f22f8ae5bce91b0cfedd916f5b014df825cc91871d9f60fc300e8b14883d51e2fee0c49a94bfa4282d3526266704b146cec63a6d0e656567acf8418525b945fe59a1716772e11774b1b3b9d25980ad63d2527b060f105e1219f4a75e3da25d7191c5c6a0d6329722f703d3028f6da95863a4d9c55b7dab0f0dc80681804507c48eab1202148126f0cd49d27ae276880422cf7a0e250e9ffbb0f1c1b7989d324803d9ccd180364f6a868c93f9ec990f9350ab8afcabb580d390a777322751656a13660d39e73c69cb5f2bdbf7062cea37099a19a67cf7191759961074d3651b880fd00790bc925c7ac1a0a3ff155a3a5938f7c0143dc161d91536add312903acdbe95a72f4c1745649d6b9bd00c4631977b1fb2d277e639347dae1361aeb712859bdc9910376010ee23c56787d0004dc28dbe1d4eb6fab691e30d29e81e0265caad02f2d44ce459af7dfb8283c87417a87bbeaff803b17a931b282577ebec0864e0f62acee2fc9f630d36b84b8c21cba56ca8809598127dec5bd7fa1d951871e181796712dc0a8e952e76f38d3980b7d856d84882e45bc3ec066a425f7dd4fbb4e300065aaa0dffc0cb433b6b5c3a73d0e6ce5d982840f36af6343d57935dc538ccf021d44c80f353fc5f5e7e0675324a1623265b39080c0cf791bfb7f9ccf145877f3f2d40941f621223811a35e28936b9d50b190262f0b21f7fe3033846d50da8a752178cc56f1190e19aa91605646f9f9f07b18789538ee60b8f8a34bc5f92927ebd5514556139491b34350bd1752bbb673fbcbffea36d909f7411cac3de57ecd19d420bc39f4d8173740bcf8f637bc33845872365321f900a470b8cdf0c36edbc2300a6be187accaad6528a67e7987c21a35e7a3818a2089bb1879714fbdf62eed17af72f0d963808e3440de40d70653cb1e428f664770140a146fbde8c1434e65320d4046e957f70359db096d069a7be9ffa5ace70a665e21e82762ce4bb69408b0a9d33d73292f8bb4a17d3f7df970e0419dbb7a1cd0ad4512da0fe3dba11c2f50a83b4d273ffcf90208521f7fd451709ee31dc72314a19c6cc089f03208318d00d179ded73e4511617267a912f0628ab0403335582188302602e48c77a039d7af2a0358f02e0d8f5d651ba7a93816eccaef52661510c57f82a454c27f0dbc7f64f231ce4c7b72a34224ec46b3dc18f9059542c4a24d83deb483ce233a26d45be690fcdae5de646577d62796b9e0a7f3245e4544d3a39de56f925c4170b0fcf42b84fff95960bab5c569ef4ae51dfa2e0d97c5c2e120ec6d10eb6c41c1de7b4bd3e415a6c4ff4b43bc45afb80f6f3f10b736fe0d46392c141ea730f3fb0db8d2e28fc90ffa32d231630ec1157b0e4e5915e2b2ef3a0d14cc6686fa4678cd5837121fe14c6bee04eedc2d5167e7893a13c5da067a084c94d5b59e386e4010453bb9e2fe177ca9074f27cdba735373e94995f5e4c73a1e2244b37a330b2e2c574dec3853b2a3eae8d689bb3e322ed2ad790d6497d7c980d35892a8be44c2d6b679d1342c4f550f0897635d82adfa9f179ac952576279cfe133278fdfbf58b2c0926a3f37b340c695f74c4998b556f5c5c95ea7cf5e9aef66003bf31e8caa29f1c1af8c5ff92ac27cb521c9472c260513feca17673ff5e5826263bcc0eb522338e25d7932ca51437866065e73fb184f6ebcb4a60dcb0d1b3ba7dc75b59e9118552e87762bcc854293ada2aff865ca79039e1c22731af4e69a2e1e8862d82ae038da2812477e8dd973a07c9383e7d86f400b37bc487cbe9655c3e14a178f610dcd8bb772f3d5d872f9e5eb14e4191407060d3572b4315f8a387aa8cdc4829a8b82ecbc57cb3a16f5f3d1824b1dbc5f2a56fea71695da3199518d48205e6a086b80d81472a3fe37088d5962afb1e3c8a40b5fa6fc68b9df883126ba527e63f321c7db6d98572df8c56570b205cd9b3f0421a740ab105ebcf72d748e51003dc022e5c0a9843ae5c193ff6c80796e1777da4bc46b0dbcccdd30923883c47820e288b35b72c316a802c1a65eef4a33ae4fac1a8ec54bf31b684b977f03ecc579b57afb40190b765eeb2fe5d6f42cc9f553e07a21258ab9775d62f5e1a0f40d16d0ae14c034b7a5868704ac88fd230779a2042d3472c709cb8083568b17ff9a1ec5ae45d6abfe11e6eb177e3e309f3aa7b8551f32b3d7d404c7cbd7a01da3dd785c9efc11bd7662309515467f366c9e044ee9ad8cf41d696e1308dd4c37440e5d1e7fa4d730bf1d38f0c6b50e666b48e866e92af63a9af2d46d1d3216a68da8f052f908bac9e1fbabc9da296db5c34027d65afe445c836341be82e84c55c2f04939c392301630966eb54c05da5f41fda0198b155279927e4c23cbb2f2a439bdd00380c68f68cc4425a7846707382ef0ad78bdb8685347414a7162f0fd7166863b35aca83499ee238498631a240377735a9ffc72ae0b7ca9397c91e1a38abdeaa8c74d5007ca338dca01864e92ae185ab430adb902e43922e6a47ac24fdac60f10449795c702125b142b4128dd21f0eb01636d4b7834f28e596e5720e8e9433dee04bcdc9c26cc70222bbff0c7517361adab576e7c8ff00380f877bd34fc81a22ada3b8f817d0375b9bd4868037f171a521d71ad033d652340810dbb5d8dd88b2057c017cbac629cc939d93a4d62b0e1da967b633f052cef215de3bee08ea767eaf32df6e0364c6a8c1dd13cec1963e064c83a8a67b49ae9e40ed9fa36829b793e052706b7aacbcc35d223832b29b91614f4ceb6983820f159388ae9f44aafcb96ec87f16886b2555078544709ea157a20c0f5f3477827293877c69a37f8c70e7370d8e2deb470fa6e75d54841dd171b96fb8fafd0eff64ddd942afb388666476ebccb060e731807c6ee1b02ae25be44cdca8d9142b5e1da4adb9bd4e657fdf39cd6dd0d95dffd2e26a25e434eb6c6c09c369e4f7acb5ac3bbe4c720dce84452caed33c98eed54d8af6f87639a9f1052af6e2384d2f8daf2e4c75188cb206b886db5004efa9b71004f8b8ecae3898745924219d1d6fb58f258efc6b52c55401e0467d62c2abfbed0bd9a84f4080d39d3ce454edf3ed71e3c00e536aff26aa3db5c9035222c39bb8a64603443db74226aa2cb9d0470591c9a089d12113d057f5fa6cf585b3da461d94c1851d8cb1f83e0213c431c3169852aea37bc3a6d66a42c3a635222186bf412a378ead7c8282f0f36ffc73612a38ba268cf739ecb52054c7a93ca2d2d88a0413e8eed9fd5a1f28bb8ed9cd5314f7d47b0c9ee471f4c364e212d90b3e483a123bae3d7e80ec98d32540f5675b0bdff2d5d702cff5c0ae4dde6739668472dc228db466249808f1990f533e1fbb95642156cce99954f3ab2e022583a572c47a48c00ddc05c050c5e036ec76fef89276a4b33cb3c7f686e561f674793394dab20b8fdb5168849693362710ab47e8361ce2e5ee577b351fcd7f371ba67864771053cf12280b92495cc6efb8f2957304599276b7f31c0624cdac506876a5e0fbec8280c71d865979baa712bcbfaa0b3631c68a5e3e75f14115fd7b8aea1177a39e6ce653b194700f44395f427dc401a4d6ee461cc4641a01da42e189f6b2d9a3f7124cedb07474323b7863bb63938c0711475560e03ee9977bc7ca2bd3663f672a22fece7faf2b15245c71817ca041fec01a9eb90b6473d987c20d0ee4ec2bb9bd6e50f7775224cf0598c9d597b84f27c166f393a8d2e492003dbc914af6bc112ae5ab04a717fa8ba76872be7844f71ee16fe6d3b4ec271b20854fd73765436987f9e2489dcd3a654f8c406efb2f9088709112fc3e8085c421dd4704cba94c9e5475e229afabcf12eebf7af8979f8faf5196b0d9ff80e76b77087d4e7b0b1c48901c496d0d2bdfe1c9be94e9dc80c2c4d7873041a6dea4fbceb1c1f2a204054d9512040293af2525d4bbd388b18c66aae0f3d302b02d3e4734b863b310ebe7442b1254a42336c653734848214467d34a642f3aaa7227238a78a830c5f12d0d2863256a48daf442a2f05b208a5a87ceacd3451a58c502be1f8ccc72d16f04401aeaf929f9595f15ac787a0e172026f0ba68d019a31cf7f0f20286950086cc6dc7550bd73a5bf357c0a02dde165b8cb6533315d1acb4f1f548c5a5c5e0a07a3e2b6d11e63315bea6d8288174e6f14423233e8f1a43bcdf92a05f4d49f73378d33e1447213795bc1e4a73423274989fb2cc44e883a5c695e9742d42d0e723915038771b2c78581e2f3c849ab9dc71b372bdc1a5fd5c81f76265311e8623d9ed94111bfbd19e8aad3db0d57b5d9ad89ab44658dcb34140c7f80f4971de99b76ea04684adbc233cbfa125cd4668d38e6e7a06d482c17aeac5a47a718cfd852cb0f673261e824ae1061bb9ddc0efef889bd6db720aa2b8bcfff838a324a202ae017670f168b734d61d8b59e328864168ca4957bc2980c22d97c3a264b93cdd1d4bf625ac32e7516fb9b9ba8d0b928466a8008a22c78941c5d52c8160ec57d9c7652518791299e0afdfbc5e6df2d669b0668b60e47bbeb038af1864d71e627cde7357fa0bdf9ee67db3fd50b0a5167aec390119d47d55c3cfd66c0f7fb654cbd5922c07936d0ef42a39698b845708a80e6fd5011d17b29f1ef0581d72bae1a092379cc4bf0d90a9663fef17fee0f20f1209ee8fda25574124fee911eb31ae509b5bfc2140ec208fba7604c88cc66760d8fd120905b5cd02dc0bb2a2c725c8e168cc784aecea0f7422ef006ea72c65ee59e7677f1fb7d587991c9edd092c033bca4a017259156f952a5747ad20af9e3db80586bd80c10a04d099d7c2cda248434c2b6840cb64a917664c469d01d92b29c9c7acc2d915a6ac460f106d5ce16cbc7a5e4a6dd477168add701bef48f44599c35fe484da58ed53f5cb6c84d6e57a3fcdb3e625e1d547311554c8a981a02424d8cfaa3f13c603ac1bd5f175864ee7017a1adeef37f47230898e2254c4083400040a875280c87be6413f5e42c4bfabc5c62ee8134132ac5c1e46189d2f99292a2565d0b4ba7448f2d30afdf3fa7df1d2d9e174e2a604a0a49a3388d752e484e25b5618d2c08db0c8ec510b69e48cd78bab7c68472069b2c503a6f6a9eccff6d6ac482ed8dd1c8522a09d03cc8ae6d8ee387c14a1ed4f5cd0eaca4b7f1bca63a7b354962254d250b7425277cac0103d8bddc621c5063928a9475f33bd89034c5034b83347be63ed5e35d87eac761d1b24227e1287b4ba71e86377b1125dba957e5618d075851a6a07ca65f1af2d31ddc7a3d0b73cff98850c93859d37f3a22ca3d6ace6bc1dc0d2241fbbcb42b74785ee6caedd561addaab0bc76db5707ce7731c1b3af308992e35e2ebe9091e9275a187f8a6cff8cd086a0585d45d27d3ee19f70689e34cc55461697b9489b7ae385998ea185dcaa63967dc3e170c7dd83bc43fadcc2b405cd32ec408fe8d6939b812f21b294f99ad3b034215203425b05d46a1f0544099decef969fa4f4b6ce5e3e2a5357fa44911ac07c62e16aca45fe2d294d8a7de4bccff9a7c98492db4cd9a249ed9835bc593ac16984eebd8585811693e64db6bdcbf9844c086145fa914f4c85e2091826a1954107b4d061bb2302ff1f040d2cb754be3bd929b40b86003230eccec6abd600b7d7c254a228cf553d20984c0472946ca88cd8e2013d5b00b05acc70eb7c5a11265d9567097454681509f6cccb63a76c7b554d9f7cae19ea7648c07e07945463eeb96aa4ffd56919ca1bba785b39d2a2571478e406704867e4049f088f291bb6051d2c402e7b365cd9dadc2f3eae480af13bebb113c0d95d14db1f739daa6eb9f3fc52e2a3f505c1a5541bf235906d2c49e2b6342dab8ae3b8c246101df760eb6595ba45fe298014e656f55cc689a65bbc3d40ebafb8b933ba478863f2ed05d8704c1d6d8bdc9e8aa1392b2712180cb99cc94d1fb634c73d0fcc298cee19b439072fad73d9929003e1234649e1a0ee7d68c7f81ad21c09af7a427a417adab62a061228561423c8c5437224f110a4780556e9948d402141bd4e4c6056a4b0985a94be895b63c8100a6573f4bea3e0067f400a982a53c9bcffb150be25d9a0a9e311a9194baa9f7e3c59d123b9d9554649bc8d02c535b3b2be5710e95a819c62a45f959a93124bbc6beabfbe79c271644527931ac284f422423e4cd4357d99ff139100e3dcaca83c3718c37b6f01080defa256dce5c9689963769606322e244dde0378324cadf97a2d37a49ff676bb7fd8f67e464045d8d4ab1313ef67619836ae0a79b4a9da382dcc1f3259fe4a5cec8e21283aecb0db5cc38a138134062958895b4a831c33e1e3e32f3033d8c32346ed5ada11c11ec62aef134cfe68e3ee71f08e9cd5b659db73b9977914efb4d99cf1d12a925ef96060d5ca8f15625ca05c8e36a127f5ceb7d52cad5daad34b07970a94dd5e4ffb0875c617a83f7f9e406ae92d824bcd5c1e8186ac55b70b5c6ecae1c1c3d2e05df119c0d1860d6c955038baf5eb50448dedacf16e39da92e6d3b4ff83817ef23d59e753359b415b01d48d8ac964370ad3a01fa84f2f792077bb8009cabc96214592b6b7c8e8440ac6549f9393a9d15ae9177107c96165c3b3c4590f8def9e90eb3da9e4f94344d6b58b3a34a8c345ccd32f0f259bb9d2c04598ab1d01fe8b3775c3b81ff791c641ecefe28de69dc25d84a55675a9dd0985016f86b5978d019fbed29fbe9dae1bade75a644e1d922ebc339e9c06db50785f4b1572759263be2384f32a69b004797ee14ced4576151f8b72eb7f1f750a224f3789b5b6efd9fc844ffd1ae121b8387598f27fa530156acfc8c4ac2f9987fc6f7f92ffecc7815bf4a0e3dc09398a6387cd2c2b7274da60138c2ea0826759ae322a5e9397d29180a2c9840ef7107beaad4f13e6a6151a6a616810be9f1fd4d711470d568a20e0a02e4a6c5e1c89a0c8bedccd7476f31687192997a661fbc49689632447e0b63cdcdb659ce7a1189ad02ad0f63028b5278e14f564cdd04488a125820ab3a0f4ac081b21661e1b01e8d035be2c458ee53a010380cd9ad884d7c00c09a25dbfdc6e4e903ef6e41b91d94f36fde190b613b6335ff10d84191164fc5dd201223b9b7d839920b976abbf2b8a29ffc6169d7778464da573b76f779050311505686af12a06d7735d97e00c03acb67fbceaf34fadfa72f9a3cbb9f6aeea3a92aad29272dbb77f99c51bd5818f4b40b3312d31de381c4deb13a3cc1f7b079f1c66899728378c8c321405590679284acd6d8c97c2fe902114580c60dee50076ebdec493b7d8dd1c940b50c6b7be6af871ad2e05f0f9192db6d02205b5886307931b7e2b82a1b4e7685ffe5be75d9b5a2bac0a259b0c8fb00d0cc006a681affaaf9e4684a8a8ccfba634867cfbbe2d8fa95e1a5748773f3691d6cafb008199f5715d8351d832f2c425aaa38e3d2094160a017238f6214725ffba98002f7fd36104b5e1890ae63957e6bc453a8b466954bda68c34be10d8620be80c67901da5c545237cc1b15b786ab2869ae5f58910ced21640bedfe3d12b7e15a752e3484a88bcae008c0efceb456e41b030198e49dded1337f56e32642a0560942405e869185d1a7a089fa4b54d8e1084c23f34fdc6986de32e614b0ea5cc1ce2ee024800af196ed62b85a0b2e70c73c1a1c8ce6a62d2de173768fe8b9cbc2a895dcf4cc48ee24c52ac0bbdb10952bd6cd1223a41a105270a0bfa7f0cdafeb0eb0a43f904e7d4af507ff8482f37b86b68d28a0e57a18002207d0dfe3b323206c2e0043f905e41650afc74fbcee008b9d48756e813040cda893d35dfefa400e2eae7b8e993d3014a43edb2a527a82cef6d11e86a6689ef4865248f22e290c6a4ff6637cdcaab288ebc1c48732b856832c38d6fe03ade55ed8c79fbf99098ce540c081f88f4f20043bec6659434d9aa3c261f6d37ed2c6237e9125c435a3b3d2bd99bcbd18052d32daaf36133f45e2673cbf90d903cc033aacb4f75efb923de661bed3d0ad94746e5db48e2c72abac059255f9d995258876648e52e57f517e0bf9844027b30a6c1575158e2f53dcdd9138993c5a07a3eaff8b59d32c6eee99239ee635bc9e00df16b03a8778cab796f31552e70c05ba29953f0a4d3b84bdc546d8abdcb83d46317512fb6ed695cb318bfcebda0437e73b4f400968cae40d5b1bd5cabda0f290df200f7fb6ed5e9f3fde415b4117b73e27d8da46718af67e7f2d876f750394225b393e563b5b56778e853b52b20e5e6f96108c38068aa36baab21bfd2bd9cf71d8a5cbcf13be9fbe591f461cbe20207228d0ee238c33a4202ce4cfb93bd33ce46aa77c5028bea13621cbeeae1647dc2a211e54e7decc2c51a67176cf603de93c5981794f96d5987bfe353d5b9b5d698c496eedcada09e34fb04d8d52ebc17bbc1f180b684c0d7a369f44bf6f9ce4cd0a62507a1e86c37e5ee8be779455d55892ecc28dd9268b85f7f4a23a5801b8c6230777b8cb077b101fd4bc6a03b9115702268d62c564c0b84cb734ca7e684c67affbc9c2b27b80febbd662c414ef0434976c9232e991050053094e0fb2e3ab276cfb215a4a5d268ded0cffbfe3d1789a5cb0d67ca1315bfc71eb6f63df307dacd434ca0c1040633e8ac426fda997fd0b9e6028486c4bbfe0626a21c637ca444212199a141699585ce89cbd59e64ff146600ffab09d9171322a01b8dc4384c7660230fc432739eeddfe66e808034c8da049cbbdde7525686968fe4714576a8bc2e6f0d92d042ba347a4b0d35c10297eca2bb3ba61efefb32a0b2e60286c7c5fa8dd8ca0342ac7ef4246ff34678ca2445b5fb89e5dd8af258c1af0545a00d28b410ad705d4f68e0dbe6f709fc3792d23327d2662b326cc3b6882166ebcfa0dc43b2bb5f1d555f8f07752ee0331ae23dbc549fe006cb1fdc29eded65cd0b5ec003186de47bced9e3e5b16b5d5941cb56f2b96630090b8a82f24aff98d8f7a8cf1813b31cfbff62db110f15f35086118051466a5e9de2157b3e2460db85b23be67d2cfc573612b16a2ab71606e916b940749906c03d738a02a41bc6370bce59d757cc3e10485098275450bbd442097cfb0b326e6ae3fcecfb0faff66f4838900f72f71d7fb8a25ce1f5d0445e83a7b2dc54a491aa898e18d7a8ac17e816f945096e1c0424ad05e7f8dcbe25c5dc453912856fe010233787f340c4e64177bdb431a32c177026c38447be2fd4a301e8046bf069dfb4be9d1c66ca2a764e467268e6f2b4377dda7717b3e3567cb78035d775d15d443aa097a5bb8dbb4585d661038bd8f93337d09eede2c98962b577cefa9957a6016cdfd714f1d7bfeff0064925eb275793d88b359ee344bd131a302afe52709b9f94f9396143929c62c15b55db3a1ee89b9796592f2c80488a26a5b832661b77e72e39cf2f8449165619390cd1d87cb95437667b1d905381c50bac41fa18245bdee2a00b88f0353d476243815368d91a6b392b3357cafcdbff5e41965008d11799c82b15deea1db6648d1da71ae20b143c5b75bdf8eb43e69d07c2a7603973ccf4d7631b49b449fc555992c90dff728d6a6a5be4253f3de05c2c5f4d70beb3ecf1c24849056550452b90243e15239372acd0f5ae87e9f2cbd84cca8be30edeefe20e0fc5e0863be428546b61b46a5ea2dac6b3e647b56f594d4080741d1071da5cca7d94a95e5ac48fdb3d96e472b511a14f489d2ba040665ee2f20e3a8ecc32acf7049ac132867581198bf1b446c1c9306632abbc7de2bcb0cb00dff21d385947c3b911f184e0ebccda8dfdf033fda8de6d2c4062beb862ee6d81a504991ceb0fa8cff292dc67dc9c895378ca9f2057e47be8c726e7009f1a5d87b14a7b7bf8febda9f819050bc2c87336011c5b87751b349415fb959e6864a78f763c7a69bb6ade9a0b270aabc266d41e4b88763efef996b71847bf9525eba794d87a2a68d79efdbfcb0514717c18c9ad1ffedda2ef73201b13c10d601840902658e669b6a619ded110876c7410abcb02426d22f63424674d70577dcf6a6a9ab1911808d93a73da0742be12495b6babf7131c60b68204f45c6aab6082f689f6d51ba8b0e2ec96c22c4589a123e76ba5cd5ed9622381c15a22466e2339335a884e5fdd067eba695c9f43efacd01e6a722483b6fe77c4a3b1393d0b378afa82b66a9e99b68f5fa5d98f18179b07e6807fa508a1a262e90fa54b6d9ba66f6ad1e2a95792077d3ff67e4a0f0f1f6ac38931cc9733201a903de260861f0f72a2ce9344b97622249e32a1e30346c70718e338cd2d830fbee29000647101dc9d1009e7711a12cb544d4cecdcccdd8bc512eaf9e58dbb88a0ca05e330a421a5a9bb169092f52785114ebf9e3559cf05b83b279583c30d1bcc080c673ff07256a54f3167b2093475bd3949620b3dcdec7c69206aef192b25077adcb3a76e9858acfbef267ec03fbfceb591662f638a6817d35956ceb41d0fa952bcb9359a3c0d197970ea7fe9a6655a35bb7782c05144d3da521b55082d2f406ba62770f2f11604d2e8eadce486678c70f1179630cf000507fa8f285c90cfcd3cd148fa7956079bcc017e23d2171028b0ded1118347d251a1786197ec6a1c14e3c5efaebf9e57855e5e15e31f0a4a3f094d35f89961880916a4617650bffdaa738a778899bda0cff3e07fd10c940ac1eb684952cf44ac9ce5ce716af09487b28bc458d60baad880036bdfe32c3b132814c5905b976c2c61e747cd7376b7d2a23f55e294f3856f14b3c2e107c19669762a5af5e9c271b5408b3348bd9a5dd32e9e816d2713031ce0131c4c09b22e960922f26dfb8afa8dd5ee9b5f0b1d8956148772c87e4442cfd1dbc7aa33e6487fcad1e23b654461031b74bfb43e656bd108998db9df568072c08a5ddcc39ef8b0d3dd21ce1c1b0d9f4861bd7d15fe28b1b2937e237df35973639b667815b01e627b0647e1e2b26a920bc2c0a40a0ed08b52053b34f01a9f9b7ab69d3254e2119d4f9f53702eb91cdf353fe2553211a1f11e0678f74974bfa779cbdf9e7ac8bfd5888ec4db47bd27944661c04e84aca47734a95c7856f12173de2aa6a6eff3e761650151ddbf78b8c78f204a8d300a38da69144469d0015a59f15e189e81a2ba1ff95151802a7708356152eb05d0ed68c8acae5283f333a907b9bcc30c887b9025eb3988680c10b790390be78f68ccf4821fe9e553daa9b7a4f33314978823a7ff53b7f1a7cfe880be3f8cc089954d4ee2df50e1828f5bf263244082fccbf6d226be5a31df8c263530ee5ec82eee21528164c152c9671939475ed4e27afd2289fe42d4ff8607bc351f5dc56e7a4a53a932dec4249d74574be6bdfa5ac50d35d3c24b98caef059d989ce192e5daf9a2b523c800a7079e5ac1ad169cc6180276cb1a1fb38be631c6bb54bcd65eb0fe60bfc66442ec7771c18bc85bd764ded5f0cc64d1715d977b54e71443372c2cd013b2e3ee8168ca9ba04dfba2f78cf9a37f6f02de574f795720a8383e4fe4e47239a10076145675619c9e108b43a5b33f9de22b086a32d40ded1504d8aff69ad8af14647f41d28b431848a49d49de829206b25336a504c24848ecc63887ab6e83cd4114b8cb1a40c5375f8246a2d2529e2153413333e127d3a93d94b611179b57deaa5d384e4823fe5ee81351729b3b435c0c9175d4acdbc5f07bea2cfe66f6a34af391dce0105354f5203dadf42c6b07b573c71b536ca0d0550b02e1c034710e22b90766b576c0e3d24c2b18982729059a62e59a68c6dc416a64e246396529dc0815bcd11d4d438edce3723568b823cd58c0fe60c5895f8189d91e963b84d9fe5337ab0daac270c78d4ee66cfe25b673104640d7d50de005e29c3800a5ce54b8eb5d454bef783a53fd87f5d2db0a7184cca926d89ff0869377aa3b9e96a7da5494c0ffc362f27650d06ff72353326806371d12fbdbfff5014e327e1d88b6c16ca1bdce9548a3a85cc8a200a8b78ffcf3a15e943a01324dcfe29dee1ec752ed060a5cf725411ef8c6b99adda6cdc855a0682df9428f62a5eb64e8b11742280e4e11cf502d709a96432a5166616e5775ec014b16f570b5827d4f3dd0174ccaf6f17e53897c9a6a3812819186b95ae30da8d8043f6ce703e87d3d6dd3f4549b1139e6b634644afad6b9090c02a2b66235d04cef813a879edb4803a08125c451ec5b877f98a410e04b17ac586c8cf7f1b11ef392730d66be162ba9a93b509a20ce49a7355130634c13d7a4a3dc583cb4db8a1d78e0a808d48b63e53a1d3a41127024c260cc8fe30c0bc7b6fbe8c1484e5a84727b31b22cba1073021eb7dc48054101aa152af850b8d52f8b5c49baac9559662eaaf2e71817c38dca7c376007cf63b0933a73e3faa2c6f716b40d32170958d3841cea2614afbd36579475b4007fa0bf03a6a6496fb81d3d7e5d7d41937190ef0ab80ffc9c4063e0eef99ab9c2bdcdbd5180a3941d658308986fed55a96b9357b8bde4f7e39dfd6b12d64afef11ac3dfadc02f1395adf315a759eb6d92898090174f8dae105cff370eb1268a4a889395d16c3aefd952befb4b28e960d7931e503101ed51a88a6886a35f28846de730f7ebec543e62f0e2a6734b0f42e4309537b177df9037cdfd4013d3ce7682d85d6d602ad66e7890e21976a2b01432231fe122a3f09b92584d17cb329f3e614102930d49af3914538e9f1e04c472d5c46ded036c0ca19371d6757ec35331fa8419ed2c78b8d7a450a4a81a61f10c884c242b1f5802eacb03e940db0b48ba003e35855f2dbffc89af005149bb675babdd24ab7eef9fb410bf1dc6d27f3b1e616491c33d7c2d8438fa590733c021fbfab22a96d009f95b79c600a8e5ff3d5c1346d9795fa43077e607c5834e3d1e475104e5b213ec6e0ac64069491dcc46e6b20ced82e8671605042c54907139e547078a415a54942f3446c98c36f84cd1c9c3c488a22b57fe0c0e334bb597a9d0dc8e02df5dcf1ca335b48e5af0ce2c694ba18f422ae654b0215b61bed29fa24d59aa4de6cb529e1b201c660a6b94de829362786a16209115e0eafbf4741afce0eb4e990d1ea94a686a4d41634e49f30e70c362623631b4741275faee0fe0ea4dfa23e37c8e43f44e44ce2f541a98adc93fc08f39fcff1cc34a440b2b04503e071ac277c8dfc3fc4aab63fd568812e94ad4bf20ea7781f55a6dca3822f3880186aa031a6da0a22f92552c7a2b86805873ffe2a486698e9ed48ce4be751d75ba1256ce2517d2e6da2d3442357497e8a2c64284c1044cf488a448f4990a488e58377926698560963d39c2f330f09d2cda58d3ad04bafd445e94c0d043b4f601e4fc66e7a44fc116a40d01867fd2971e4711e430daa92e670a055fa4221bdee2c7e5ddc18db119284c8c07fbe3f8836d771a0d22fa6f3e85081d2385d757acd6bfd760b3ccd6a987a92b5aa4ed1809f08eede9c909bf29067942a82e626c4aebd271f3cbfb05c511052051dc2392eb0ce2fd1f01dc1863e9fb92f9ca444ef7b24f539b5b0d152980c0bb7128fa3802bae9a3f4d615efe8317603b48bed696ea9ea2747a40d67c8b89b8a09362ab5f5814c0b4c58123ce7baafb37867a8e32d2ffdc8d8f3343d4b4b40a442e1ce8299e16ce2f9e097a732bc17f5386674e3f81fb13fd9be2aa36027c74b2a52b831aabf9d33429d076ba5652384ab11f7d6bf989d39e3d7991246e2b0cf19c3adec3ccd2b156d592a7a64ad79ec8db61ba1099d66be4ed35d1515748dff43f54783178244eaedac66e801dde1186138b2229796a574f256024dae7d4457fe640d9cb9518acebab0f578e1522475c33799e435dc71c2620c221786aaf3de814cddee25f704bc1b2b4409bf94e62e94b19e0a5a4ae72d3b075f6183426fb6b2df923cbdf761b378c6b959061c2348b79cd4868fdef4d75ed893c654402d18bf4548712e78e187202c3ded49ee6d5b24becc549c2b0efa844098694122bf5514e4881cb28237a5b374478d46a30856181c6e8c6889528a2057d187f9778fe13a17f74b7a8c3c438d0a3fd9f037975f07461ec32400790bbcd782ab68c7580f30ffbdc7faf470c8a82e867a658e95737f8fbde6a8f9f9ebd1362a73acded4c76ade005c7960e5fa66678622c39c78799417196d920514ca7c0a654a08ffa2cc88a7e79122c511f1bcc1af8a2e0b5a71753bd73dd4ba670c97e72e4323abf8e49d9a7daa817f2b270675a5be7992d094dd9f430d2cfbe36c869e9a167bdb2a17a0d05a27b92eb5ceb7218d938688f3ad43860c0ad08d625bc3706f61feaa0783d11d7df899f91cea4922471569d014e91bccb53327ab2acea7751fff65f9ec5f591f41fc6e3c37b6e350207062c67a2500fa43e345f0e3f356965cc9b2855e1a4b245b75ab718010f706068b481cfd644dfa5c9771ce8088efcfb841c11fa08d52768b7ed142e82a2fc782115ae9a508a86de43bbca59bfcd3a7c6591369b42e7ea850e544f8355a91f9e85beb20a794acd1fe69cb27d307cca556da18f9f1f332a20a39b7263411f4c4c086e7c7c002fb766e18b5fca3d9dc8e6f68a3e8645da67ad8bf48674fcb4494e217210967505ba50a8eaf96d4c79154e0f3439b148fdca16ea7c4d520ddf4e2e7b913f86a1b5c157b230f79adba1df25e712d234f2cc4313625f93a2cea3f33ac8d1a3fbd7429065f7d920627581e2a32c8e963feef946f3f29fe80946f6e3f771fc61c3018db49b945ac902a5662aef1d1837182f6624d195406bfb44dda1e0c755d6bee33e5927cf12a9859256773b800af0c5fcda296960a14d42c3dce3ee34133944090b60c75b3b64581d583cf8c772c2eec024adcf346787a12fc102415d9238eb47bcafebed6a8289a2fed14b0906309fa1b7b0c4ec62194b03ba352e79dad341688c1d532c2c6086dc5c47186a3d049a3462792e63cd77df2e59649e3d354821754acbf9c510a7b7848160c62deb57dc6495d594066e0abde59e75caad79339eb9909085ec8f2e986491c9eee0543e479210cdd8cc3f01c12c2cfde481f3de48f8381f1afd658e4786578956848b336add114cd674ac468c9b710b3e04351d2464c6797c8acb2d178dd83bdc37f68164439f212901507dcd046c05d0b9b5da52f8fb10f4be4934640e8ef38ab1d749adb143cfd224a67614fa27b7585a04327730529b478b622db8cca8caf00daf160a8d7a803588ed79db31f6923c1b54d59d5a071852bb730f65d464b1252a7f3c979817f2562401ce591dda066456d00d87ae697754b6dc08ab2dd2afbc2906ec97be324b17bfe4626e6437a1471cea443c559673366f40f0695b596499c881f2f7556175a9a52860f4ab9f2be29f56ab22db8a8d97b207a02affeb6598ced15cc29815ec5fe0a9117e65e03f3fa6127cdc631d05ce53e309b0e6cfd719935d2a78a4053660055b04e636393b25f7a323f097666bc219b0d3386964f5fd7237815195f5cdce05b90e353040b3a215ca575bfb1223615c138ff8d54b179e69831e763302f7121338147c56cf17821f7724ce899eb2202872bc3e3bd4133ef689074b8d2cb84267288ed56c48ca485a83ce60b5b639a8fa586b4e6684f37abccbd253d6508b8fa09d0cf106460c61219994259c91e407bf5802612c51174221c83420de4d09ad10e228b2d3fd63b64ce607872918e62d51f38259ced81217d2df1fc418943c311694ff528895ef35a9833e0251ffacbc628d24c37d7e5c7bc43927db56a95bbd4fab7312f71404cb6ef5eed1c41177f7ddffab57340b84dfe2dbf5b9720b69fa894107cad1a37a31ded55992ff1c96656b9fcc9defe6d4aaca21ebfec22f4c9dd2f660719e043d622fd2e1e82fddbd10f6a1b8cd84b518e81b1313164d0e8e39e5e05ef32a82d3b1ae6bf4ff1984ea4434b5b756505e328a7202ba0f4ea1ba60c029d926827220149cf3f67388ca2109939b446415d3fee37056b11ad6e6fd25880098c1b2a20d84b188043905d2acce0e5c09895bdef94c8b50f079001cf4f696f34feae833ef3cdc14d9e74953902cde9da184893ca09041cb06d819ffb964f79855695baefd8693d9e955f43df9099c4d8ab6c955be14e78eea5f4bbebaf41606452085599c760e71abf075769ffcbc6dfebf8707aabe252810f88d7c90dd7e528275bac3fc9daacef00900792dc1a9d50f185366f5c857f0a014f213b2aa35e5e10deee839a85f15528acc53b05ff669776381f7925c2b7e1698623fd7e6acf45f2d726d8cf99f261255ef93888d6eba832f840be68e41f5c4ea4d738ef0d4a9c88828f7ac6eae5d6c888767396b5a27ff49e6d3494827103b650553fd846a8475e4ed055eeaa168367a08e4cb2816680f7d1329de38f2ece366023a261d431a8467213ec2e2de3a52988a0610a8966db95e2229c4901945022f173df0b4152831e163f7c558f1f9a31f60607b720c7525b19f74d6e31c375056325bd548859b85c0d3b652b944a4b8dbabd93f1e85c25149b0970121eb16f8ae62f7db0d54b810e32140c7d56367254fbc687f106dc91ef96de59fba9b1724c45981a0704320e13e558719c337a287be5d122296e9fb62bf4fbce083ae1322819c12baa6239465a60303d4fb5800c716db6f655b4334b621c436467018f091378056cb32023daad7f2bcf18bb4955783b289e6ddf181eb399907e2fe42625f03ae323ca44e48c3d445ec4968f40653fdede52b7d96eebfe5a8782c4b972740cbb0a2f7735a133a8feb09cda7dae66f9f7ec744833e5faa338a4c30a041ac1c75789f3afa324b4c6299f616d6a8aea7c8bffe4c36e98266d21c5a4d5b225ea76cdb5af9801a3f825094bc52ef05c1b9d210a221900b60a2d1e585793772f4b116a6c9ac9ed352b2c65cf4169f290989c9b5f0dbfc3e32ecec096573d7326d7d4d40c850ffde9ba5f09475afc62786b33aa5c4e8f55a4161f6d78f7e653b4416038c58baf119397cbec5fa7dee3ddb1a21a103b92d2a9b59ae955d015664685bd24c014696c99be103f794054897c5f4a25e80674a60a36fbb3972bc91e44ab93e72543fb2b9691a36684520e881e3c04db58ee49026a29ffdd4f2ec4091e7d21ab67d4c4d7574169190bbab761bbe2fecdb7ae610353846baef068bceb5e6b667b3d3bea13300084073c0a505f5d2d80c17877fe5d5e11e17ed228101b57c7e9f68b530bc9ab5f2b842bf87bc83f04a62bb12db4cfd73b40bbe20322c6cd584136bdd9da2f22442be2cd2dfedc25f3542f62cbf43e7cbfa444f073803954b0d4988dad31672227c310156546fae2dabcf463bf2ebd485b198c991526e4739a9439baddffc0dff638821e1d59cf708d635937bd9251cd09d9570f74c5cb368b2056bbcc4769e04de3626d505e8971dde2e97bf8c3c3f886c3b173d16bbd74edd032c391bbc366a324744c99002c519493a580a8e464570d220733c8de7111f81124de591cea7659136430ae3b1b63f20c9f731699086ac80a9481d3f4bdc183afa3d7dccaf6b8f671fb068bb28c86610f8be33cf969a43a3492e5bb50289aa3e7d968e798b6879d601ad21396b39f068010906256549f80fa358af411abb809f64916bfabb9ff270a5a05574b046ac1c7f800152847a889a2c36dcc52ba823d782a62f55d904bbbdbd61eda6963830520e68efc4b157db98ad7a93697820299e3b47e211357c3e91eddcd95ef9ece2a4e8bb17eb506e30da649771ec58a757459f69029a375f99f1b1d6cc770e766b58ec891f38184ddbdaa81c46ff25ba0002ff9f735785a43a2ed5dc4784cd7a50834000b0f45273cc304cf64f94434a7f64b39bef716d6c28068f529a655ae4174a8b1dc27a3a2bd940af40ea364e2c2970d2b3c6aa5a0f046d5b7d30b50715e2521778df941d0277bc5e9ea3c46a3af1e7628956188285b4ea53f49c72dfb06ea44f450cc9242dcc1858262b4528ff132f70c61a675c97f73c20e6b069a49a6875aeb50ba28ebd123e610bc1ed4d537c09e9b5b2c9f5666e75c7ea4716b78f628ed74a7839aef0b4c3bd0d0b5a4448e02525d3f9a115ef4325d9adb881156fc5776de3ced4493690a430bc12d8bcf608b30c1712d28bd1f60a84c8ca3522781ea05d391088cd7f481ecbdf77feaa3f4fa3ea6aece92b1cdbad14dc3b95d96ee32bc2526133e48ff5da1fc6bd718e86d5408c000b5d0fa94a218bb0a85addad081ddcb702de3235d09a37f0ddc5a9206589830618ee23731e51d8c0f8ac292360c28aef89c62590ffef6fcf213420f83dbb700d0b96c71541e7a51e23d5bef4bac0447771ed5d445a334c1d42c7659b06f8a221f3efb2aef773eca3c29e09ef7c7a46e2bafa06d7e7e213bbbe20c68b898a900a6175cf37f8ca8f2dc221f053f5ba6fb421a23876ceb49fc430e04796835b1442716d2db5df72174906cbb1b64a70410bd4c3655e281443d698732fed7818e7043e40f1d2f7275d8f94bc4480a07f656940c26f93f87c803b1c2e1ee48215e84dc5f5f97b3a2782668607d14f78bf9453e783bc712775cd878551d8ebe8a3936ccb0a054588cf9c30fbe43b7445fbcf1fa84ff5205f87d1c2695a58752a05c783031f7746cb8bafd800d90818c9f7d9197456f54c2397dce8888ba410f50c3435ab5ffd43c827f169a586e2f2cbf14997d4c725d3719c07f7e078eb7fcf6a9ce0ffec0a268211e7ac7b07c415dda7e206e4383857da138a2e840efae5c05d9fbfd924926b86329556e1ef0e3728c5205f688902e00ba6579ed7b85bc0c03517be2b944ffbe5094d9699b2ce8e80c26a6f35e3219fa64df8a2b9c1df883065553b52f4576a2ffd5171138ff529fdc52acc7df213d5a32fa24005921f3705b508a573d7b0c5fee6d0587cad4cec5bc492954090efaa2871b91023f27be261a392272703edc244a278e41fdb829d0c9441baf8949f4d21ebc20b6a338a67b406a52909c8714e58ae36301a800a06464227bb3a53afb9a05eda7b1fd1d94dcfa7a9db318aac4fb3a737abbd7392aaf46eaae1733f9dabe035e841a7abc81973cdae39245e7f474287496c3ec3789f0eb8f6aaa2083db9f90d06f81d653280e4c24c8243272200df4be6f6830302c3cf8033d1bcb20b001c92a0409240bcb1fd28e01e1e36f3bfb35519afd145d87bebe097d901c56eca1093bd83334380bd0245d4067356755c0995e578d19d4940a532af4663dffe5cdbe461efcfb8936ee2a92c94c042a909b6dde07ea9eb958107e7ece79f6a1a47055fd59e37267dfdd4b17ce15a89ec51e4445058bfcac9be4683853e2e51a08971ab3029c8b972e0b5f9df71f3ffd82a858f84c6831858bdc9dab241467cf966744378805cc70009f5645bf8bd5f8c9fa5f4695d9213232cd3060e2d1497475cf8f837132db30f96d163cae6496557fbd30a8fb55286c4d286813e0470ec5a244f3f89d04ff112b12d390b4cddff61c342d08554f877d60041ea938eac3c7fde6e81e555225633f2f5b88fe9cf880b40f7893410847041f907b969cf7351dc555ee42490573257b4ed0a46c98c2a5ef09cb4c46ac01bfd0d8901d327aa0759dd23de748450408fd6a3b103937e88db5e3c7e30cd9c34d61d85877b4e8d7a3a5f3e9d150e4bbce6f8ea1622cfc44a0c6259af73c5337353545d69265a70ed74af4cb3470f6792ebee729447a3d912f8798165aa86ce3468b2675ef966610e071aed9948edbbf01050be62e65c10f0b023f735080e789b9f7c75595fcc59a5d66b8ddd28475bd14b6f9916ce6441e7244d1e827d1544303cf887d6252e625fae9e53ea3827ced95a9a752714f71c30ce9b15f0eddaa3f483eec43b04d81439970f998ef522ec17cdddcc8ad80273a7591760e2d08ba738a83267173dd5650770ff7e5a8245cc1b2a5671ecbc008900eda25af863e4ba393cf339fb912dc46957e4e3a97f8ca3dc117c4a2d2f9c4eaf1438983edcc43ef0c145abbf74eae540665f7a62a16f4a7e30734119f845326bc441a03e91f7bd864318d5e1d10c76ddfceef1a70b2c4921f170282801333680c944f7fdaac4e25a5c7887f4bc7cc9f51992671a78924444fc4a548ab671c60a094be2876c9ba7f2325b5668b06a0db433d00bea63d9257ebf3567e9e17fb9689f405b044cb5e243c97ffa8bb67e9b968656678ae89bca847fbc2479042a897eea55cfad322c17e5de2883cb5110a4414fcadbb729d4f2d19f6f39f421e89d57345f10edf910af5a8041ec644204e5498aebeffd01123b629b1ac9375be68ea42c0d3eb33c32f9bacc9d8bb9465819c14397b9e1c26edf91e6ff612e927849350324199e2f47454b0bf20f5ede4644a4a38de6f919e09d0ba30fe9621a02a2300f7f1f2383edd60a5ff7c49aae22e17daf500ed27bbd3cc39646014ab192dea6594ff7611211785258b9b3cf656fea8bf4820ec788fd376a3b72b482d9124cbab2b3682c40394e77cca0d2f0513462a86ab59ff11a0e4b8c5d0145f91619f4919762ebe1e91ed63fd80b63045005052f9af92dcf0a95a12197a16929dc3e089c643557937ae8c33393f8fccb1c9ee8e6d74dca45e35d7fad63e38262a4bc15f2f2ccfcb05ecc04d2511bae49c7782f0357240c79110cbdaafa93a9483ffbd7a942f9c9b91f77cd0fc4606de83409f473be518e8e5275dd5d17b9831ae82e861f436916a960157ffff7a989e6f26e5103fd4a2aafcb0518ef04524e4f334a3259b841ad7b29505804222f48ecca0cea1da555b14eabefd18ad5913fab7e7e72457a5f42f48eba73c4d4c1b724d3a51cf1003ad375b6b9d06196097f0a5341a4f6d3dde466856c664d23e4b8fa9562dde6fd78ccfaafd7e96ba23a3f0f1b2823aa38f9ebe3fb3d93c656258d70ac2b49f17d051573326b7fc22307d1527962980fcdc83300d68ddbafb4829748062d17531a2a3da575ae0205d754a18c92123dac1473421c66e397af308dc00c9da4bdfdd52e0629bc2d99e1c86d369f3914c2f8197e61ffcd0f60502879f6910e3ec525f7666948e4e49004ee549daca09a8218e65d0fe5ad2ff46036c7f7ba9a94d881ea2f9920105d00893f60cde272121a7c0df01a21be70d0573048b950babf8acdad3380da126ca7c71fc2a12c71c0bcfaf5efdc0d63c42b4c1f9b690ab3546d807a3f9a76ce5b03cf606dfaa61d451f377912253b5f70890d84164dd8b02f621276c4b44447ae57102ed546a919be4c40b0e84cf47aa0fce5920e5b2f34dbb340a5b656f6f36fa5e36960ebb241c17f963c1b8e05f289560afce3282cd89d26b0e21d77140c858202d640426e6e1fcca542c5979ba72e917cf0e902a73404616080dd36382a88281ceffac12fe7fcf8dace79d6df34deb4feaebad5eca754b3bd14c7a7f704a587e8597bc22b16d531b90e0f9564e4a48c6f20d94cd0cbca726bcf819d3a2db809527a453eede910c2402577d51949654f3564b0acf8c6e66f94fac24f6a14917068264410ad420207ef2f010cc00205499440d019b014e264b067957462489eca145bfae7549b6aeade97d26a6e1dc3f2b8ccba90a752fec366fa8ba0b21d724227c53573ce4a579226bb274ae6c7e717ea1212b5dd567cc575afaef0958df4fe136b324d5595c4ab1cdc997eac536c7a982206893559b69d03235e4eb6b825177c9618e360f9cb6111fb15f146febf30f2c1367defc4e7cd46fc6ac2a6ced22b5aaf7dd4cb63884b2b6a33e7f28c12b527e653ea731f84598b5003e23a60a779b600bd6f08edea10141807a96e6d83e95402d873905412f12c74b7478a0b0397c2bd39e558e1771741558c7c10615d0433e8690d81a5905b6f4ab870575a87390b23fb6232c5c8974c739487590ac9b45ce3f3a2b7daa87b736a5d198eb16b0f630998b35cd875287b924fcdac0e628b97cb7cbddf6aa2713b536cafcb02b4d4858e856c9ae9a102a25d5b4ee44ca5b021407d29b2e1b5c25424034ca027958dff3dd47c2ee5125117e9074dfb2ddc048bcf9267573be8ac7782c014e97082d19312cdfc1ff7d29ebfdc98c2ceb3a4fd08c3af9f558183d079771dc28a9e224940c82d39501b972069fbbcd5a8af13e2aafae1c2a0865906f8958f420758ae5209dcfc248c07a2a5d204c239e5dd517f3c30e8a634bbdf95c40f74cd81b0f787add9b654c931f55e6e3ef33b05262563b08b8e547f554cd594d615b62d4a26cf836db2c8f972a1e9f3f95430392771071ea092f9ed0246d44228b9a0009bf2325e2010caa8ab05dbda2446803519fc83f7502fc821b1b5385d2936f3ff3ce1f044ca0bb9ce3a2aae1419ed31db4d9775e9cca470e2f5561a7335c54fc0a02216867d098b1006f62ea14f804f11d3f2682edcd0fb526a09e11b3f5c514e0c6036068cce234284561c8dbb362ed5e36eb060af969d6ee60d4cf00b5184496144322ae52c59309896a26a80b51b3d006b6878dc67e5ae638ab50c88c4b96205b6c75d4d5d717a74dc38e3e3689ae248e43088e56342419a11a1949cff0badc2072697704fd338526f8cfe30dcfce416485461720c0deff2479c99d90c1bf8efd30e77a4c394abdf7d4c73005de6df82d948af3e97242c663253ccad733d4950b1a60517988b0280a789ab625b1f6be41eb57565b15af0b5b11043ae8caacc9c096bda12bf101a7c0400eb5ddcb757414c122568fd7e07173eef410c2a628b1b1e1676d8a7498646b839c9bc4b970d8a55f1335cf29acb0e3ed9ccc468d4292daab132bae6a7cf36368dd918bbe96b6b633f5a2cb62c7ae9cbaab9f78c69488a113619dbeafdd0b21671fe335033f971d2c719b540cf046e488633fff35a92b14b4af2e2615fe4db665d1ae161a06e1e5e4d0e372b2dbf8116186f87aa2a90ccca44febe261fe9909a0df4bc4342f89a70202c7287c9f67424186ad449d2eadfbcf6fc9e802464e310df8070d86dea5add4923d1aab6d9b34866648c00c0b2b71a51a35a1c1f9e282f71c62a447e93f3482e2fbd89b617c933a2d42eb90ca77f8831c3bfc3852b821bb40374bf909695e073c7473a8bbf6ddeee2e60b345cf36f9bd18e47f1aef77ad18eb50cf04573008af206058c22dd7b51e8db598fab324ac982998312ab0f3d81ffc7ca20ba94ca82d441c8438f5aba99ac8fb99b25cf19df59c575958dbebf938a573cbc58a24836f8255863e1dd9e9728965574f1fa9d20f4c5dd659deba21de1a33a032f4a092196226249fbde8d51ed6866e5b84f29a995d2f3bee02282cc788efc95359d8f5e4161d05bdf5728f629fce15ca1dc1b09f1484c5ec08bcc0c9548c33870443bf71b898ed5cb8f23f1cc3817dc5fbcecc68d71dcb577b5ca4d10e6afc069264cf7e13928ab290dfba0212d40890011aa18b7df4d925c253672a833466ddf282789b1c18011e9f1a13235a246585015674f3fdf6d344bdab706177cda166906261f852693cfd95107ab0cb00808b5a44c94ed5a8a4f8b9cdd0190b9932ec9e51321c11b19502a24ed0f3c31832ef78de9d9736fe4b96d1529673f570f2b91af59842d7742e0a97ccabf77525e9513a15b122e82a31ce86df83d456e7d6e90e16fd0a472a4dfa0cd79553306f8fe457d83e21c63c495b2cc4a9d89288ec0b8e0765e95b9a3bf9e65196274a5ba4164c501d16ca2830da2126c98969749b1fcf735578685c63dde07065f197d7f9a255449fe5566e500bc5014071423a4eb3a75fde60015b4dba7fcc83d330ed52925b155e3e532dad2878f7ac4a039f35b75892224800a85f7521f275120d36594f9e6d6bbd42389182cde5ddbeb7b24e47b2de72c6460272b4fd44bf135128476da43f6641c095a6d54f36da0e5e980d362330657485e615238802b4b9662b5d29d668ec6f24dbeb8376e18b9424271db6a5b7e58327cb99a250d8ae93c2fd1624e75dc83cfc1664f367d133d98feeb87443fb3b169d5c4d0730c138cf43349bbd9bf3c33e031130ec9d1313b4d672fab37b5d1f2336cdbe579876dbfd02beb3464b20545f033a5ee6a2999c150605e0af64313c48e9a05d6adb90eab8047a27260cbe8a0c63726d924720cadc8c98ad3012404dd33b10791284f9382a68bbb3c938330b7fcfcb434292720d9ebd86893268c6bf4b365268bcc1de3ab59ac2c02fa03bb1b82f4a1eb69922f10470406342637d56adbb54f3cc452b85b2cd7962cb9a6dce0c619e3d40be3927dc79741085bb2495a5732c32f758239d1f01640f7f9894376e5ebf7762c18f9c48b721e64a74576cf38bf16da9ca7ddc63e9a5de088c350776f075f8bdff3bb4fa530abb54aafa98b93c1ee9c8b50892d2d2f0a1be25d75947829fa0c77f73f3ba186fc835f361cd6e584fa13a286c5ec9ad94cc9a484e1c6afa63a258d29f0b990bfee7ea49e7eb5a3deffee32bb1f6733caeb9ee75d1cc59352005881a72b9dc4a4bff228498dcb66770b6ad5b82a4b10be040f2d5b56d49e0bfe3669b93d0e5baa1805847ee778b45f4dbcb4486ca871c41a97b746f4af77ff9526a82217257189e47a6f37dc77368760f55c37b16269c607a97c6b4887c38e8c077ad781f74a7de5e7d29c66f9faa871d8c4f56b71db75a174b6b8fe5ff1026edf34bc8c06fec890f94759c5c8ca941aa057b6e0fdc48ecb4bbc251c21d63a70078b5cb19b27c124f2abd1e66d2154b82d7be4534f657886891cc22d86e64f3498d9025b80e77d236184c504f5255bdbd70db97cf44fda9df6e290d5a24844e6ee28bd37edcf9a1fa164457cec8c6ae7f51380124a75470b22c282aec003ca51ead32df5a2bf24f09185bc4dcfb94357bd0d04de483ff4a18c22ebbecebb6bb1ba843a305575221b898ecc3f118469299a20f069349bb9c0f7f307a9a2b15316cc8c3a6c7e929dae40970186fa643f0de72690b041cfd9bbeb3eee0e799fb43cc8394671d24afcdde9e8f1cab9549e9241eda056a2d7d7655053ad7520f7d35e321e34e4ccbe69b08ed3994ab419c32f107337470ef8ae382e6c83839756b234a9f2ae6db74ccb29b0c6a4a4e0c1061dda65ec8767aa0cac0aec22a8cb4d9251f2cabd33234ecdbcf37a59ff5bf05366352df1ea395cffc17f57b014cb99d1113f74a421cd9097f4b0c122d42fbe09ae66a6a386110b307a72606b7860f34ab56f0e6de60f69aec4013e95e6b22f012d24580670d9f3f935408d53d4b5754d0db8da93743851715c4c73a230f29009de75149d859debee6340c2aaf5304c0b0ce6f2b06c911ff3f93bd627a8696c407c79ccc39df7dba4341445afae833f8b1dac9db8bfb71a9443ffe83797109782aea594f7cadddad8ff4ac76bc89637ce1a29e92e211bd9f53eb154989fa00e44781d6928eb7c54d6f6847a470b84c35d75eeade1ec5ee98ceed1059b8ad9e124c68d919f19e4d5460c7ee1af779a88833f1470080c996c30fc1d84429bf88fd15498dcb1559d3ff87ff9e5e5d9f9b3a4321b0d5f74fc2207db66002773489153e57dc1cb28c6e246083a4c6aa3e0c51a92ca9220189847dbe05ef76355c541128fb1f372aeb82f4781a5cc925312c8af5d384323e3cbca6407a26c1509273091371d3e79352eba8a47380b8b46cc78c87facf258858ea22e611ad39b7e5d8d13f5c824cd3ef7baf78c290a8300f5c8ac0efb20caecef3282c82543ed0d2d6fb9b955c7aa3ee0edbd4070d57f38517804788f82bcbf404c392a288f6bb4611580d00fdf87bc589749a4427ecc097c669719e33ed293a574d3c3f7ca0cb069e5ff80343035c70d71bcd546ca41114784eaa1e85a582239c67ffaab7639805bd422f8f284ec5d8c38520897220ee21d1df6144bc2d83af7cf5d852ce9165c73ea45107bda055f592c43772c8460f29e88fcaa23d7282a7af00d9e842b35f09d605c456e8d2b8a5059a2fbaf4aefd8d4ba51fba5520cfc5a8b3ab16b461452f7ff7f00570dbefe2b5ee85e666c1c0acfb9e2520a488e9f3466427d9b573faac44be04ee8e3352f241367b336861fb34eed15c76cf4639906eba0efdfa153bd5cb8c415353b94e314c1521f07f121134a0abbd217791dcd26613c193806f9baa03d4ab1417e0479f409b296db0861deec7a39c2ca6ae4afe0eff917c51b481ba4317fbb6753705a2a004f819554ca10e3268a23cb245df35821d6d2e981a2c7b4e9d2291ed0b7d442f8456b8ff235798a2fe6d0ff78f24fd5a1ef6e552cadb77867d4b625f9a5a610d8bd9447a6a607748fd6f1af468e8f61a9fdc9a35323c2a8bd4853d24c0e00f606a080ff1d89839616d848313d987ef5fbf7a2d9935a1c9ad8109db267cb9e3a304ed47e2c49d96d4e3c00754a01b468f8f288ea6b6715248a7bcef2804eb7f88519c774a85d06033e959a005a7f59b87413d90757fa6e0d525813fe8d7fa60369d1f4b2c56f1f211de91e3b2091ecce8542e3c37471b990067aa2191105597828532b268945b23ca9b83f3cdf8c39d73a57f2e26fc1ba5e6bb7200c94034782a5b99deeef51e38e3c259d8d96ba8896c7eea0cc4c2a2a0d5f68951fcae70b9534ddd68076f9021be471e76e0d64ec2fbf9768c7d1adca54663150b3a0ffec2a0e092f3e91de2ee672f0984625feda97a7b0cf85189bc5a60034b445ffb55a93d224f411e771baca98d758b659679ee669f5f4142ca32a65d1ff06595df0ee8888dac27a1a099765654d125e3d9759e1796763a4e2973d7e5c4ba912ac3f865c0ac59908bf3e83126a7c34fd663943345c399975a3f7beef1e28af64cf4347c6fd5128985236df8611289bba6f30ee37e9e300507236bfa8455b3876e96dd415ec470bee0dc7a14ec89d02c635f5e5b12de0fc7b7bade166b57fede7705cdc9925809da8bae74dba4b311a56dbe36d0c999304c9c93aa522de51e294716a72cb815b1194f9f179922007d2facd6faa8f94ef795145c95b6562480bf204fee02fe2151d7b0f4b132f52e26895f9a809485cd2b248ce872e79529802e2a4b31f0d8a5fb8de7e35cf96beea627f50edfaeae40b9875907210944456ab4c012542fbe10ca4ae26dc0b0e3dba7af8437c44008297f17e54656e690d930792d9ce72db0e295d4eba8ebef2aa7f722411b2594523fade86465932937a29c4cc4193ad4ab59ab1073e62e9a615a417f3acc90c30a2dd1f6c49ae698da3236cb409ce21c50b4b13174165ed531309749f44ad6237235e6e8af42f917600b79d3fbf1302fadef2a21cacdafe43549813699b0288fc034d6475cc1345a5d14159108aa05ee58dd17a342492dba9fa7cf2f95d59ca1e2f0de276a5c0a87c56777714b3bd8871a1fd0e77d6072dea69db0d5bd651583519289f0a8559f3d4ace8e43cf757b20efb70eab3b9a23f0a242a4a2e99ef5364cc4dec76853705df3cfd672cdc751149164d89aeb4dd101911c374311e4cb24dd4381eed07e38f100f8b69c9c577c63f1476c30b47d4a337734796d4264cd54224e0eb00884505062f7c220319621405eb3e3861c3a8607c4d27c8be856d7f98a46801b518511e3925926d270010715b546be1b28757a3f97516eaf32785a6bd7d41efe369516254a94571e650c44b9946a080bf384531ab41f92f712d29c2758cb5e8bc6f6e00a9d16e4f80e2f45a27c3c08c2daf5109867352fdc72358fcadec421f93ebc56a3bc263fd99fe4e5bbd3116b515323f84b26f241cee4749d902a4713e68f6bc1e62123f2ca97ed21c3dc3d9b3ffa2bc27f3b149f8dcd3cc7d43aebe5b3b9cfcaecbafe99d86fd81126c31dc011f95ba4d83fd199c877239abd435c71c94af3052e0958ad9c39dada30f2a798139c10e863a379d87fa002caa34fb884a5aed53f7a5fb8c924b6ff83ac45369a6366de1efee0c1493438368f5057c78a41bf04e2f88ad99676ebb2e84b83f6988281f8510da122295e681ede56c417067bd8d435517f417d9626f78d4644de410aefd30ae3255d69034790d573ccdb121f71a8a0c0d659923ce2015f8e464e42c30b31cf32bea4afa71adc2845dab01320853dbe337b6dd142598e5154b3f1eb3ad477d7c9ca3f2232ff8fba42a5c9d4072f431c3ea5cef2dd8e6589543f5899e4bd4995c4573c163461f40dc9e974d0e167e3834ce3bbbb56ec748c9fb2b6aeb9a673f7fbf14f1839112b7ddc7c2b764df548c05cf5aad6b13e5ac6ccdf9507f0dae001fd9c8bd2b2e5e0247ed81cbc17753beee58f74bc13cca4ce447e10a360c15814cae5d428be317d0065bee23b8df536d40f5bb2d3661bd6dc531f0f51e4d3f21853dfe6446bc69a441dd42979b8fdc09dc7f2ff34bb980dd115e492fef2e07a106a81990d5cde298547aa6be8e89826c8149e330e92f0378360e3a3235fb4f445981c9d63d14b22e7c1f9ca9dfe6f5c3b16a90586c4026cbf3eea59beac79daa7b55f7f5dcde9269a7ff5364a7ecd3fc99228abf21bf59a76c8c1ff2d1998364995e5d744a3d08ef6ed1776de059c2a3d33d1c92a475f5e59d88aad11fe5026673e932d01ea59a94b26f40ac73f5c46170ecf1f28ef65d6d32d686b43d394c35095ba633fc2651cb3fe902584a1e7e9f83f0f744697bf9d181453f43933a5cea96f1da753602072470a88d4bfc35ce229eb1d8fd4b07443bcbf629f7684e8e77bccc2bdacb668b9cb8d93095eea093d166311fbc0da2351c29b5be08676a741a20f4f4ad299536ced4a1423fd6aa8f1bf871bfc3ae75bcc82b26475435c354b00f0e6de6c4deb82ae6951546dfafe6e60002b78eba1c4ed32ad7ca5038c492cdcdaeef27a635f08cf38d1f5d9fbae7068ae887042e45ae8fe7c331ca7d065e71334a3d4a90453430d4b522ac79c4de7a52a665db3f6ec5ce8a91ceb827dc8818bfbd8dbb89581dd6c2f5069a3f19745360232d573041fa9ff977b311d151322abb69a1d9799923e8aad92b1fa0c4d34e9be9db1329e03618dceeaafcc67df3a34dd7590edcca70e7779996a91919fffa43576b7e63cd2091182abbec730604b78ba032b9181b68df9c699439aabf7d64822dec6029e1daf279ccd7811c4ffdad7f544a83c6d97a9923ab7315ac1610239c0389ad859ef3b33536baf37580623e467bcf69201ebd4bbc52a744de8c58e0a80273f57759dc67cfc9fd309d7ca2d59ea43a9d0d662d2030475143a2b8a7b269b340ecef9f4cbac7d6c299147511a30fdf378e4edcee8d83303e9d5ea6a47bdadfa57a811ac88b4080326cd9e2dba6934270ba6cd022846c76c4ae475107c2a9303c07230a7888be10ac969f116e5bf47734356ec1a83b52e58045bf8b33ad379eeb0da294c9cf5b8ed7ec14249d6fdaed26f66cbd43c8c87e3b6d224d1edca8cfb545dbdbab029394be9b7cfe63c49ceee82046b56e70334cfd5094a513cf7259918274af924acd32b34c383b7415a571c7da76a1b9abf59d944e3a741afcedea581f4a5b38840583db428270b6524c52622e4f32ea7ab4134e22cf7cbafa7a6e12cdeac945c44b0001704a559b77af7042b08457e29eb7b8324e7e8dcd9ab175cb0b363b3796e5503f1b6dc93b1bf049fc84c1dbab9217050f5a148608cf1220a5606d1dac88c9c9cfe44764724ba4129d69d8d37cae847da6a1d56642b89fb743c4c28a2373830875107aa03a198ea1f71182a404bd3f4967f8dfcd6a62bf2ac7ec564fa70041cf645b85fe1c0fdfa78cc3a5e8e77b73b86d9ddf9b5b65f15599bd11bd03cd8ca9c540c5b4de2148e00a10ad7ef38221990cfc491f835391ff6a722f377547eb9397bd753b901715e1d6dc319aacfcf6fecadadfb7e92c43455014feea3d133b51e08f5073967e945fb793bd8283ecd821f168097557d3bd372c3fb53f35fe6d7321ce42f917aaea123149cb2dfbc88682b4f05112de3c77c64347f6b4413bf37e77542f78d6f4681b43fb69f5537e968903dc7fc29fd7917eadf4977bae385a14d6a9d789f06a774543138b02e1f44b6c05fe1046a849b18bab0daa8a605a435f5cf723229e5b0ad51ad465c47ec9bb35e2fb9ddbe8244a0674c9191d913d7ce08420b10b0a76e19df7d82582430778fa43798b326cc62e19c97abdec2b364bdd9e976a170a4298b74a50a0c82a0e588c1e0faf97802c54942a1620031fd5b59e86fd095543ff4f29638436f6f87d9a7cc14c8ca792b5836e8046c576f8aed833a15a8c9974b8d28b9567fe1c4d58f1d80ae4762df63793dfae424d746874c6b1659488df5f78cb1fa36de9daaa8421996753fcfe41194ee7a660dd9e5c7a0e53d09133c27af1b5f8a35f77601b8182558eaf761ea7f72a4d78f24847bd55c5e7ff866a1a931c9bd9208456cbbc6cb38993ce7f6c4b266661c6d0a05ae1e1b366c8832fc3b295b51cf81470439668ef3286e8a34fdd511ff868f95110ccbcaed4689748cb2326109c5fc09393dac7b8855ec782e74347e259762c593056d80e51d88755e3b05b270900dbb6e7419d7eb31e42e90d5132eefaf0b7c57c96a3ec3290e661b48fe7b47e5b4fd12259dd62026691426d83760e1612cc80f6857913dcd8f1bfb62558b30e6425ce69d19ec42d9436a652726c8452fc195d120c6984d64c69749c49a6e8f0634574212ba16ed93c9605b323ae75682e7c646365e8320694f9f437c3f519ada6d9c0f900268fa3d68ff2e52d4223246ee601c304f97ce3301b52d9dba331a54d2a3daa6dbca1e712516b5f5f27edfc8da48b11842cf6cbeba2a4dd31ebe0a4c72a0193fc1c9aab6786facb03d83c15fd4cc5c651846f2f01e74dfe3dd3f1b865130f3378ecae60d4f48411c35e61c81cd642c51baf1cc62cdbf18d5eb446aa0770f7b20358ff9cdb261346508b9837bdb67569267a773e92f8a66293724f5128aa5fe300587485ed3e524ff8e6de3f52a815403840d33a9213397d2e0958decde71761c24e1e6e33545e9e1ba6d09e7951f53a8f09c84f025b2bfe7c7ecfafead6edf652608afd3bd50a70b71ae7c0ecf49bd009b737c1b727f3379f6e2307ccf9ea8530c418b5f8d2ab97c06138283b41dca1887c7dde594a3dd7eeb084918a73faf9a2a04c28832da89612b5154161db5e362547619dffbb002953b9508655b8bad506b85ae59eb0cc6a141fbc798d89da04e1463788fdb878276bbf6e4b127a35462105533b8279a010c81d399895bde1384ebe0aa444a608cfac59a80addc6808addf228e7711383f68b85a7dfb00fc89a85424cbd449eae674f48320cea4520fef28576edd8b667fe709ac04b792ad1860f523500096aefbd7feb105b5486c8f2d9b7b6ec48eff6b3ce44abcc37093f5e9cad52508faa22289967b9d440f91b115331ab1d9e680764bdea57eae015ac580eef39745dcc9ba6812352843e13f937cbbcda83057b635252f30cc5044824e39ada51d8c65a2544c37fb8b4e64c872fd7531a97242c8379212e95e179527fb2bdc4076df8027b9e56786757e6863de6ee9478900ce4be70d49cc23d1747716da019c11dbc7189c395644c3c47c9c2bb9bc33dfb8acfc60dcb18acba644c9113cf62ea7e5f39d2bfca184d5396289f834c663ce51d227148dff9b7a84ddc2533a39ed84e96889755af3922924c041c9ae81f6bb50a16a732cdeaed1dfcb166e2d375fd77ec23c9b40f02e399562b7a849df891cef7f0927036b28d5e1fa4fe505cbbe8a3ddef80586756d9be09bc0d425f81bcbe852ec454934ae009e84285f3a330c54a02bcef311bebccb1b9a1682bd925c9b647ee1a6466270829be9d7c62df1c9d2e356417e8913b0f5fd2a7f9bf66f11d009cb1718b19059f339d91b5fc4d411d2b0006348b2fb8753fb97d890e674aa76c9b48d8985c01f9a21454627699fc62414eeed65630cc365959f670ec413830b38271d1c11c8b15533f42ba82d35fbbef9d3f6a7224d5e668fb8e12691cbd87effe5a212e43e64f38ae7d510eca699ffd76ad601331e3b75581608898eeb784c306796488f908e84d70468a35da004cab3a37b0712cf578fd106a128a35387f28f64daac3e47e2bb3399a809f11b39484728705a4d5607a6762a2ebda3176c6c988236b5dfcce6fdd7c737254678975103371fa6bc84bcb1cdacaf8c5d31725316204b7f21c9f505455ef303b4b66b382cf0ddcdb53017d8d4f2d381277b15d1b0903607e61bf1d8fda613a00defc213c10f0869cfa6f5a4d13590a17e86ceb5096c7a659696df76f575ce9a9c02b39ed85b9a1b9c9f410ba69830daeb34f0117303df19aab2978ecbeecdd74173dd8f98442e55412950440b968089d964ac98c00dbcff1d1118114328d1ef35acf04838cdbde17f7172a29b3a42f19cf5904a821706e419fc4c554c694761228d80ed0ad37b061d22f81736c6aa07f6f6393154c17647fdd4a1c482cac6ef421e00dbd073d6936c3d122b67a57bf67172929e1a59549dee54059809c3d5638627a4c6588d932ec938f08319b08c03163f2af58e71baeddc94a693e2d21bf7e035b3091a6f101b1052be1e68440ed419928caa7c4665bfc9ba8c32ee8e3f9a1f402d72a0909f8f85af2758cb39dd76418e52b3759e367342e8536214b6589e14c5f0b049824faddfe6a58ebbac85f803cd4c6c176a9c38474bd3b9bf899c6521ed29dc41d41e34fe5141f1792d27e0a608d8910c8b867b5ea1ff7da03d7e048c765348e350a2eb1c6f39f2c35d625bf6b0a21428a5e4c9206f98c9a2b66fbfaac37e5c2478d715c25106b88be78e321308520289f705bed2cde83244e9e7c593d76febb44652851283cc8dd34d9809ed9662f520d07f9098195397a3a3e734b666be488546cda47fbee39cf16ca53cf0425ae7e04f6d5fd335cbc8de567716ce94474390c26245b6b612e5257783b3695e6e0ee14c9224e655cf7505e7eab0499aec59904d19802e6a646978bcb4636db184ea6e597ca160f24a58c0cf68cbfb9ce8bc04fd4b4fabbce674460f46aba66501cd6435fa6df64d250451b5bf51f47ff96e2aac3e273b10a445b6fab30345d158ccfc785f7fc6dbb556347b4707b450407dc6f2c26fa927119347d42703f5ed244e59354fa085c66b3ef96a3e11673d2f9ae697f0777ecacde2b6d0d36edc95e1255f7cac0c610bdcc4834bd79055371a2b017d7736f21b4c7d6f13cd1de169146c1aedf8f1a4c7a71ba838f16d1838de5819d1803b9ec715cb5f248ba8a8db4f38e85f5d4c70633f224f59e9bcbc6b03f039ad29c11d0b6b99af854c00cfd48eb76fbc36f49abfb04630c5913ca423943fe8da34719dbaab1f91ea7750ac4974aeac149c65a14150c312f7f506610d5a6f2bc8de5a437e5f7a06d73d412f0b203097a1914175afe65e08a9d6208ec2384739ff4d48ee442bcb541cfde8f4d3bca27ef75be0a3689fc94edebbfce2da4fd1372f8d261be5f235f6f399e2f2fd430bf5a04223a7b1f3808c27575d3a422edad28e504d9de15e87695267442cbeab2cd645e54a31d3bad7c0025f2c2cb19a881c752a82792174916540e924cdac0a9b23500d82854b11853e979dd5587133b2f2e4cf6203abe0a83a664fa6e3a2891c4c0f56e76e2666ed81d360eafa5fa2af857f55771f0b4d0e4b1ee0e7532a24c4c88e9d7ae2f394175e921e1b2c55cdbc60d9a3794682527bb50e1931eb28f6f0c4257b8bd540969bee6b94f72abdf3aeb2ff4891bfc3201ea8595de57359f5b7683c6e1805360ea5db27a3d0c3d349c5ddc6e9e549ed8fcddf452088c5e52ed71ddf7c214a795cac1a4057b7c929a25adc90ae98ea716fdb0f0fd0ad5d569b162ff768530efc290bdbc2248bffadf6d0f998ec8ca947324b4ef1252f121f06f00fea07f67c75029418cdfb5002a8c9ff6eb74be83e21f9c7c3aeb60491b8198c78afccd58a238a51786b68b784beab740152583e3fdc7746c638c36e8f9ab5338ef2e7c2a21d55b701fd6ff10c0add22d8dec922d17ba9622dfe3ff24331e43ffa295c82dd12625c616a5b8ddd7a7395a58fd934f08a7f8edf5de6c1ddb98120fdd3a2bb90a78738a9db76a4620056f707d43a8ed31163469770339fa0f27d334e0f2fb820d6fdbbffe977aac469f2d7c8acccf4a56935485986deb78261c687ef6ba559e4142258f301f23428afc3075c6443abba0ada43f5b4a9aa4502b42d87643f62e0dd0c852ed228186c541ab51c1ae479e9fe6577e8489cb95039f75192a77d413b1bf37f9ce52e7c7fd01d6df8a9d48c32193e8c1bac3fb20ff6ea9369a89cba4c011365359f6b8bd646a66932d96f979f8b6aeac758ea26e972dde8d2c8c6d919bbad7e48a98e91eb508bd8cee815f5a1176ffeadf89bc1390ec8f872f5958dd35dd3bfd011928a680d939ec6b89ba5ea14321838c17c42780e00d0724cbf7379cdf8e00889c7642ff3a848ed99a46e9797a142da3bbb9fea66d3341130a8e57f101f231f817e39c70981ed00d83157c1256d528c0cf6fc74f5706cde93184e4d64eb2989b0ac2a72a51d2371db3e685b53397d0c6cc5ea018b355ea053b933de580ae0de98600c0c66df33ace6446b7ba39a87cc76839437ff67c53e0f4eeb1cc566c1aad5c7294a5bc9d228bba84b60c5d14f3d9dd5b12229ccafa48e03edf77d7b70f9a6968aba41cbcd510c0ef99fed7c5e6dba8f5823eb378ba43cfdbe9e841ca467260ae929dec9e7d967725975bcb4dcd72c9fe0d69cbd41363412201008db88609af75be250e0088a0d46dbc2fb790c20a836c83a376a60629372625bca398a1b6b825e824e6ed917cdc8fd0105e7a5d8f017ed2fea28bd28b22e0110d99542300de71919b53190fd989d28e4e6a478ccc079cb018407a0913b6d14078ef9e1f20af3ad426e26b41eb7911567558318495e38c9e6528752eafe0876370cedd81c2ab70e50becef6dee24381ff3b73f47ca737acf5e2e9cfb510df29967ba53c4fb5bfa25916fce727ccce0e05c4661e2b6b7c1680850c462c6a8b80360125d5486ec34eb7763a07f860b4eca903be13c643cb3d47818069a4b2d4f665968cb54123a36e3dcd0f9178e1c7375ef1517e4e7dc646da8bade66c904c90ad4f05a69803b5c0b31d816cbbe4a6971b8e5b8432076aa5461d078fe206b035865776084e4de4fc40e168775d8015d54eccfb631820e54b590a419e48c4c344e2d8b0f68f71172622ee73148fdea18fbd42f5020cb463d7c3d079c8bee52011097a40fb3f301c129c0b35b35b4569ec9e31c09812f8f02ba0b3936d1ad399968363947febcfc867f20e05380630d11ddc0c8abf22dddba13b46cdaf1ec33079fdbbd907b2bb29fab37ed5c0970e400d7dc0e539edc02bfdd207a3e594c36c9ae1979068759a625661840760a2bdfa815f97ab5b96530c516b8af8539f498d26712e958f3130a4d96fcaa4a80422172ae8f267e4bb579540d42cd8fe014901cb512940f9b206a73214e58e8d69bb2c8814f999ef4ea81810558fe5e8da997e95417e696ca404426c34ca79ad55b95e4ecddcd87d87f1cbb68c13c809aef06c96e98df59f9c923128c607028fea9c0b1396770d781aee0f9d22ef147075c4a96a488f62686ca7d4b22debd10e4d72ebcbafc2da97f7c08e10326446aa4676507036d84a6c9ad88e1e1b9d171da345f0cb10042b397e162d790d7671a141e4c5e9f64c8334280d626e8858f685708bc5c50c54de42cda212d9e0c21c78abb4ff5f23c84df1e73241ff8832b701c7abcc9131ba63b86bc5c345a1589f92c35c8f47235f43c8e19188edca8ee05de63356de91dc3d25e25562bce23b74b4bee8e48c5f97aebba5af931548743a3b916cbac9fe633ec7c357cb67f0e23921ca4b1afe80255b9a4986fcff944aba7b00989607f6da1708558f2c147d356b305cdf2e69ecab166899de3febd4548265dd5d946cd32c7d8983027e82af618f47459b7b7a3d8b031316e3e66674df7bc190f3f7568eaf6aff4cc965720ccc09ab866e28d6c6f8061a5b7e15626c259da9a432dbbc3564b6e63e8288e6a99585a8a47e3787f2f2f9716c3ce21d1bf3ce1861b88df87b0cc71ffe0c726e85446ba9b5add6bbb0de9dc08c24ada702b3dde06c48b9a248d383440990db2e76af4a6a16061c70c4d25adc053063cc1d175bbff82438a4f80db7406a7d384e57275e6589517293b98ad3cc8b700a1a1a8e30eb78291c84f158e8095048bfbd07781d3e46f037e4f373922ddd05845b210d0e3d89622662b804904179dbe64f24c304a7333528122b71247dbf4092647f8468b7d127844ff2a442edf33ccc054abb83c3d042e9d6a021ed4495bbc4d9ad1bdf3e1e3335f9de8b20ad83b6379ed346cde3375526da5a33a5b62a0ed5b0d9c171ea2362e61266ab4863d7d05b0ab0970c3fb5e55b6cfe697c2be0c12e899cf19987b478535f1985bbf707e61c08fa5b5865742027d1e757935776208bee41da5407c09fb74d839b3a765caa035e8125711c6f8027f757518b36cb83da469e93ede621d2055d20924fe0b6be306d905e67dd350da1e4b7768b7999bea8b18383299a7d502a2c9f1b19cbbda7c393ac468968bb6a15f4f6c252d2e61965e52c911528874354866ffa434b7af615949dabf9c5880c33b9dafdba44ce556a9117ec690f08b56586619a14f05487e34e0f603fcc69234bf8375f81c6c34cebf9bd50cf261744b51d04923647384e0f607012c02131154a6d2d432997394ec709d038bac46d93f51758cfb4b9e9302dd9c4d21512db5940936322ea18e18583e36b6183e01b440ead67dcdd4ae975994ac03ce6d395c89aad5948140cdd1b4a91ec33171f60852ef919c37876962428f7f543facc30359b2830a5e129ef763965a41a6785827add1f3235284242827e988acd458d0099d10e952b4cb4909aa8c17750cedd12359d0800b9166b465912cf87f7a3dd5a48dd3dbbfb221d1e22e14f37ab1d438bb42bd8e17aaad404e3bf4d46557687714f80b7b80a7e8d4e1c1cadbaafdca67d06951cd2a739f26628bd5d3d4c35466ea68a5f246418dee687a53006c178e28fe9ccde6463ad827df65cb74609542c2c585a0d7e12a237cc206ebb4205ec955eed22f4b912a6c087da5de892fac17b454de3de2a93903658dcc4b8ed1ce3f1e32b52d0f2eedaf22705fcca9bf50a2c92eb3612a4a4c55875fc168fe821987022da04a1d96151d1201a4370cecf2466a4fb88a17f1a697baedd389af7330c150f72952b8bc909a19e015983d65f34224ea0bfb4639df6e088d0c35c68826ab55d52d1c4bfbe9347ce622464d4274813b63dc281a9fc03c3e2a48d8054c1d2acfb8f0159dfaf59c227ba9ef74ef97140ef96daa8d95ae27fb55f081dccbc8122f35babb3c33bdf75bf003b05c8902de8d47dafaaeb3b835ad3e24fa10ff6b6dfbf5204f60fefc0d2d0c1c1be04ac0588723261754d71b3857ffd1a08a947902406adb7f0015583333ad05cea08ff3f914b6cf3bdf524074b2a4d2b43363bdfc56d802aec68d12e6da652f6238638f55678c2af765f139d252163dbda95ba71923610065170ae5682a535e571d9ae5c793f8c8ce4cbf62915e15f1cc6d7805c9de4e55d994a24d9c3a218150e90e862cabcd8e8e8c525e3601360c0b23fd86566c42942b306be9a7712766f45e0beecacc5be0c78cb7696821d8fcfe50b1aadacbe35e8a21ed076af2df947e216f978dd9464a6b17c845cb33b8413353776af981ac1db6f3b9d9b358e28f81374857d1aa160693153a9179187fdb3e19503a8749eb47a6ad0176f31bd8a3735ddaaf92ce1c4cdd8575db74ae810d2a44bb69ad81b534bc7ca2b47c5a766a9425163ccb2886727249d9685156175619d30667c75ee7b1695668f00098fd628bb4c89abca867256d401f5bd83761d062553c0f4b280ea01b49df5d5db75cbc56f05f8c3ffcbce73484d45cc23cdab99920bb953ab6dba48539d4a6d67b64bc2f64977593ec5f7fa979755ef1fca0d900928e1c4f2c201d1eb16fe5ed1d76e871ba2a67a5f4212a5bae826e16c0a9df1222d59fe868d82ecbd47cceeddad7870895ff0468461a30def33e0147d6c3872e6d332cc0e4d5e307cc8a085acaea66f204f024b0bcd15181ee394fbc94ac66b65af593b15fd26910f0410810caf3314342b0ff1b8d7015c7fc22eda851a7ab5be5fe2bf130d5067e94ad1ce077ee3313bc90cd66d4f3c05d274b1e1d909efa296720fd3e1c69d7a9e32660c1f45c943421185f4d3d071eca05f2451897ab0e447d1cd4316dea2d3619c354db38de71ae6becec65694b4b33c2036de8556ccdc59c3cc0800d6f86be142e4d89d507226ae40d0bd0ecddc41c1bee0c5c04b4f3b86b6a75267dcb8bd74abd9108eeac5f47e805c186f0d5411fe68c3a53b94ad7865a024551cf869f855c3a6672869eff1eebbbd7ad8d4ca3dfa6307c1e148cbd72c922333b4c341d80a0ce869fef0f9db4daa71a18ab6adfda08c8a10c534ab6627f6389335f91be1f5c37f5ffbe51922d4385e6925becba1543569e2bbc1ffcc5c86189c08d6f212ef27c99ea4dad51ac9e845d388df8e6147bc5e6b2cc0f56b3493e1838ffe2507234ea27b6e7dad695eee020ec81fe7bd8e7896af229b0e422b4ce5ea933dcfbdce812a45fd33013ea3abcaf71dcf351d9526c493124468954bce8cedf6d073d2f03392d98a3941397c0bbd56a4d95144ba5c2dc95ca8c695589337cb6aa5a98bc9a8d2cf0a9f9abb34873cc2ec4e68e2b43f65c4535ba7b540c58f96f91c126e99fc123401654be81cef27cbb8ca019b0ef63dd77404e13753b8d3b6b43b5ce1f515149f0f0a5dc1c20f3edf6adf6af2b6e804b2a8fd834c65621253077a8b228c3570f57afa0e55c20a2983bbab9c5a4cc26696c82034cb2bdad13e572b3389645bd21c5b8ef07dd9a0265102095cdd9340b549b2ef45e4c035735e8df77867db200174f771a7843f89af458b3b2f83b110e9861cc217f6fb142d8c7e59bf71280142e5eb9fb47698003e5737d8b0411b64c3af1212d863ee942a3db140623de0ee2377bfec2d2efee25e5945a4c5a676c234d3b3365bb0a8078862e26dfd149f0225bef4c396e8492a6c98f03724871e880f354202daeaef4603432675af0dafa72edc51df6fb32bedee7ce74257a040ba9024f726bec42f643095b812c56e09c646526c3d977c3f640953f16cf66514007ec5c9a3984e006d57e7a3c8570cbe93740f4ccf6f4291a7b29ca39fb378ec4bd181460afd8ff31a7f14b1a9d8e4fe756d03d9d69e5d5ac3791244c2b0eb780b883aab34fc1b878cdc2907ffd0b1957282315e9d335abbe2b6122399be8e018c5a537d6547c52889b39ca6075f2c89da12ffce07132266496307b3a6dfb77db4f3c800dd4c02c1ecc65f4c3b8033570f23181a3f084d896bd3c39345efd9e0d1d54aa100eed5916d1b4612cbefb7f0567b22e7b29766f14d4172e68996e5407c23931577c29103545075eb01bc9ae78a4159e0bb4ac72a2fdbaf21166622730807c9f5a88678a1920cff8d118f5700e3544b0a79491db54f71d8d4871484c3c5a326c54a4c9858e86a9aa2f8729de9f476b0210028574d2ca01c8e41f1062e7f700157c411f444745d7852433505844e8b238febeb8f108e9621822960a5285b81c03a63ce4aa9b8b96f0c4fb98bce455fd75753226981ac6f52ec1d0504a45fde3abd2ca61dc7562b8b77a42166148fe39469ca343a837d8be1040a0ecc7b70da5a228b538c4bd6a7a8add76d9e94d565273c437017dfb5be33b96040a295647a1b5fa00b0c2d4ca4235e507257d3b62b506df92f0a709c7af485f44f55248d15ca3602d5fae0d5d0c2cb258b68e1404ad8e20c4e27ea114139d8fdb761409a74963461e2d226e930d91283efecb10e760c5e6905ba6bcccf91631d1a8ff62b3844871d0f128d1aba476c752e569c11c7888151a5c38619239507ba44804986278fc9e56704ee85b1e74024ed0c540f3b86542af09a78e68017b1b6d1f7fc53de394ef480e6e5217a7a50ba9e2202769ea5afe8d04a42659a4c5582b706677c1b709a7dda8ec00d56ea35978aa6ac82dad7a8582419568e7747d00b7b76c0c254def498845f0e52d31d5f852e5ac26d253236c74d51e19085cb56c67e71d75548d10097ccf3db0f19f4e61a2e0edc51d2c4027c9c547be836531f1ae131b377cad623909a41272975da1a7579c1e3e4e3374cb391e7f23f59a564f383a94ead0b1a8f176171fa343147f9d43705370d518bb485cbc7f82ca0556d01fa32576854d29811b0d5c8dc9e67a793ff2f16b77d6781f393764ea0a47dc1df3cc9dc7209d49bdc0ca71043eab1dffdcf7915f68e7ce76af69e363030d0a420a0413ec9ef50924fe71a75d77a3068ab296b89ef76baff704b73c43ab54877b36bc4f9107df0e37756e53d3594acfe4344d9dae5a7e33a813c88b0f44da896474c6af4cf44380340ac126073021ff28232cc0b2fdfbda5929b7a61855e43313ee60da5ffd1830379575812065e0fbaca1ca9d2575e1fb2052bb533a63dfa0b8eb09a0bebdecb0251989f9fec3c885d481b82e37e7aff879ddbe0389d1615b88a9645b993d0e0aabaf041511fc3674cfc31b4a14e69bbaa3f272137ed4e6085b5f67be3a43a586f2c241ac9c835f5fee824af9c0deda4b909f12c404a9d2386a7bd14c72f60c81227f574c3ff6069e77d7414341356bf55c851abf64f62b5c5908d8a81e40e1f7b4d6a45fc213bc9d3a0dfbce6cc7d018d4149ed1261d1141cf7df835c387e1959caf9e92d5a83f7958c054b40c6274d2652bc3d617236e5399e6518d259ccb32373c3adb0e95e09585a06d87f152e7f0143bde977ecc9f1978be8002e2ed66a030090fbc9a52937dd0e5b14142a525b38595ba3ed5a09af3a946b5a7329ddcb1ee2c8466f8ec0ce8c8da14b6bd2ee1a86f2f19cc94b46ad1c1b0b28c1c1f3be79849be3d4b8b8e5e8e3334e05f24b03a8d02930b58b259a89bf7b79e21be83d8fc71ff9df33baa7f349e9c64eebe4323258ff3145a947d3f7b427f16acc7b0efac998c30362a0ecbb440cd283b34a292851bf38a2462ac9798ae960d8f017d19e46408aaac6dd029f3637fb118b3b7f48a22e701176c2416f51e0ad1ad433b3394418cb109d42e4e873926bf793962983b02b5909e98d196d06cb04d053b2e598f034d31c27594a18e9b8274b56e89e150bcfef33cf261b845adf1c25394fe3da0423a6ce496bace3d33e935bd0e890b3ef90937ae450efb2e1142d8fb57f9fcf1e984c91d76d69eb25c83265903f2ba657ef5979e080e2085a2b9281d24d21a9c728603358eef5b826b7f32ff1912d97fcc87ea38abbe37232192941b20643ba109611523cfd73a356f3f4478c96b89cf2361274eb86197e5884654ddb444d67149ad6aeed58d03e16b6d8bf0133f85fdf82b626a27c97e551e111362e54396ecaaeebdf980272b67be3b3a010f1c422a71bea0ee73c44ed4c4c8b75fb2e2ec2bde3b42b1db13e37067fa4070c618114b5e8b05f7b08a37e09a959bea52445ab9a927fb626e43d5d6abbbd5c69006d5956f854e2d5c91929774889960f930c842358efb6b67699fef254f30a2cf59145682187a20c6cb1358021215a2060668755bf5d9a2abac85acb1478565ed64c3af921f801b6fa6bbdb93fee43009594cb8d4d561ce14e193997afb72b4ee4232f735cf9ba1c696ba52f8e471a5e0790075e5de067f19cf0081db7d0e7a3dc3b65ae52c2631cfc1ca8a2652bf81efb5ef6a774f4360ce3cda0f5aceb0d6c7fcd5d11379b3e298137fc7a5444bb409ab6447065cccb520fbe00bdca18da2326c17a7b5f34190d420cc2d82d52ca60709850383d26038599a7612f373399dc099e11907c4ca8345cf188128d470ef8ca8c18829f708230603dc432c96205cdfd79395f9d2ab394b338b124560abc72a613fb5bbd14b9056b5395db4e0ebf7cb3d0a2382fe3b4d39ad4ad90bac8bbdc7d39fbdc71c28dbe6fe30f817086811ddef238558b74a34a8536117fce46ce941ec6a0702743ff51548ac65e7c99d3e4b8da317dc5db538604ecf28ef49001b8f2d453c65b12a2bae8a2286dc008faaf63e4e17be6819ee29a1496c3fc3499af1bf1b3a4b1f952a37cdcf74ffc6a76696491de53baddc17ce25efc6dae4ad5baa1008dc731fbfca8bc708aeccd8b96367884e9b809f0b7e6913ab401bef3726a10151cc60ee773a5a0c5aaf81bdaedf28e6649334d5b3178870c514534487dbbef9236c062c5493a898b6c59a622969d2fc6c4ba69091f75759b8d1386e5fd4e9fed99798ceb72a65d0b9b5e5e1a95cc1db256e463d8cc1067532ec32a186183cd9ba8d0172d651a9de065027c687b9a023dd684d1a41642ddb205628afcee64dc40338184cc77f45f842cd0f04a699d086c13f90e04bc7de2e1540a3f88a56f453c09870fc602745967973894b7b3e511f76e6390873be6c28dd964ff14d278ff8b362461e9ee4d8b4a258c80d08a77dc4fcfab33c4bc1c4b8c00b2d85d044b6970316a498c9eab1ecdaf3f281f04cd316d8dc73f796ad72705cf53a31ce3f335d03c1a149b4fbcd660b0608da029ad6b13b6bca4ce3dc71a7ca5a106ac35dc727a69582bdf06fa86ddf184280f7358cf83cd27fd85066db45a16b6632d87e9faeb6a4e02588033bb3a39603ca5372f52d0f419f881db3c54bd535d2b52061324498a006df346597127ddd4a1e7b603234cc08224a7cb1b9d84be6a81bc65de57ddd366531aa6a2d6c24e23847937415b553a4399bc8c5f9ad7a304fef532423687ae23536949a98c63750baff1a01b23fa26a234eefa0205f26d0c1e3678ed7eed09d098602a2e390615d57ddaff5d3456576bd2b1dca7b63cc9f3a1698867044d153b06141f5fd39d4451ea84f081422f7a889f30dc690df1c22ef79ee4bb316195d62ea5dca8259e659e0a97382a66acba2b123913dfa997d543e982e19f6c3bd8ebabb714f1021379ec31b337e1fdcd4ea07addf640f7ff7837efeef04129c8296ece0ea7164bc5c7dccde1a3e22120a35eb7e92e130f93b60f8184494526f4c62c60da49c4e4292f190eac21e347bfdb36ac6ec1584a72956e6d87cab2820c54fc14c345f385a4078e019a94c4137c098bb746a1cdc6b9e42971ae72cf2ab3f19570ac4ac3fb2f457a03a843f9581ddd88ad4926411ec5b9603d5598ba59d2c177d9f62aeb91dd145c68164f904d0246ad0c38050fc803287a82c7908167111977294f63078a49297a88d1fc7b3d369bd6a358904a82ac880b632598f2fb8cafe0417874d4343dc403ea3633a61c711284267e437d66b6184a590a971b0e6bb501b29d56c833360866b08515108606466202e48aa8853d1a183f23a3991f58d862ba9dd82ac975ecc4a4c5b90be2c29db61c4a86cd81004742cde906b37f5e5a004f87a561001e75b1949884c1e5750f70056a9e66da26a4f2352694b691800d4fa8e0c0454a63278b8ddacb9dc5c00c8471d96dbb864771563f5e201d9420502923d1541fc3fa71834af6a5c3aab64c19c070fda93c73c15f2ddaffa766ff4eff644ed0c3ab80fd2a4b1df710844a6fa9a1387b94b166e7ebd25252abd59c0e28c12cdbee43c6af3c14c665264fd37ecbfa477973d9e5be9a013d0f9cd0d0437b0f2a97e5f6e83466a59b2e62af375e313790d419f157935852c7665adaaede2177eb5e329628a3a8077ac69c512ddfe43f07aa5e3f34b9c9322c961cc30279db5a9c2710b07fb6aab8972e435ae2661108f297bd94bde3e3e32dc09e7b088193ec9c0796c1aae7ff033fe7e1335e39f4492350bb5c91f4b7ad81e199e9630d26be56d8a466d9599b4b0d789ce91999e7fb004bcbe81595e15d37d85b14b803d9a33711746437792e391b4cce2f6936cddb911e35c41e670bfbf99680c1f8ac04bcd770866b8f67b860cd01cd7bb8af02fe3e1033a8f57239f4847e5feb301e0d9437e14cf5c570d71b15804023d6a42866a2ab2732ee27e23dde1d80d72f5400c9278704bf4d75aed52a9b3f8f0c5fa4512f13f3ec79bfc7c3848f4cfc653449a7dddb362454a402ad559be2c1c20311b22305d5c3f4eec082c393c4f83ec06c17ea1e217181b11f34ea0beb1d9b3378c7feb39215b667d7b47678357833d8982c4ed0366f77b504ec2ea6960f8f876a1bba962b0433586b3b3a088410682e576eeea03b76295dde099220b7046347eab7b69028a702400fb5dcbf3077261c024a58fa441d74000a7c6e0aaa89320f9705291b3254d3e472b9770fcb447e13ca10d2817b744fa303d80d07e67b547b1932a37f70b3875bb5640cc3c1c72dafb964908b1d2df8fce261faec96f7c429c7cbcfbdc9cb697f0bd646fdc21b72ccfab4d6a25fe9942c2f9dd8e92e09459e9ef078b83d59cfc7120f0a6c1597deb022abd71c84140ac450d38541b652d48a49f1d4d165e9cf3e8eb968bbb42c903615963a9998920c50c72bc02992c60ff7f01ddc8d2b72c726c8c5a8a7ca1438dd7203ac0c85e3ee9b72429efda6851783d539427cf40220de80a986e778e3c373d628710d82e0c628ec064b602c713537fdb7837a81084e77de99d17d90e18a4bb2ffd52b38fbe1088f6cd07212799f859ba7bf874d2d5e3a41f8b830e82a5700a3d59c139ebcb98863656f51b0ca03589b296e696269182191cbe9243af6f915e7981644abba77fc8f0eba7e44731ff79d080ec6c6cf4895fe1c721294a24c82f94bd316babd1d882190ab338aa21bf4c3998b49e9497bf3d3795ecf0648a2ccea2bcf1dd4ac776825bb4b8e95ebd4fae186c7d7b488887d2d47462a1af4a4901ec2200b9b82f39fdb48854355c5de090114def5cd6c8888f339a8b2c3775bef7cb8f0f6fa7f880ff0a13dce671a177416a9d953b3e0b8a242162866d03e84843d6c68428a102eb9f7aefd462b0f8197addfeab8abd5ff758483cb9a2f5e4e804a04bcd63a582a57f61b7aa1533dc959d9ceb40ce49c739fd7232541ae15fca1d3e74f9909a70683334b1f78c4e1b18e55119402c1f9be03a33e202db104be174dcd87a30bcc222a06b3b091436ee5e1024ddab4c8ff4ab06734f9b35d952b5f8a8e3e7991fe1b734ee714e23b4926a7927d096536af265e8db55707cd177b34ed0a68d44bcdbfeeb26940282a05ccc47bfad4a21525e83459df37ac1cca5ab2b2d9219e9650324387efa17aa548781eb20f6e551ec8926673a8c679ac31c2c0c716db59fc4316c741568d5a63a25744e76d8cd79f639065e2e7b7379ce69e40d6ddda8838c3af073f705ae53f6aea02d96f26fda4916c6d295f304801dbeda53f4b7f34356964ad86e3ceaffc762139b62e3cf2c228207ea64da2a8308130927aec88acf5b50abfa2b10ce97a1d2d1e8256a09b616462bfa8588ee97118e199af2d1d352c2dfbec16b25f2fbd260b7829a70738622649ea9c8c5f288d17de582a38b120b7bb218ec5b837abe1a777a610ed3b9f29c484f091a546bf4df7c4f231c12391e91590ef0cc26e85b7a2114e051ff8e0c784315d7cac3f78bbbe3caf4bf0f8ab6a545341cd5735f792d24875a941cc598617775bbf6d01e73cd804c863dddf33b0c2f8eb145563d66e8de233688fa1b70904bdf97c56c080f6b3588d8e105d1b2b120dcd6330309e9b6bfe012d98f29ad50e06784a96128a37230757677e27b835163906b2da9cb3bca45bd96bcd140af580811082376c5c1260978ff6d67fbea247dec42e4d3f3a2d91ac5b80cfc9006a07450d2af4296593bb6d99fc47170f51ebd33fd6b55d5e99351e013eb5696229e0ddd48740ae01d70a4a860f74d16aada8fbdd4024dd811590b1f10b367e95300855327af4bf52e11908cacfa33f0d931af6ca00988c62e7a611f49d7069e108e9d50c82e676a965198f154502e92adee89e346e49c41700bb6e9bc8aea0d3299f93b96216b4865aac5ce384586e6504b0f1b959aed541556db211332cc5b4629815529907563b087aa33db0f202b673bc8940030e199feb5327df25d50c032d914641d311f357a83c3bd1493e5f025931cd2e9f05c9d3dd90dd727efca793372b2fc9fdfa68382e5f2f65227c2b819c5c997d8c7555c58e3a4b5cbd7964ac7318f92778eb5e42e0d83641404e78bcdd18b743df6fa53b22e83ab5be0022ccd53d6a458188084e63d370d7bc437ff2100f843454ca4e4bf947884d947c2ed67cedf37254e720f37cec426a050f63cf1e3478ab55847277a1f4c83fdd1843e287c0ba711b9c3438238ae9a63e58510fd3b57c06eb25c77820670c392d30bfa8372f491c90435c0b4d0a0e4b5ed6b2f05597c1d37d41d2481824936e3fb839b7e203d52c16f861725bca57806248633037514d5660a554c0fa405c9e0129a895c0dfdcf6bbfa919d31cea91fe343d478a1079dbc00ea9baf3ced8eaa4bd4e1ae6cdf056946cca87eec86c6da990bc2d33fde5c1e6e4e88e33391990c6424e76533b4d53ba8eb72dd23b9ced7e605d77169f199dc99e9a2cca0ef5e9f3a06dfe01b15d67c6edf4d1940142dc8873cca016e9b387eadb709f3a9d95ecb151c4f5f4ecbd00c8a77a9f16d003659be2b7ef1d92fc51879b00b20b06fb8dd0d7a20bde9b8cda42fea0f540e8ac467d1e6c323527195ba483ef70de2158cd4f22f1bff1239467079d4bfdef6b0a6dc3d6128ce5dcf08959bd391b60e736353cac24edc17047df07bb84c853ed281df315683f74c122ba4690730e7ffa023fdabb38212ee21394be6659156a6de561d4f6327b00927616a85ff2ca10dce01ac73c531b1df30d9a0b251e1d6b2104c1b1390e5b179281646935aec7ce133514c82d164185116e972c744fc0b9aa5bb85081bea5da35cf40603cfab6d8d961ee8d7fdaf60a35b33336c9b770c66cc2e1267b167dafc34a54cf547007c13b556d8c97e8d1153772e0f01324c3ed8b2dcaeff9db122577c853988dfd1344d6d96e48c52a2aac2d4cc39db3d9b402302323da041e616ca717855ba2c6756f59600bc79cd224495ba707c5c6d4b7d92c79b4d7e93494aa03d5b282492f6eab59d3c788b89378ce2aee23873a4098ad8c9017ab8932aedf0ddc8a6d6d0849fbfe41b31611b655644586bfef46de5b4567a6de01edb4a0b7d18d91feb09017aec322da336a253635ff3f6def6892b520ce158eb39fb4e8ebfb536db1ee4330ed1215e5ed3d981d49cbb83da610b8b6c2ddd7258757c232bcea7a59e3713b654997c96fec8ba2d1e9c00a9b71bc07d34e082aeb76aa59bb782b7ac90aef1414629e80a8364b159d793cdc89ffee94fbf3d8505c5c9621b2319b71d55287f9a942d420aece6ba411288febc71034bd6ec85f9cc82d9d54c8e88b2b01e714bdc62ff7165d197e9e71be8f92d59a0ca0e797bc45f7cd0655be2399315118da3416c549551af7cc24286ece163965dcdecc25d748f127a87f91b9be426f22e9ec9567b9bdd3823fc60c33c89b9e8aceec186d85ee316c66fbe1e17e1f13710410b0f61eeeb70721ac70b607183e0e8b5651c4035d9cc4a61a0b3a6e6816bb418889b4cf1e7b442b49b5d3da9511dce60440bf86f4c407d9f594bc29a51f66bc81bf1f552d6652b9d5e9fae236108aa8aee2109d1f142e1e5601c30a75220dd32e34340d305c2aaf061e03e7c458fcc705329d0d25478bb40954aa76e45c6afa7ce816686ee87615a5ba7351abd4c48bd17d00ae3b3385c91e753b76c3447f0abcd61508e914acd045c877839261eb597d1969b02db77aa4f706c86c5e33ae8de73b973ff803c1fbb54c0342962d6481ee489ea3c8bf6381b4789e9975ea53b039bb7cf43337bc5f4eff858d414cbf0368c45e558952417923e0f8c935bdc9225e5f4ce23e81c35b5f03f2de1c5a241eb6b0515d23c2d62ac633ad83c8d19174b55596a3259128ec09d2ca0bf9612b9ec1b43db311fc699b47df30eceb18ae040f7a866f9dfad4d6c4006ab3b2140b36ed0b7c6f56e599ca59f4eab64209339b354348e0c4e81f5aa1056736011916c760eff9acd6e301bc01562f4f152f7c1fbbeaf5554feaafc087d1930aa2c70f82bce030d7ae3c96e916ccf3c43805f62a63630074601dc5e516e87a4f4fdf508b0f04a39c0e27706be51f20fff1f7864b109f80f3f75b88e56d51cdd43947ffa7217d395ec1f952ad05a5741b7bb55510773f0326b9a1da654e58f9b1afc1c6e660e5cc2cbc440a8ce90da05879f84f9b097edf353fe2ac5075488341c49388c4463b0c8730da3bce07b7460f149003061aba37445f29a023128d6018084a61e1d6cf9a76c4522bf95b77a2aa67d78b24168609a999d0b3f8b341ec9fab85279ebbc8129391877b3d760959f98f28e2560cc7ebf895118142a4abeb820d918047af2450d515ed3687fdea7801d56b13158c4966a46f8f8f12504809e73518cc42795ef79639a6ddaa2ae3ce8d7687cf9dbc8eb5307da1064132b395ac26a9c739b4ce823f1f3e44bceb14b33b08985ce226eaadf2e33688814c20dad7a8d4ff7c250e0b2f5bdb1e64b0da8318753273fb55f6ab4b9c9abaf99f9b00f9edaf53b5f0df10f735997b43d69103af3505f5ecab62f2ce530691e3a05c3f63fe67a067535347c031a43742e262a1e6f8b3b940f4f02ed5d32fd549ffc408159bd22204d0b02fe4bbde531f72b8776caa7c3db35c0aedaa229640eedacf63ac526ea42c187553c08f70d2dace463d05dd491a5762e9be9dd9062cd4e988c562d698e2b81b6e2fc4675ec4562af3d0265cd7d1c5b7ffba0b3cd939a5f9ca9385c8aebc2a9609f49116beacb149bf7c93e2deb6107602860860a08ca73db406d2b4c0bf478ded2651f83e0c43a4a80d66949ecf57104f1beed048b80f7c7f6a7347d691229f9d7c63e2abbaa54f48a725fab87a4ce3ac48ba67f1a516cf3358e48d727ad9902f5ee14b5373b5957975b92a3794c171489a2be77f54a9917110d5e83a8c8469f26fbcbe59b42b57bc8cd949ff28af420c52f183e3f1bb1068f1c683395fb5e3b0b8704a977db1e6496b38604fb2d9a15173123646ca8cff8fdcc243c82cffda5e47b38f7a856d704e0fa41afc40ef0b7477684ce22d78deaa8ef22cef700a7b81557c64e9b909f40fb20faf7e5cae3f84d1294a5870dff5078a42ee98dc31543307d5ff04f015409091c4510831de9aaa33e85d9debce196cf1dc66dc3890789adbbdd4317e75a38b9ca9a7110240cde389b48fd349acb7315bbbf2c9724894a5a9656b692344c14110aba7ff826db12d5014d918dfd6c3e5da7707dd938deb184601b5b1747deac2576280ee76fe536af99bf2756d23d9abeb8f0919d572f219f4109ac810d697c46603cfb550c73b150da4c8d57bdea9688a514a9cebb3ff97fa2312a496ce72570fec2a3c00bd6540ac1e88f088cf2d0ffebadcef8b241562c423b12eec1393467eaeeb8ff95eddfb61040486f559e52c6d4c26b55392c1c016d0c7904c5582ed8fd71e085032af4cbb2b62401d97ee84b382e7a6b483458a0261ac5ff686e181b5c78063c4fb384a6af973b764a7de57f1b0d55c54be6551c02d9a16c0a1164b660b03b0220e3d4f4b156bac452eca30bc6a3d98b570302365090bb7c78aab3b31f7a1a81f122a91f02f437f172da7ff7c86dcb3e26d3ba26f3cc39216ebe6fb29aa676133723967c1e4964ee11727acbf0544946210bae2d833b36eadc3bd3c7e8d2e4803996be112b0c1885b34fe9627716586b57778fde3916d7eb0a7178419138e91462617bdb82aeea7141f52bb2fc2aa5cbc886b1a38d8f34823da9037b19edc78686c577520ef29b46bf8d70afef5b6c47fe0cc392d75ab5b58338966ca5f8132d963ec34972a7b0fcf1f431890eb02c8cdaf6c5eddea2bfa3161da0ede8a222ef2a539e86761a8dd01090050e9d1e30abbdc8d5d157284ceb4326eed08a54bd609b2137ad7fccd24da4eb43ab4fa0fe59edc6a1c2fe5a67438375c2846282e6dcbb46ed62363ac6e5aba1fbae025fd4034cd0cd82f5736e55838f7869ca34e2f41bc712ea606f8c1880fc57cfda7e7efae960282038795595c0d734da18b507cdd85885f1d07e1b393bfcdab4b512e47573e57370fed706dc96dd33188658c94725aef3d30ef5cc2275681797f6cc0a8b1fab7c54a012ce34a29e4f7fb428098960bc0d38b017c9789ba29c50c3c18701c74671f8c8052d97a9ae8b4a3ef33fd4a149c40060a50712f02e11f6ecb8268729811810527e2a8187f6eb3098850e62390d72d28294aa7bf51b24fb747565afdd42684587a2a4d79ccbb427175f40678d096a243b29671763d71d3a0f5615bd95bcc1429baa48b88c98fff4a2d05ee268e38039fcf9bcb601d6350760fabba203f367b3bda4c35c3836c0d61ead8e700a69a476c67c2db60b4a763b8a5ddcfd605a171b5f54689e531f76723fe9a5b3e90c677c62f50c8de7a4ebe07cc1b08ea91b99c9ef40c6d555e73cbd0d361021061ebffa981364793b560ec89f2f3fe7a53a6d5d81e8fab44369ad1658cc45c0d058d28489eea10d944143a56e2605b6eb2770779d31961650b85734b5079ccbeeb0ac88cd691f6b777277afae13c1c54fb8b14c46ec130d3f0f9b08a324a76561a45b7fc5408a98d4258957ffe3c7e33667f51eac119b3da1666aba942ace059af28e1b5c8e5bf18ede002d22a87fea4b2cc34d844612deba643a2fd11f7143f085c64aa7872f343a282e37a7aa43b2a32214dae6fbff65b2ecdcaa00f60b756f74928ef5139ee8648071ad292515ddbf5c218c2ddcf9ce1f1703b434a302464572a52ce366f93b4fdafece883851f9f5c3326b10303754982c13f3dd439eb4a9e88eb7d66abedaa396439b381351e23886e1767989c84619bbd2483fab5a3d4f0c20e921a48c4e1e4a55b47bd10a9719889355ea8c453e4f512f97455ebf7f0af74c2e3e9ca99f8c77601c5a316f8b6cee56058c8bcaa1903788bce0724bbe9624d7b4397f2bd959fded2e6292bfda72ba43ba2708f5f3ee66cd4e28d5b94c5d4a9f7ed11a7feba4ddbc11675c86484a6627932b02a2ca46061386a5feabe9bad3e35ace520f962321ece8333f335d44b912bb7554cdb5a504b3bedb1269619a0db7c88c3ff7c26fa6699c34c05d7f04429c117717270e4363bbe002c9d73fc338b296187441da593c431d8dc1916b7428e4c228aa425b8e9a8cfd2bfc8debd27580a3e4697bf1caf66b94a91ce0f69381c06ab67d856d81880cccff8258783d4ad99078ab1fc02d042b09b5e1525d3af8a56b895387be9233bd97a8fcf495637e246b8a429cc596e7d429c6d6bed35acf8025db6b316fe99771d2cb9bfd537f154eb2da5af3d5cf1df47d5530ccb1fbf4ea2ffd2c36d423e4f583ba41747b0393fe57e8f5d4cae5a59dd7566809529dd11490a057cae43c24b4a1a5fa1e1eb58be08b094b56897f4c0d7bf6a8afa7ffa1ba6a4b0c2ecd8461b65a2d4becc098e444f46be9847268069651741f3359d562e7688edb0258273755ea179b4fc949d6bd076633c205d1806bf9a1e6375c31ff7168b1d443db408032dece245a6a6c292e77c4f4bb58c1be02fd554ddbbfb4eb1f4b5af3fc114cd369f2b4beeca1db107e5a538127922f25c6ee5f047c0905ef16f9fb7d44aa218a3e09288ceed63b75f70ce789aa7910c61ce5d63120660ab00dd911b19d006d3547cda5abfa88e233dc1e6a26145329e5ef1df6c4a872232c0bc9f2b995d7b586bed47c8246ad4e52e49bb4a944c64b641d49b0b085e131aa71295507c318ee4b24872631d7c3c69b416e84a6645cc0ea98772652def6d454cec607a9a46675426290c79f874e1f3fd2b640d2fc59d5f231746e4be3d638e0cec99abdd8b8d94ebd2f73ddeb3285b919e42130f5e470164df6eab8664481ced5784d67d2829a8dda0b4e751c2cd5616cc7b79bfd56c385a00f609d102212c7c91dd1095cdf40be0bbd4d3e25d2dd2e08dc528bfd3fe613e962f14c359e4f3f8b22bd4cd24c8142200262dd593e631d4187fba0cab228100bfbc45f68731a326f9067b21310be459c9ed15642e1b7cf3f1b0358b3b338f8af8596014f43a9c1e2f8ce3fe651d38a08443107b01cef79ef7f10de37d06bb09c19a82ec799828929b73c935ee0078196f975ba2e8175ad804dc22b94de7188f4c7ea20b0592104dc2e3f423ab05592386aadee85bbe15e8e05e262b67f1e031a9d6fc00919a334e020fa079e57e258805744bc6acf718e4e68effb7a39099c0d30229369bf2cbd7bc428c8cfadfbfca4177300830fd857771ba3e9391e18ba48b04a7d2d5c502352221542b1c7d31630957d6cf5279f891a81b5418eb3adf22ad731c64ff929e3e6f6d13b46aa72d4da13c8df700072d9453618ea9aa0a25bc9619539cf7746315fca59536203ef62feef2d4af2d707e01e923dd282314d84ff576b20b242e1ebaedd09299f6f16d32aa890ce7b5be5ce25d100cc444abd8f563c990766d0ae2faed19e8980b839d491c9dc48bb6707001cc342745ff39f8e8be2aa5da253e51f5b2ac2779339a0b9077cab664379b24056610fb6818fbfd394d146934c848cd1e6fac67f31c47db47dce9998631ccf565ffa9056546fcff9bcb5ae9f3db662b7d6db999019e28886b9eb4275f81dbb6fa1a8d4569b02c36d2b87100b0581d801a2694307c124c499964936b0d919f2559c5fde6ffe2052164e0d00e2095792809935a712d9e44806ede06703e3ace23d860ac3a40ae1cdff49b93d05b2a4fdf948c6103c7b0aa5d28cfda9662e2215d6a1b2f0eeed6611f3df9f998fbe28da25870625ec690229598e7e83aabd821ec8ab02f5a5a9f2180f3a8217fd7378b47a3859c5bf97947f4fcaf67c2c24bb724b6658b68f633ae99d737a148f377cdfe0391099f366412648d62f801781a9d81827aa2fadb7d752bf3e538a3d6636fd7febdbfd6de974860a4a0458f9abf4a3023a1372eeea25a5692023baf1a6f273eacf7f08d3f54bd2a79d7029b0c7fce8dd2ef109e99966ff5c6fd733e67dabb8e37750465480b408bb9403655ff498f60a4188bf91c3e414ad1298979477809e9e92bbafda538e889bd480123aef85d874dc6efb8e195131c93a6d2a157f78ba7f8b84879670d28c2c60ab59791454432846eb105b89ff1d38ae086191e554b6dc0dcd877e52627ecfbbb550341dba7d3b7c4a1fa93d2ae3dc4cd02920ecd6af0cc0c178204bd776569481f6b14235c850dcfa1e3e3bae4d0bb15a879c4752736b0aece1f6d61fd6b47905146e4572d587a28b0dd51f08fd6166fd1986fb97bf50fb3eff099168676f0c2dd2901617188258ce55c0be7c672b1b171b76f80529bdaaa445c2e277802feb5a807be29442faf2415d8c703b766c2ee6e2736cadf6bdf17e6d5584b2d4d98e50ed2841ea2f51f9b938fb1b662dd5a32c35b9e072bf07e95992024c1bb6afaf0261ae6b32df630ab22228bf190714ad04b3d6ce1a120d9bd42785f2714c90fc8eba588f89bcab3f2530d8c5e366c2adc32007834d5be708faced4865bf8536bbe6e4dc2e6c1a6455f2cf4813c886f75fc38baebdba28fcc2c3be9c9af084533acfc00a5c40ed9043c4430f078f18b4992bf1cf4f36615bfa3b9e83671a87d43a7cdc7d3e5d49b6d114ac30af3256b448d1c2d20692f16475684d0d05f3377906e45ca88664b46275d23dd87e6a7e808cc57007e5dd4df81c599d6dcef03b842b404b418df4c2a7bdab18bee6a813deb005eb1088bc65c821617ee225deaf7f0c531472d12026fe234caa8413c27199d7de02e8edb63fa4573c97c4011f9cc6718133cc8adae143d3b41e7a4f187f0128e86210141f47a3460b276a21ac18bb8f6373262d90028a64e9b250a36df2f8da4d4e5e6d252d92e40f0706d1ed7578d9d26e76611a2553a55ab3f97b9083bcad1ffc419819afb7e2b78f77042555ddb378748dbcb0713a17f4f95c06abd9f47c8290aef3e42e1c3db1c2cc5695aaf532eaa54999c9330b320a50081f5af832e70cc40927d184bc8bfd2401a966a30a470ea3d7fd52bf438abc98614fbce3612854d879cca78a5d38de6a2a1f1c72998ae48c0cce2035a9d0ae3ffe36f98903e04843dcbba28c85c12689201049518ded7b807b7c398116ca33a7099e7edfeecfa26a03a9209e326b784698cffc1c98ebf2ab3a34b54698b1bbf68de49b729f30a2ad7e4a10d1a13e29443f570f05df436d7ab53f0122bb08897ecd171f1de9782c44a19aacc1a645eb84326b0fb0cb99b54da1a00aeac6c4d82681e9a6f2f84285d971255ce4b79d176be8712c7c0b063c3111c060e77723cdc255ac66a108a93dc5bb7f7389251ffe97606d1336703022a973d38845a56245ca4b764a74b9a7daa6a7ae67fb8471975477bd654b8a7059dcee8b2c968fe3f834bd1935833d9bef64a2efbefb05458909e0bf5d547a46d35c087e189d0fed304b1d460f0b0cd209ad66ae6da09c0ffd7e1d9c5bfd75eb41818975df457c869a60fa0599ffd548d284e56ff23ee997e71cb6e9664a2c2a98aa4a96ec1c8235061b2e9377e593e835f0e2e96a4f6d136c352c519ca32c9bb0396d2b07ad019ff4ad06ff19329e8fbe6666db21036b0f75933197d6d8463df8025b2a09d058dbda400673b2850db4975a78a3350f56672e13af7884fd2d3385c8c461033ea1ac236087ed6603e91548f6e3ecc9144669a54e072d020f0ac69e12eab6e5f1cc26cd3af4fd622bda831d3b0643a39c25075e4bd1931046665ba4113ecf9a4dd9d3d510c90b777fe370128624b5210f2f6c47fa69090de878dc55442c46d1023eca4c0ed6fc7765aa321483c17b732e28be317fc6cb5d1d6d15ad6276aa96a4c19c304f644abee1d2cb88fc5d60a53d8bb0ec3757fe0cb26f9206613ca1dbedb6c4c6d903e61288e0256ad58ad07e1b25c7fa85d1dff92541a215c232152cf4dbed4c81ddbb7616ea3ca48e9e8d072252cacfe1a0c825bf1365c8f4393917b462c230406033c685abd9323acd0f871d213a978ed9d469c1f167ac3e881db32ea82618b9e5c2dac37208e2e32457941ceac86363fd2c2806e2f3adba0aeef035ec53b8918bdbccfdf85dbb1e5b426006d05d982444b4baad8203ac8f75fe5dba0d449ec5c0a5bdaef92732da6b072aae4ffcba4999d95c211733db841d8fef80b290f610033f257fa75feb0ce0b967997deeef93a7a60255e6030e70f83b13c2db49c784a85587e13e2f84a94164a79b0957ded569a63ae82dd4e9b4a759c5af4b7cdc9cbb51f40fdecece7d2a8920338a1118335205d13ca1e811d2724b6fcea8de497fafebb5817e09b570ac70ad96e9e0c6b3c587d53d3b32f0f41846611552df5bcf396da0e8c279c850b522319f2b455809fe84c57499bc2c262976d0c87da54089ee85959d0a4ae06226998c67297ab9a8c0be08c34c319377c1fd65d8a7bbdea0d90ac6a9aa21b51d55ed4dab630558a43384fbacfa9ba4c30e693be3b47f57103398a9dc0d0ec1fef0d26312412a28c360ff67ebc80809fce804795b16f6ea9e64ce8bf0fe5fa29714c8450fdfab6ea6181a181af42b957f104eadf16f1c06961bd5e4d765c4ddde517ba59e22c266bdea39a67f3bc3d6bc887116e848f1ec4885111f1d8334f385b4077718598342bd585f0bf4c16e33e59e6ba1bb1f60446347a7f5c46bdfb04a46de1d7431be3a05cd9304edae2fa5d386c3fa98141b2cb69ffd7ab27086cab275577e3be6ec56b094c2e61461a2c8a72d7a6384bb18da6bc78807f933d891925ac9ee0a6389ea38d75a21ce604fc8e4188b7988ef335d6670e83a5c20f01f100b70fadff31500372566c81550b3feca141a5d4042d6ca646c8823508ae0b6c4b6696b97feb00eeb3b7d382ed708a556eb61ee6c942b31e3b0de51ea7d8a9d57fbfee3033a8e91804778aa2dad604f3daebf6f5f704f76f7a3eae2b4ad1b12afcbd6c0a7eaa9dcb89b6a3353295ac3da1007792c0581627695930e24def668843ab151ff4f66afc2262a83487d6a0306730a74a0794a36e87b3d8f6a8e89794d2f01e8beb10ab0e8eb9f0faa089d004b6b1f2ddcc0d56c9dcdced31edbb8ee70eee573e06e72cea21656450e162a2c28acddd0640fec3e9908a75441455108d9c34dbb8d27be411c31abf19cb2cc2ef0e3a50707010b5edfe7e8aebc1154ec162db2212745e3a46430a1d6417604942b831a83f6c454a9956a51c22a5fa42dfc6175ba5066c9b1d66384f63beeb64b837d0483049044ca976299d82bfa3785395ac943658479ec42de8d8903bba732bb6ae34e45cc124b1aecd6d30307d51b08ccd8abf8b9f0e061668471991ff9ac2899fe36ffb4dc742f2ca2438ab846bc52a9c1bdc4de5f5e8bedccd85822d09134ce14bf11a39b55a3fcd63bcdb0dd83320e295a0106645aec320b1440c7fce753464d04e8a2fbdfbf7dca547352b47d1c38ea9633dd47e7affd9f8f7760e3f494a4a8d36fe5a2e49180c71e85e606ace79244f1a84c046a17e606f7b7ae67d23b3be37a4998b8dd3c54a90f13747f613acf20f126c62f61bceb1d141851659922c7d320ce3109818b9f4d3c102c167ec90d620d0140d90be630bfb0a74edc9585194181f1506c7320ec2b940032f34942d51b529cc6e91f4b7da258526402634c8a0edc443f704e3367d1bffc281442c1076f279f70371074abfd244fd62a708b691cd43b83b39d520e239bc3fcf8b2b8031848810c54d136d4548cba0b392335cf16cd8f3f482253b60f629a8c4a067d7dd5991515590fdb6f75bf434c40345077b8174b35d9f518e7bb0cf8b58d672b1e0336b731a40a7cfb3c5f1ed45de4fed6f8a9f46b5c81aec753f74d9c8625b4a827ad40cd340a129aad1f718c1bf4c99fc4bc937866c11caefc8664bad2715ea402bd593510d3d5299a83c4a7e9d77e9e214e4490f2fbba8cf82b97f52cfb627baddbc4ec38d8e0b0ecd345c2c4d5be887a8f37ad12e3cae100dabafabdc357cab385826f40d39b90377e2ffa740ce8a58f99cb48d39f66ed728c691ca53faa0ae96a125cfd1f4029557fc4648a3c3b43ac72d680c7dc99b5eed88770915586999875accfdc6a488e9933adcf7dee39af944e6af402b1306110287d2b5c52e0bf6ca103cdc2e6bcc4f714af2be025858932080448355a675aa0b988db3a84ed921bebdb63b396e76c64dd7905e60d3e92bab15c60d42494ae6dbc201844f359d1df8a0384e1405219bda19fe66a6275c87defc2c7c5d929c3ef81823be1191981b9c174759b775ec88650c286fb0e11ca3c1b9822f8673ed64b8db92a0cc30626508ea40cc43f3a5574529d8fa3269416df786ef8cc0130c1a97ee1e1618d8db6954487d9ff68422adc2f760300b1cb12ea081534eebac750bfae4044fa88e249b7ca8dccd426448d826fccecf5364905463698639acaf34ade27dd21bfa973d2023405594b4828572a8fb6bd3139d5ca22cfc1750eaaa3dc72dd93d2d831f60d070fc47313dd2c13ff2f2af29d2dfcc7c642ceedd85d3e191bb1eb653a82351caea94553696de5122cb2c705ca8112289efe530865cfe3f376978e033e98f5c748b2724108f25e3438b7cf1b0ba580befe94563354464ca471e2a3650300ae3eedeb6ce18f83e6231846f52af375f831ef4e657c75cc35c0b093cee08e48463cab10534b2ebac2d7dbceb65d41d58d862ee7921d1d03e007290a06ccf6fc0711b12ab3b374cbd0f96daddfa822ba021bbfef05547f9e92d62ad7f3e54ae2f1ce3440ad64fcffb512f4fdef59e9b9cb9ee9692fc5c3a93b99c113041f352acb819419a0002966e9aef8e6cde852823baf7243051d44d603817dfc72175331cf3f82dd0b24653e9e173ed179d9a4c570741c00db2263c1ca4fd0fd695e0ab9c95b638da8c0dc08e14e080ac83a8bb007c861855316dca0d67041201d4bbccaef3fef1f22456176dc2e3f4c652072ebc7d6d2ab1d3662f387c8f33c6fe53257c9239a3cefefac66b3e5e989ec2eda8a85716e6cdadf4d28bbb93717a52ce1898f92485eedb5466ffa7f38f6153e08ab2774aef8f33a085008587258dadac1888f5660a227073358507ba5a3f61e57b241820ddf93b886b00ce40dbf0d56590f5c049d11184b2d7c82791604161e00c66528084fe56b192020f5c9dec650f668b478f6654515d5baf3c571d346fc80b1afbc2aa060938e3e13616634b0deda8ddfc9bf54d0c909dbdc931bae1c0346a1b14bee1674556ecf49bc38774b4da0e6e54319aad33bf485b506d3840c33e8eb080a82c9fb460c009275c7000c7a38155f9683451e282aefb5afa1467926565132939e805838992ffa9cd4b697a851b292e0a425ce52cd3085262b6867165035c219ba7a2e0719bb255fde2d8d5692cdc5a585146707ec488fbfac5c145bbd58c8093aa871b25810d0c17bfef2bb6a9e80040d8d71394b52164ad6a3a5d8aa916c56f9f50124940be29fb60b5d4c663233b67df182ca24aeb5a12f551ad3f479c76599c0df6907f0b0ad360285e7fc1df64e179a90789b02097ba2b8b3aa8589477ad8fc27149c810bf82c57675486a11c7ef163fb12a63a9376ed91c33723fbd8d732ebb96b96f7f0439b51b0969fd03ab9956c881a07f004dbaa0bfaac32524e91ff80fc563d9663c2c039fe7f14ebdd10a0269e2083fd93ec7ae7e67ef826615c3405ff07ae38b269119a6d1496a0504c4941bede7990046344cb8321e3456096b8bccfff7f9aa5df37320c8a9932aa65f21eaed1ee3022db1afbc88819760b8b5317022e304f061104fce9d7de471633790aae6a4ad1dd0f1ee15c2ea4759672e5cf4f02f1f696e663fe215a36f1d264c96fa7069468d73f6862b2c0b67a07935aea0f15af39a8db483ad12d18dc0a6174320f1f14623825d06c4321e61dca421f6333e2ed720cd57d6d88af02fab6e6ab92d8357a980223c7534965c3b0f1a15f19572b96406dc67375a23f7b58cf0e7f31ea8be7e3ce1dc76fffc59c4170885e2dafc3ec2129e606718bedfd355ac6855fac8e054dc2fe3777535593f0e18f954fb2e1966fc8997ecf06462a63d5aa114534773109156009d484e7475e87e608f9b325332f5200e68bbfebce19453fc40742072b6eb9d2364185ca9c998332a5debdbd13d6e6d934b8af05afe3592c5993b26e2ec23fb87c95b08777a11d40a8d8260509070d3a8c016c565464340f252a0309d0d959a111d449bb844f810a5ab38dff12a38b439123324226ca104c33037ed037afd28669dceca1d1f0a7dfaca5f5b6416fa9fba5c97a6b7de8a698f89ec904602d25a0a1ef5a438b87fa80bfcdef43ca2a65fe288fdf33b760595a36aed51a17853e1499eac6d5cbf2c0e2e41902d982cb7badd9fb2c2046461d18354eb8fb4c279b986ae85f7f2e52babb08dc2836195d055af79646efce7b8b466cbfa6d3a0f66ba3377a3487ac3286c9d2d8a99553239bb1d23769d8ceb5036dd2a77651c44c954667882e44ae9e68c3aa4e4d543c5b141a22ea6e9e7edaae03fc115684aa3a06890c3e2f42d6d89fc913fcf68943955163738a5d0350421d73c5ac9ee85ba4737ca0678fa503175b9905108351d1c8c47cf1d10e24f609c7646ff6d7139969c650b94e24e1b284384932f8f95a1d3f9f7b88a7e15602b707b296e5d2a74e0e31529f5ba07e60e7f40b9bbbeaf9ea2d30c91e1ee59ee90482e4e67740be24a4919a2b6e16900a75b1a7beeb3cd179e1cfed84e494574e00ccf4e56f5d680208470111e445730dd98a4682adc3c06013dd6c21a91b47e591ad28e76254f6e15972bb779640c6a45e9dde63de6c61c5103770af7c28f41dd5edace9674b2f666dc05d3f89925af2155550b444e6dbf2ac0565d85128de3d2bc01391c7f69d1198614ec2739840c0ad42735882ecef3daeb5c18aac90b22b2d5ea50cd4a8dbfd5f239199e1c12d2cfe86f65a2f1a1a20684b74227d874522e503e5b0001c187b2596dbe1899d0734d928a5f38936a320b0715ae8f137f0937f7d503008100e9076114393ea9ce3b91a06cd6605b4e5a87af92c257c42482e7a47b7643a49a43aa83b5a995c4405607ae9cf430dee108f670d2f88bd5ffa2ef2f617b0b4d5e9d2fd6369a6c461f6d0d38c6827a0c24ceff287cb66bbad51977de622ad9f69fc7905fb02bc70aab14b98876de6864f2aec717eba9671e0a0416cfa2a9dc2f5c125b537ecb5a0407b7e466588a6232b13cea356304838df8a3b35ea2aaa78be3f7caca3dd3cf341b7dde64b3f3e2e21634ef4afd887e48b3c23de5fa1ef5f25de7fb602fa12c5547e019d056b618947fdf4226fb509001044f4e778927042f5761684dedc288574f757adad33b7abde086a069f6ac4fea77db55ce7339809cc299daf1694dc16e4b03c0751dac4d5040e386ff683417a9d497db5e584180e77f6472c9337576a5a9879d76d597efd6a535c6ba211a14e0798c756382f9011d6c2498e0b10f789f2bb2fc79cff6a923e4712f13bfd34cf9cbd6b53d07883feda8eb146f11bba141f47dbf0efaafa23bc36bc6f15ce7de85c71d19430037de9e75f6815bfe8e93d86e33b7789835205c3073db4df9c4c861e711b22288f059335365a69d87a207543c6357445d29c6c5d767c1cb3e605ef0edc2eee1ed91bfd5b4ca843993cd6da3b37327d0322a88990c7caeb288887f2a92596bbc0f7ca00246d482dce29a45b2be31b3e0db691ca1d475dc844821b767040a8475de26060bc2be044c47ffe621e987cd2cbe25f3a6ef1b7c73aac1005a7fc4fe922f9718d113e4bcd31d0dfa417435a9e24b00d8732ed9e7055085ceb5f943991e3db548b9f3678cfd8735dc41cc8f902d6e6386760f36d8f1a7bfce5cae189f4e37dc728cdba9302457ec3235d7b3ed5bf1bdd34564edcecc2bf0b171e04eb6a545b95dc7e828c4b90408c77d48ee6acb17c1528214b9c7f3f17cd0d2a0c28992e05b21e086d35a2700c2da9d2e1eef2b0760dc07d5e05055267d76fd655a7376a3dac716eb74019974689b6662ad2132873c90855afc31f19dbdda2444e4218508c9df3e76a3972d1e583a496b7657b2568f4819ff5e9336e80b5b987110f666653d16a8257eac186935c041caac55d7ebaf59f0b505472b7da80e24f383c48eb61050f6d135d70b74886d0052cb4d17fc52f7cfa6152165b19173b70dbf2a5445b6ec92eca1bf10a20529a96906ffeac6dcf819dbe5c64dfa50c8d85002c582625078a2fa4695a21a521f7a174c6710f12988bc4306e6915fc3f69d761a309333af62dcf3212cff73d1aeb1679232e4356166fcf1d27cc8e90e3358729ef134a5a69a4222bd3f167985f09a1655b7c16ae60abcb0a0e8263d23d5580d5672407a712a708022b1c9aab689e0d7bbe9c9dad40a62f29a3309fecfaf71eb30fcb401fbef46a4d7d3c5fb8854ccd3d7b1b033d5e4dde1a39229f33b3d29c386da630ebe25fda89ffede030972897d8eb2588addda72cb7e6f9d92381578757e931fe97a24c800efe3c819fe484828ec62950e8846fb8733ddee9d7808ac5b3b66fe93088d165fbe958a1040d6f64129a222cec5ac0f9cf6c68cf70b9e116eee5033a87659c4f5f937e5c6cd35bd6be99bf886f99b09aaf19ef63706747966553d0f530239b867359da80a6e40a477796d3dc8b46eee2dea45e31aa7e38080dbbaf7b046be10e7da6cd1027ee1ae99d3c6ab8a0150ad885eb871eafd42fb145100f8da8559be58f9c8f52052c40fae581d14a81c2821519a381355538eb25919dadf6fe542bc5b62193a6a24e66fb97c010ab9243193a606b638ea8a76314a1f3c258fb291e3fc5ce00f0a1195aa7a2dcf5f97c9a0dfa642fdd67b97f2b8aacb4c03fab81fa038e7587e9a677a2dca7720f4b74b943d80a419eef4dc15633ff96175deaf272d70e3cc8690618444e160b803894b4fd331bfcd8b3b8cfa947bb3288e20a2e998a173e1288488ebb3f7cc8305a77de07c3ba2ed03ffeb076029adc403d045e0882c3fa6f12956429472614522e65f7c1d45161e994a7dc52d1fb51b014acd431004c81e8c47bdd056b95e6ea037d7aed33d14d0b976a03c6220c8c6205de26d0cb9c6173255304496d2f82aeee4c07dd0819cfeb1380dd004e7960b03d1b6f49bdc745dc304fdb2d6234216846b225f560a3251e69f69aac6faaa048598dd425af21790c11fb512f7805be79e01a8f5c11e2e07df2f8ea3de1349395119e34e7cefe487d6fb6bce16f51985f4f989a510e2f0fdb5bf780f673122c4acdc193f2276eda0b4fec7a4ce43909820fda747c70793add371c6a5b4a3cb453546181d90946c03321297c75c0140122030b1e385118f29ae1ff58ba4f20583944eb009ba3ffa82152f3ed06be83916432adb2821422b3c161038c14c88eed127cda1097e866f80ece80a5b3eda1b4e8bde72e8d88150bf13c32de31fb9b995098748623eef86639640656374f0790dc6b3f4ff887af29f84dd2b057ad1527716919b5b0dd58b2dc79aadb30e8a355e50e9beeb82ec7d321dbef8a69047afcbc40f703b9a411fb79dde722272b4ff38426a4d8a688c294ce0725f2fe802b9da1f653a1bcd251f1f895cee30f5a357677f67ee4bfe15ed6a84da9be9254b7fa54b9027b9c1792cd87da7a6df4b29de007264cc20ad3cfeded00f44a34aa55d4b655141a4cf5510a2fc0ce6f13bcfca63b9df2a3137702e8cf0bc49edc1aec020448936eaac75b27ef92d3b0b614049e9a2f06bbd53ff64039b213af46bf1ff49c470548af1b90c752fecfd879caaae9a39e438ea3351cfff23080d6465930625ad4af15f28b93eae916162289f7811afa215d743f72436ce2316caff9e7a44c1a9c57a8464ac27c746b1ca5c8757de7472bc3a78cf1c7ec11771dccb29021a23a09d4c45a7236d128c2d2d0e260dcd63395b8c240a315755b0724dbb9e47806fee7bef0043f4ccb3f109326b77bba9d47a85e2d1cb34d9993d3c4149cf41005df1ae6076c22a7834ea93bebfad27ab2c63d333425a9cd8a037c4571069b6b0d27659c44b181ad44855c8c838345f07e7ce98e4a9b4e99e4cfac511c5958ec43548c0d0872146c5899996f1b10873397de2cb783c4528c36ccfad071996b7a9115bb7d4b4838d4fcd4a692d2d4fdbbaaf5cb9432308abd4668f02575b27bd2b29f064b7a9e9ae11d4ea992f52648beb809c6bfcf85016272fc1766018c201c67cc9f9cb2cc6e62c2c4c9cc306d316ea0c5ebca947c953d1cdfe3b40d4415fb586f390ea932e6225e83ff5fe86f686bb2a5366d3b2d8a247895da6195abf01af981a69ee91b6172ed75e375e3cc2f2eba1006e55edb9afe0aabd92e933c95e95294d28cd81487be1723a037306022d477d418b8b22ba1bce94b3f3761f6dc0413875302e2b666970ffadd4ee7d01e97b9bc5dee2a6445f0eadf3f6d2d8ba56bcea0ac845baecc8af1cd8b749928d2552e1b0a101ce00699a190d0dbd8aa5e74ddfdb3f76551084a359056e1d1dba351ff55f189495a9ea872e3f6661b45582421fcce1e80eaa13a0cdcfd11abf4129130beb3b1a137891abace4fe1d4fff38e72232ebd6e88751bdf3943fd055d6caa152ddf7bb69727326dccabce68f83b58896136d4e374a9eb220b2c9b51ae7ce3fdedb60e0053530829a060226b1f36b332baa3433d679abe7ba3e9ec79046bc3a8aab354355c671c321c98cb588acf8776fcfa8267a009a84323a0483adb083b10463bf9bcdb25c99ebc6c04b13e124a5a909c5436e9685b565167c0b9373ff12694dc1cf7c707839f36e7469e19d1faadba11b58f30d95d538f645793883debef1fb1b17c06027cc983b39525ee90617b7ed9b9bc975c85b90a86094249aa62ace0112227e424ee2932f4eab9d6f90dc5c99c1c433a8a544d8fd8cce49ac8ba96ec9cab6614f8e072389bd3d28710e3c27b0a4328fd00dd30d31a34eb43cbfe7edb750d01158747548d58c930091af3158dd1da0b97e3db3c802a37da7d6200fa29afc07cd1abb7e27f3380bf00f5858f2e845fd0840b14367d83f1c89b23499bbb555af9979714965993ae255dcbcf72e9fe758859c283fb3b8f598b3324fd1113b3584a002a7535fd17070f9a695f2eb9b6be069fa4fe5c5eb87dbdbe8b1d7fa7e375f4975dd24fd5e9d92f854bdddc741a8f939f79ac88792be08809948ddf38e316af5c934174fe09b8fdf41c9d13683c17e9ffabf81a1caa97893d0493d3f49ad3800854111756479760bbad09d6b11c5ac1082c0af87b85af7fb994b66092a547eaf5f833ccde6cda2ebe1c428516d7e8ec8fab91a9336bb44f663c2edbe04f21e9c49c21c1a2b184fa232fb19b733ba98fc7eccf85877da4873312ade04bf31ee5567674f5464cad32f147c6695f6b04d5e0f8fddd8ddbf387cea8e374d75aa703d664ffdb1d284d3f54178f4e46e69290a2b4ec41cdcfa18391e479715301d236fe8cd1cd68408eb1ec00746c9a0fff147b71c63cb45d406c8bac63373554e25f01a19ec68b1cb39ac0168e406b5c40c69c08ef3f14173857efed8bad942c69662ac6598e5faecdb197a6582d7e1634719c1a1ccd63c660d0965d6979ace18a92237771b27de496a9a542b49a99fda9a5c4f6f3da6e78243c782e054ddea52887171bc10d07abddfacefc1241c5c7c967a1fededaaad4489711b801d298f3df855a0776eb8f4558fe07a02db8a10c0e6efbb6841b16cbab8936388f210f613fc0f14775729800813859b0d2c4ae3ee3035a7ea35c375e07b6020b5fc410877f4f1876fd584e3a7f245b1bd3b0be1555cf82002fcba463b426fbe0a3d12203e77c6d18dc732fc5bbc455e2e941e024cfa6d2d22133f5286124875c1bd4d57c461e64b19e10582019797434cbdc2d607676988befdf50b7125703440b279d9a195452744bde42b7d1e96f0ca8bed91ad40bdc01102297f24ad11e8e8a51a3355a659fb8b97e21fc3d45043db3748f706f0c11269f01be549bdd73f3a67e8d9616eaa10f5eef309d7e453243961b34baf1e3911da3ce8e77c769f518729d4900802b01e55f30a18ce6fa2d8a877fa31355d833239c2700e5c16bfb3257c9b11ee8151ecfd7b436ef9658d5a556565939b496a31dd6e44bb083a56facd4cb6050b32aa4acb198fdbe3431592cd8011b8db161d095d4d2f6d6e8ed23032684f1b76fc6e396fdc94314ad8b6e8b183485288e248f60d83aaed74d5a416af2ebd03d09ec026b672b933eb2c85c05a1e1ac8ff51887d68806961ed803a3223aabcb04910c597cc7aa89bc0c8b6321ea864b302adef751468f9e878c1f143057fe2f29a647025ff36e42ee2e8f27cd9e5d7611447d753ca7662778c703d3cc45da6e0af7290999c23b7425e8b732af0b710bd5d52f42e409aed8de775a4b9e110d99cddddcc94a9f816db1b4b3650f47f3a8faa789aa31e024c533503daf7e016488c60b61deb67b072c273cac150f84402755caaa9a841afc0ebfa34af73823e9a886b25d2ac79c15b0304365b91bcd060b1cb81e5d2f7827f76d9151171a09663bfc45d71a3fd55af761457f2aa1b2bc84a9ecbc9d9680cc0be10a5748b7f40a501331eace2cf2b198d8ec05a383a4ddf3eb38ffc3cd7c2aaf995df93d6d6fcb7e8b35ef54f8a73ff4dbfcb209c9f8f946265480d5188fb54313634b4dc265104d4b0f8813327b60374f51db6c7b3b00e73668178baae934723be5c6c43d06d1353c69f61668113d51e342cdc8c98a6e54f28ce55ce785b4ea41e81ea9922f371b60d6d709668effa49568a162f219f92c9da383528257efb6f4baa77e594ef4ce59b8bc2d053a84beaf6c137ae8c2579f96afabd2d5a984a197b18f14abce1ad6e1c08e05329a5e3bff89f385280530bc695de7ca2b89b1ec37ae25a0b49d591a98680928210dcb0a62c6480f4f75986b6e65058fac0bf213fe9b6afd709c6f2a872c8e17721803a90c3c2874a03484a497ec7514bea225d865831d2624b41ee2feaccecb96ff8d0a96d73a77b7890840af1750757ce92f2f6dbd3f8c28f7a8361c43782168c1fed4424f4ea2ea5eb9444358e7493e7d41c02e579f16f41a885614f66584c46c36e6c96456207d871657f5ff2a17e328c6028fb011b2c297cd88c17a1b3730144aeb39f0f790d97a050abd10c715d12e0d1e22761ec6c60575bbb99c0951cebaab69fa6ce00cb4bb3488414ad610d2353e34ce4f84d0db60f6f3ec38a6283943b143a4ea5469e8a9e470a2199699292e318b1d3608169e6628a07402ec388c666e93510fbe9c53e5e42f191822cfd4905aaba62c50cf958529fc139f16bc7bac1703c3ab42d929f5d51accce9dd5538d8ee662072f836ed30f54171305f06af0983610af1c5891b86cfd943efc736ca6eece76754eb9f2ab1919a4d313e72eb6f7d077776e3bcd4900377970871bb0e10b47aa90173f227d799254e395d3a9ae24292a89102b65b10941a2030c581dcc72378cdae8ee0c2c0f7707e072421ee8d9ba88aa4d0b7ca687ff596f1d65a9187b491b4886e1479c1795362b1dc37dd97d3aefdd620da27fb507e108f46baec68013a7f24c58d1cbb4369c293252a09a3f99d3dc1929a4d0cbbdfb8ee33994b15bc308c07e2b8700060ad48c5c0da1cc97f5e70525e770bdd727493cf40c8298aef0cfb265561cca8d5e755a84d7e4d06497594552afff35957216e4ac4409ce861611d46e56691cde85bcd07a53ffa00c83e5918e9687ea12d77487cbb8be6f2e10c54756634eb3dd53095d4e4ee86adb384a6ccd7d6a2db3fa2b6dda73afdbde849cdd550ace354ee28e347db15000043a45bccf85d1b1eaf71062273e7eec9501c02217ce46a49c6ee5c7930dca5683c9f26e8867bdcfafefb3dae016d54935885ada734e2bc2ba16caab43587f7a0200dd273f07340154b9d06290b97665262ad071e8f34fc00ac1b38ab0874db547315c1adbb9dca9f12061680e99fc70d59c50722780b5edfec78fc186839583cd1d268fb894dd3144a44a3a2b7e39ccf0105825034a7d1181aed3b52f4de32eda0afd75f7dde13d0ae4c33da42ac54efc1453a6f64e342e479b93d759af3f300fe39e08dc00066f69d33906bc27549927b06cec1ac8f0b35f6a3a70e2a507ed665c26093da3eadf447160294ee3ad600e1d3766bb70d8270eb3a2b55b6f270df7196843422a8970648baca902f10898a82aa33a1a69d56f11df0c9c9554344ceea48432dca0efd9710cc750044e3dc5ea8831b85a9b5bbcbedf7752eaf2f1f446eaa778e221c6560bbe60882a1d37df21418551e4ebd8aab256907af57a2d7f16abb2f1525ba3e3e27193a9d529deb4b5edf8c5310fc7974bc5912b9c0b292e27fef2d20d52f798c5f2e0aadda72999b9ac0d8ec641c9e9a64772b3218a9e9eabe9f37871e7c96a9bb989e936c49c138622619a49f12046672058685545eaf58a2c940d0b945ccf3905136b6306f94114df24c5eaeae4f9b1fc53f4944ad08646f01c3ae6a87e3759b8cb71a94feeb79d61ea34935f50b87161f24df4579de4de44cfc68b792b3a2669305a8d6c32040f22c0c766245c69b748e0b288b80d74fc167165a8953ecee9034ebe104d059dc68515228e2d10427b5287fc38ae95b6767828d4be071f7c6429f7cb0dd1876fef97562ecdfb36cdc555937e89f9886afc25782db2c7fe62c8010abd714b504cd98fc8feefa4b25c0b1ce0dd16677755d1ca9d5764857b4cb539bc07eeb06dd42e59063d7a072f1157107eff3cbea240bb6018818a3e9cbb1ed986bb8945a44783202b6567884ada6e64fa727f5debc5eefb6a712736a851976805f6edbe011fad428b8f684bd0db3d909eac7ac1f0a1588ce17ef25ceeaab22abf2fb58a28b477308dc6f52dbb25082651606047f5d3af69202d01595aa1174442ec48fd6ec9edacb8df34f3f79f3fdb7060882c3881f797bc52121c33f3f88410bcc9a684a85ed09509db3d6512f9662609263780860f029ac8e75f3d96c61902c7cb8970fee26abf8ef3f68597c024681aa833d159eb9d3a482f2cb20c0c6854aa142cce8cd1bfed2d48c5268ce53175a5441f94930dc162d9f6492a500114f3df3c4e3ab7f7751815241eef447872a1dfe4a81650a9395ec77a98897ff3ec2f5ae8f8d8e734cdc0b3687e9ed4da31de67920b993af0a66a2e3240cd53aed33e0054fd7ad7660ff4351d40acb9a419d8e8bb9557c8e5d90e8ed3e10082faa9f31c4860b46abeb239e7e5ae4ceb3f76ed3b7056c6e66b1b227096b92406eaef599af437947e4d106b675aaaf0da704a72612c89b56fbe8faaee8371058e52ce14df096a3ac8072f1af5bac4583dddff1039cc6561c4d050048e5f5daca218deca4e92ac27e85c8efb2dbf2a82b45cd0d1725cb2b0bf3a82d81e612e6afc5aa38909ee4508c4f306f1a2789999b9252fec478e3007dce6fdb55af2fff863e0df6ab28fa32cf3e8eecc4aed597d8389bc5912d910aa499fefc8abb12f443b634537d700530e79439c7c6537b10cf3b0b0378dada319e5f194fde58dc8bd0a5e44d4eec1a9463088d90d77f365761d0488caba1beb37e33d7f2d35237d004d67b20ec0d49553ba30bc7c7752b1be0aa71b76c226a094d45ee939d4486469e1791898c50e89973e6a59be8a96404292acfda8c494ac2f7c400054bc9d23b5778b20a4eaf4b08bf9b81a95f579f406ac37995da3fab3915badd6cc53f25de744ebe5dd477b6278f226e05f27392f44437fdc614fcbfc85457cb5db4227a240987f43e302561e5ea1b542c989eb363696aa5ae3621f9e958f17c5bc00761fcc9b9d45117bd70d7a2cd963bc6f29df8c3bf36b1c8e853266f788ef7a598447fa4be053d90e4686cb8c141d43c03a6b4afceaa668884f7608e030737d3615b1236ef1229fa95c5f783ef12c17ea3a07c30811ba4fa0cd49b51ce38617ec95e8bcb79255f044ab68a6d8fd78b36568027baa016b9fa68084ce769232fe4cdec72911edeeeb152a3f205de02769e523fb1fe05f2b5cfe9efaffc8136b0ef024610723614db6ca4602f858bb0b19295c21244cbb4265d569bc633050280e5a7155c3bc7b932a0b2ae37265f349ff40a48b76df04ad0fd854016878732522b3b32837af8c2b7c07dcb19f9a444798cd4e13ff316221abbf329b71b71f13e93333a3155e0dea17f216d80c93e412f678d09bf32352bda0ef8f8807f23e95db29294e0cde3716b32b10b95073558ea6d756df77cdb2c6ec4b4a38c5b6158a46cf78ae773a7d6059e9013b1f96b6f7a2a028a42c5ac78c1c993207334f3843c72378f73c8b113859681ba96b33e4371a3d61e825732e1d26789656ed4b5ab72af95011780b9c2fbdd7e4918f4445eeef8c5b7ae3ec815f6fb3a54f0418e0bd5f5063e7645160f108b3806d2e1801150e23e46b586f868626a375ccb32bb5ec906cb5a25bc1aaf0c62e7ef11df1a00716d65bf17617985de1b6c10c201355f299acd4ea0b9e19f077382ee9ed6d58cd50097c967e465ab25236dfb0c3d215696dbd4fb80703257ab01ba25642273a9e3b9ffef69d4a1f9764fdf5e6f299422dfbf4468ebeb97dba4e540ea5bdd0e70770a42309b509e34f701c015acfce497c4258318a4c271c6c63d9e84ef7144290e1ecccb5ef5247c81914ebd16b9249c228e8c36073b2820f93a263ca1adebe5f5c509bcd2f8e4f20de8e0bffe8794a78477a40e9a5ab7dbc61b34aa1e0dec0e04919fe043d782ad12dfbf03e9d7935ed5767a1f0721c1754681ac61d8f7a5f113cb833a06bbb4252b7730899722f8bdba4c3af86d0526355af6569de4c641e02b31d1846b064d1b54269ff9e363497ff99a7c1e4e2c17648ec2a3597d79d727bd88c8c7ff2c464b1ba3e5f1b1b539b5bed4edc129bdb4dde96137c78913d2e0ff36900e54361233c4c03471e2a3882d9873b216077bf2a58539038421c9060b876f71280496e49039b6803637a78790e8e2e61e191b30e6f188119dc0b6c0eaddd873b6e19220f090bcbbfdc6b144e4385f94810b6fb71586fa0959fc6fec741f3c837842548ddf70147736ac769551b6016615cd046584bb5153f8c934e0274e424ec9c1fe6388f92fe6b74407c3ec200d79a58ed94120eb700054928cd151a2ed71082eccd76a58d7dfd5ba96bf2f3924aeae5be1fd03660c6812bdd75adc603fe07eb23fd87373301f1376443e1da0148f9e9a87af2b861c26719a000a0d63fe15f5a1ba6b393a27c351069e7ccd80313dbd674a192c28da53a6b61b23674a55b0ff2ddd35209c493015e7c8f3ddbb08637ca53c42ea0ef518f820d7caecc6cca2ade2d5777234022ce43f0df854cc092e6365e3c32c6e1e1ae260ce7819f377dbac8f288a74f6327619b808fcfa9e42dcdf2e269735c84f6beb652757ec077c622807d468e707242ebc9d0dea702df9229b4be9ad405df0657d3111df9b77eff0ef1ed264fe69fded86405ece90faa450a5251201cfa6959f5fb96025b4ddd08ef6cab13011cddc4e519133d102441521c885f2fec5735c859cde80d498fc4248d176d3f83bee473849b62064bc65fe32f0553ef367af5854a8dd45feea52095a577eeed3daee47f767f95ed6edc7bf5b06aa7855b57c7de24331a61b03f2aa62831cd3f37922713964b55ee2de7f1ab7731ccbff2529f8858597e50a03ff2f99551c97b8a9d67c20cdd18dfe0471749b14858e7c41488d91ffa26b03829fe8b3f34aea06236f58030ebbfd6526199c16bc292b3109a94c3ecae116b1c7f8808c8f17d1925dc146277e43e8b959fd5d854ed1522518c2d10109988f27d93963ecf09e6cea1a098bfae7005facdd7e2d0b95eb5d2a7edb7b944eb7b3a19d50bd6fad0de79139ee93de6fb3321c051d2db5f96369d3c6b01f562dc09bd8987ea3278edbd4e435cacd7cc1de4b74d060e5805354ec390889f66acc762d842c1acf327cc62a2a933040a1c378de2cd40718d887a5f3bc50110b4b1c51e9e86ba7fd8f5e2a515713ad924a19678033bc87b5ff49dc1a255262e2065f182e38b0e2a027ae28c0da3236f07ded9c22988b48dce6b8123844a15a6a2bd42480b448e49cc6a137f4d4a8a66344cab9f93c7b5d567230dd5047ea0d0bf388ff0ff33c09c182ac27ce82b0c62b7195983206d96593315b958ed5be0ecd9355206fa9a4ad367edfe18949373683dad82bb56a694d6a456f7b9c5cb750b157dc1da77dbc951fd09ba143e57dd43c10ece6351e21df59338b14b0414a7a737bd87cd93413546f07181ca749dd17d38a279aed8aa9c2f11469c42c824eaee82a571b2549d1bca23e8b7d07aacff0637971c1df6cf44390efe1dc120f3f7c7c6ff3aa1dfe64716a3627abdabb0f384f336b91fd80108ae75cbdfd7e961a293efee8d834f434785f85f674805c137c0ad5b44363eb8e21282da3e5bff270480c17153638c58a3d583745f2e8b8836c82199902c9af424779635eb6e2ffd8d06b2f771d1ba847e8e696fbe460274372299d79048e5ffd64a84d9163eb57b1effb758381c693f8e5185fdbf89e92c4701597ffcba4985aaecefcfdcaa829239defa5803e2ea939316a073ee89e028253629c5088368085c7668e5192293a8c3faa9eda3c74015256baf046e7b57916eab95cb3ec46ffd2b62a19e422249a16115008a96a818c85fcb599ed125fd2f98424751e5c3327225ea0629cbc54dd51a86a0eff3d1ddaeb1ffd9f8465cc181e4786bcfa370f1548becd379f63924af81f4f9931816e3d25d0c377c1d9ab2fe5256467a353b5445d5fcc5db4fcc1c27b28c833b6c0d13f3df8e8b66be6a83a22d2f4dbbafc230c7ce28a7be360af170e4bdcf7e8c2807ae57784f771fd9f96c9af8fd688581a9212b5e9a79211c9d8eae6bc39bd6c4b0f85f5f125ccd6a0ef7bcdffc85db73dadc911af2ee7430e1e885ec1d99fd8e667476fb52dba3fa4e682b6f75a0d666b5ac62d3b1c50281b55120b9897783533be73b83805ccf5636a6acaf3cbd9becdb91f2634b14aae339cc75112868a9fa89abba2f8501efebc1c63df45fd336958173c1b19832c89d3fd172985989c21500a0d293988382a4433aa2c15bc1f60136c7ea71589b668d7319f4ccb4f006a19be79066b6f983fdc55262714dad240dbadce73e8cf129d89fd8c4427fa9922a16e91b035bc9229da3c66ca2f77780125eda25bc04f4340572845c03a25ecf5ce4a268691cbcaf9de9c69cfbe449e09b15a8ed5dff8e92f8a8aa53df9b01de3d77efa7110ad61dd334303b2310957c8db994485a8d1c2f8696472e11bc3e840c166be6d8504f039fa584d4201a6b65c7e2330cddf85e5a09c3a9c2b865df8b12504dd48970f43b30e5fe4099152ebc51833b06a6eec3a076d17c6b389ba18d3add80924753c293b8222f6419bfe45c390ca51d6f4f9203c3a589bac4f7ba271c48d00113d3106906e947828ba4b3246e2bef95be8f6410ab0b4fcab085f2c6d73659adc5204625a86cd131bee62092a4b25511ae006cfc6b31e46b0543a77456d3939e06ca89eb2f2a0eafe2f455fa84b84908a8b65b7cf1d41cf28b0c0c80f59354623c327c0e8edf0ba66eb2e1410e7bad697503258b98edb06a75d60690ac141eb40b8140b3a7ebc783c36ccc81b2003d7075c00dd9a300a002e9771362bc7679e3ffc7998dfe3d817525502fe15856c8f88ddc311f169f983ac51457717252b6b8a96c7b2fdde126dbaa7851a82aea3691b68bf8ff673b9a78cff2e58e7b51866e11df9315ce50fc1311304fcbe76a9922c094ee7fa466f2723ed2a0e858f32b3466ecfbf78bda1ab791e423ebec91e9d0ce9b216c817f0da5716cdd4a66c73d35aeabff298d2b507df8402effc83f9cbc340c7fa2b49def820d76b2fb9b7ac6aba40d600cccdab5b824db1d04fdf30865ee86776f5c2d1e6b52d0966cb993045970ba8c9107d19145a1d2922493094d3ae8d56a83e2e7525d54832b69ae0e11f5ceeda945c96457de2bc96c0799cb7d23dfe2fd4ba1e7ff97344abf08b6c304ff09551a15b1f9a9608895551203f580bf96f7cd3981697b96edf8882f7f912122bdd7b1d96dc8361c1cf4566bbaa9e1b009577e5795a19c3686f435ac589adb42ec1067118ba593d64d666c7d40f181c70facbe8d0ec61d4c48b708790ab9deebb57cfd4f7fca4bf744cc7fc7f8c53aa5acfbb3faf7c404b8208526c358d89de33feec95a245b3d6a7d408396ba902a9e7cb4a03888ecfb042da0a162eb022813f0719e19ab3aeb8964083a97e7940df16fe607d169deb4838590f64b83fc9fd1ca131c28882e632b841ee9957b75ca74dad0b9127c20b1476fe122acc3684f17cee0d29d31763bd5b3f48a3ba587f36711c2e3cefed039d257cf5603ef9c8820de45366e610c739dcfe041b5a12565ff2a41952920bcd52dc2dc45c8a32dfa99d219246c26b5526c2d4fc661a2b339decbdb2e7f7ffffc3e6c8452b891e0fa191925e67671e49f4078e4c2553344930633070f51413819f8ac5e40c1ab0060f132f809474d84f03a92e975dc1ea794850767d6836cf56aa28e2848c2033ad7b860baaef8a32e61ca65c87ea5563a80d9832d3cbcb8ecadc5c796e9ae9fa20f5ea73b8b4bc708f18fc70cf298565fff489735180449849bcfba29423962531013b4356e11e59ff9ca4d7c08ea475bd8b78a5fe52864a309d05c1c585078eec879009351564ee0d4e19df21a9b961ae52a544ffd6fb34a1b55a048fb2a75c1408e35602f4ce4e2bcc8f72d5da05c303a1f0f6af522ea5214d3ddf80fb68acab301bae63d43492fccd9b0c193a49b260034e9a786be54710e787962ac748ce2892581354a3a449d0619e5e787b82710db9858a133d022d23f1753968a95200d62e451dc0818e677eb6c6e0eeea3f1a1be52db5d647f956b5540ddc68d04610f2811c2055f78330cf010c84c11ab8a511c6e0da2f8b04a7870248808c282dae61e05b6af6247d2ad4efcce6d65f18845a04b1ab25605e67ed1f9bec3bac8121e193baa5fd217638d9aa6a437d4ced2559f32655e15be4616616a88b693cc65982e98b766b6b3ed065ae4eea8bab99f52fe10f714381a1acfd56cad54bf0b9a398c063bdfe6e663d6b1d8481d78911a1d0a16d5e7a30d472cafc2cde8a17970d49a3e4f1d5a22d6a169ce4367c9a3a71efaeb0ae02db79d7ac9376f358101997db1486a210587771d89b53e82172217dfe43c9aa7c02604dd8a31cfb69824f1ed0820033c2ed4ba049a62f038723feafb573b8a536fed558fd98a3219f70727ab1461fb42b98d0463b9d5e32713cb1441c4d10cde924e5b8cab6afa9444a902b8a44852bb0ec8a1c5f915579b3ebd4d389bb2de871e70e3d0e304d75cf5d562786cb6433112bfe774ace8b3bf153e779e1fba893461d423eb8b447497079e1079db9f48f2187f5de5da939a7663bbcc958ec7a8bd4446c3de9f9e541412a2241136ef71e63d2bd9620bc009e722adc182431300d0c61b98d91229636209469f0cf04add0a89e822f2001f33c2ccd910a51039d7d4d1595e6a307895c5c2f455eeb2bb99aa40ac140657f99dfbae3ea00e8da484194f301c8dc33f88ad760613413069b910c88fef466e14c89dc1eb72ec1593a9f5d091491fd6b0db152a409f5e98d0b69261326323290dac16fb17700b511f96df1ef2d12c71468c6972f264a45c27c960b3897c39000e53c15838cd487a87111f54630d65d9c2a7d3120ae6c7a4aab33fb5bd741724819879b03a1c5afd68787bbdeb1c4f36fd29c6e0b8e699ecfa2c5293028045bf0ed1041b217051d061b6c6ca72807ec48ca71d70c9f8e0b3175d669efe46cee28371d9c99b3644501d8dd6a07dc65e4eb04b76b25ff4a94f9e044d9def1d3c25f744ca9bc1dabf5e2e046c228b02bad23fbf0888b9e08900793976694e9c51b48776b620ca7090798e2e39b8d186b1dfe18f61d92d1ed7bf7d5b71276ff44f8c6f2d45db6eeb30136ec1cbec7ed6d0d837fac0e2b7a4caade3dbfc9fdc8c6e7fd2a928b4a88b93d69bf1c2a9ee8859648e9d8e370a097b9302028bb999f838efc650413c036a1d3c459df2277df9cbc8e7c2803cd160064ddf614074dba91a1e116523c70b5983ff5d68123df53d0f6ff33ee3ab1e03328d9ad568436e5e99bac689b56dc4464004f503c66d814f876de84dca090671e3765a015764da6e43a9aecb3bdc4c5f1fde7fa1f1d68bfc1c6e5a5310869c85e83ce2f90d46dd29a9e825b3a38917609439e0805635973a0280694f54bca6a3c9b8b57f2439baa3c869777cee35fa392337d75f4f6201bb6c474792a813bee4b7e6b3b74c518b7dc86fb8c2b01cd5daae51ab85c35b939712dafee5101033538f571701b56eaf2d3c3d4c1a5df54c61823601b40ea78b746dba80d22ab38cffbce30a537a0d3a804a18fc67a8abe826be4ad6a1aefe972911ada17d84d053c7ed8a75f4e77c1db23a63c812ead0097949fa9b92f7a0575a1030c74e33adb01de649436a2c16cbc6c5702c731784fe3760cbed314910c336c05212c1159c8d99a144311129836f0363403f457777fb425465f39ea8a84a59b2650f11fd9250e1817003844441a2c453b275b4a8c6519f28d1dff69a18558a56484af28f6c225bf638e5eed47bb3aa6eff5f57f8c27089b6a2220a80806061c498cad2c725fcac4a4761c37272a8eb2fa8a22a950af932c34a73c63c7421697336513843b861e3ef91d20073ae85e768ee3b79bbcc689a2ba5539b95384715de3068b8f0247ba809576301555298f51a1b2fcee5d5a31cb70e4a618bd8bdfad342326c384d4fe9959cfb612e999ead35fcdbacd8daecac371b1f944a808fdf43e4d1ca0f8d3fa4942c50c4851055d7c530ea482af6243b59e62ad4b7db57dc153417e954b2605d3b6a35020ee6b1b4a0dba472b611b2aa57218eb6007c2c83306690e4869712a85336980d1141ae67f80ce4186179a37afbaa9797e932cdd7b1f210adab044e6dbf4957a7edbda0ec657f7facaf1c9ce50a9b48c10626722e4d29843369e6fa372bf3aabe22bd8c02649ef1d341a51735e3367841f4d0738c5a331c4f4e05ac2bf42636e1b5cd346cb1df700bff98752233fe194125c1fd18169e5323f143d56895d940adc888eac137546c824bfe08128106044334eb43ba083852e17b001f0a79b934a3c4e4ce6d73031d2af171a5c5104a5b77d3fe975dd98830c07cbfc65580cd60b620e7200b463fbcd1a4b2e6b2a21f7fe1edb788cf4d6d0f7ee4600f35afefd3467eb440f21ee0a6cbb314a79dc254a76845fe248fec596e29c95c65722d62aafbf1b0f48dee47bc8f85171baa5399c6714346e42a49828e9c74bb60d2e07d8640f111721f175c21f042618be1a4fdb421624f0ce2fbc2cc4fc392cebfe1d1106242237fd93b6ea1bb22aa9f3363f0b3603c4b6b8c6a3e58a0086a40c3ed55ad66c30ea376a78b56d5642d0c0b3646a3c3c02ffffba85bf8d52eac774c5b7fdb53a677039c16ea491f1858a3601fec4ca01ff6a1135bb18db70f0a3306e2983f55ae0660d482d3c171e1ff602b6a81285f622f6aa97ba49ace9b30805aac321ef0929779643d59f2e43d613a753b294997df007bd6707981880c8627d7ef201390cf952ba62291a4226680f6790435a39d1499462a4d409c1acff2a618836cbd36af7e665cb68a823941c9eb510de296196761285e2a485cc0ea037a0fe895826f90843afd560853e46ac2bdc05dc33f0019097c911333ade61424c7b198db2428d42a777342a3ab5a48af81a86e785cbabc71cc956f7d077525562743ab3c6ee64287245cf7020eb049a2a00631125f9761632aaace007be6872762b360905bb70c882ff43b9c705ecdaaf9f0608b13805ed64a44b2fbb8a4c9812ba9c067726d6abc139aa2b6ce1913bd8ecacc7ec32f8c65c0272c3435d5b2a8e5c69ed2067467cff5dc9e02f1fafa996c7dcf50e3ac675637bfd8982794e771e0b04bda2674c9f6ac9253f30530240c9f79f38ffba9fba46cb91cc3458f1cc6b055c9640ebc298b2b50f27258d3564b4b7148828633d5c3e07ad153a5ec2ae9a8733291e2521497082aed058b681be41b40a484bdf3f84c7c813280dfa1a417b9e7c33b59bac882a166887cc46ef506761accf74379fcff500be44b94f3e144675e5ad808ff7a4d58311770e52d130bcaeca8897fb509055a15cd76ee41fb4e60ff98e3c2f6c9182b60c38831ab11c018a3bd19e97cadef3175abb5f1eb2b8c37879eeb95eb1b5bd77769c7402d1600a2568039270f605bd1647ddc25e3a5a182dd4cd64a5d27cadd5da1cc3e6bfc96d6ae65d49324c473a4d5474696d5d706bed04cf36d032d27d8c59374bb8e4241b762a290ee44bee3434bfc0d48c91de525b1fe8512004b5f6f080e045db1f75b30bd337350afc1408d66a2d1034d1065c84186b6ef912660eb6629153af3fd38b756b14b6c5d2bb71023898b13017ed611a997edd21d3905857da9af76f903c52dd9d82d5337101073fc4ecec1f21d48e10e98dd33b6b725b78a2513865bfb4091e5241529ec3d6e7edc93017dbe48d8cff526ae0da136e1194f4cc0cff9db8b93cc074a5039733c43042d14362ab3fa2b6113a7f1e30e6a5f9116e13312d8c547a73f89734281dc746d053773181dedffc7cd4e918b32afeaab03dd49d3a2f81a86152b679395a7568cc03662f8f193d29265a696a79d361271207a0983c5ad3f7573a8032c62fbc2b2cc5dd259ce95e49495bd562a1222c7cc79f800321e5ddd4399cb416b5d8d85ab4384c5cdd8463a5ef19b2a9934869f2c1aec7dbd32e800dd60abec5445c032210485c801c20f35bb62358a4f63dccfd79d085dd2198964011cf2af741573da4951eed0f332843407147b55d5bb013632f258d062717c03ee89e394971c01a2f71de934fd1a54e180dba2b595aabcd8b9f4b84695fab05941a1a36ec5916687786e87a067e028107016cd2e1159a576343615060e9ba1278743e7914a57513c8caa4a1c399d17a88efbb27dbac8462b428aff79709dac3064ba7f11335b6218e05ae6c8e6d9e35684183e98939e721cf057d21d04d5dec68b887b5f875d64289b860de76274d9a1ff7f09f6e8aeab72491ce75f517263ceccc868aa08d1ad2749672fc710d1fa049a30fd8378e31d399506ade047a6baf67eaf74bd2f0dc2aa26af934da16858113a5c925d98603e55fbf9dcd860b9dedc4e05f0f16707f18e35eb310e87d21fe5412c1a33cb39a1628c404edeab79c942b5342643600084a0b504b6036505d65c8161d9064a6707234632240c86570334ff230645a82c58cf1e067ecac0ebf5ddee4e71c26067a0d2fda45bbb5fb8bd07fd42a026a4c3eb0f438cbf3eb44454087c1f7563e8481f8ad7e520333e2ed3a9e9e69974186d477efa1640a069ea1d9e2e9025d72ce3565132660f9a43095aa31e4ef50cba6ebed46a42f42cb710ef2f81b2a7d9c09ffaa47673dab901ace199ae3efa8a449bcebd863e53af8b55bf06cff2d067da51f89fb384e44158bb347ee5588c23c14aa09827ccce8cc672da79b4edf222a460d7d9d770ebaf4b5966c9a5d377a6752eaa5f5fea924ffb05ff05409e4225f4f3017be4fab896e8b3c9cac5be0faa796e3824c25206fc8c10d678cd8f68ac947abb9a553c2239f623e71939ba6826800ccbe639e8d528df5876e32c4628b8c97b3eb9fbddbd93fcbd3d22ea57358cd068fc721066e281468bf1394378593358836e74ac1744ae013092d99b84269cc03fcc845e553cee71a1e6261c67346ee82f1f96f497bf70f578926db10d7fdd6e2692e6bc07fd574df9041a37c28e6a5e788c3d5d6908e99b245a73c0d62d273057b9f61302f778706a89597ed0a0a816af89bd15188853cd4577c25f67502fb9457e529e1a3527d4bba60fc0b11d9884b647eabe6c4864161528e9c1b290b96aa09cd5cd0c38b877a1ffd8e76f259953da256b61a3c90dce5704aede52b5802a6b46122940185499dd42443da2d6837b65c6238e34addff3ee887d239122a0f79800e88eeedfc645f2e3e148ab72f8231c81c97f9e336ca3e1145d20ba2931295642e0d4e30f7d0f3fb92830f5694c56a40595491f62c51405ea362c4862f4ffbba77071eac1cbf489a39b2e2a9876336e2b6d33d9cfda763675140d7c11498410fa0e30b213af4a81b988ff628b7ea7949bcf6a7fb9198ada3294512e982a77363966e69810243952c076156a96b9541063e54e0017727da814089afbd3e0b276fab7b82ba3c92ee86247b9d992b8a222f99321a8ddc718b8a0311e47a4f5e5f7c1ea2ac85eeaea0a873165485436f14990c9446b01331c05a3755c57a9f9d3d999f879d5cc5a75dd191f97305acc5c265b7bf263b4f17811d187b70cfbb804e62b9029a532062541acfb69ba35a59c740757c33ab78160867884e827c4bb3611a0eac9c80ad98ca9b0bf750c91ad8a58cff3c406868c2ebb27eb5160d2ebf19cc94425b3ea41634493d80d90e296c4132563a067109f1dccf637c7acf17c7fbeb0bd26b19e6fd7c37a21664340583e52899afd0ebb12f243eb69d1ceb63ec69b3b9f6cc944b07aceaffef99b0884475f353bde225ab02b712834fad81a558913a6f73ab555f988718573aa8b2ba4b393cce2e6b828bffa8eb58cbe322a553fc35f2f90ae6681e62e38646222c59e8bc1ad600290e61b64a10205d72597ca74c32232d6080e7db3a2a9b826431e68b2580529926f952c63b9be414777e400ee59fe211f5e41775fbc3752b2a1158bd7b9f9298e3e7aa855b453933fa7430a5340998547bd0d7bcd577bf751780de4d0f2a668f62c09a83498aa74ceeee6892d71a6ea4988f44eb6fbcb9eff023e2ff59e78e3887d8b32014012409dbc64169bc5f9d7ae0436d2132bf0d05f4f9c29ac643ec840cba89c339cc7dd1f4a710e1a12144ef716b4764bad91397a12380eb0760f4856cbeefec51533e9bde742cb8515323ea653cc6ce811436ed8c4864656d873781a030d7fdaf18070150ef8fe6444c493ed16929fe5c584399ed3a5724d488fbd75d3b358782b922aa3aafb8ef3b5a7d6c46ce58719da2d56466d28cec41b99aa0ffbf0b4d5eb1912994912ff74ab8833f837a0e8b4e4a8401842340a17be4df65bfb3ff4717876b09b0482f461ba3cf92398309aa5c0ce6c465a51222a45e42b48792cc6a5f5c0f057ea9ff48cc81e2e3951cf0deb4f79271d96122a950f9c53e19d0218ec87178776db663bb43332828a14ed61b1236eb4310a20908698881a3c6bbbafb25b6baefc4dc53236b638f551191ebcaae9a9cb600e07ce14b4dfd08e17597f691fe3050b906b90abf060ea085834dafff865aae198a4d5be8f4fa0891daccdd050482028d90f2e65d9a19d2ea345818326bf9d47914b4200e39a33109fdf796e5f279985d6d7e3873075c865d093bcd2e8b4ed2f6404199a861fd285e9363eadf8113386ce118f955b7a7e736e214113a32ebbc19ae14a64923a09736cebaa57bdd4c6f6540170afc9287aea15f3bab2f4dca8e3e402a0424d2a255616260172a6bdaa78e02b98015ed8f78a660f3c8261fa449d003f134e580bc8c24c659c9a25e05431c114b744bb86d8a3f59f748f0de6a4d58727b7d98f96fefb9e3875295a5702c013cab255a4ccfe58ecc524e971ba42d59d35123ed4978e570179d458dfd84271a9a6fe81a118ffde44ee28b73e9222bf22cce3f3d44933325fa1ea09102394c1526badb0f719dfa35a402cfc89de8a2e72642df95137fb57a76c30d190ddb9e0e6b2334b24a51ff5fce794b5d517f9d523b20e4cada6602b8866a3938f16c8e9f11c8164d3f15b41c33e843c47e0a2d11ef847d4b25f705b00032fb37a26516852f0a056bb471bbc99952e0084dd201e2b4c13f500107c3594c0a1e27b7e917ff6b27f1276b2b0b4b11ef0945c80027889176792a9c2f13508b59618864a5c7c3da4e21a7485b6ab5ae083ccddd32a03a069d03bf9c8c5cc7abdba2cdbe6b98383d0ace7f539546ecbede48e965609b7a8377101313814c1b96f4fa039323938e3080a1fff2724279f8b97fc0331f18d5829907833506950a9044656e3d1c2252f81f7f683c8cb2f5746df8cedf90232835c55538fc3eb150b072b462f940876695f2e16b096ddae7e06f4a77e3daa414f9e6a98760d260286bfb38d362ac781bce2f59b61b5f6107d2a77fa0a8d5ebd62aa87ba177f46d5807d1daec4fb9840f5cd15181997890f054e9f39f46c89e7afd7e49b90bcef7469639c83a1e953972df1981e2ec365a254a52f7a9b9ed6c3c320f2cdd1632420883d5561c664f5ce789b217859d97a1eff58cc09e124791e6064b5ab9af47894c8f6a1525320fb1d74d63f64a055bf491ffebdc6f5e0a42434838aca321ab447aa4a175ff0f721ec8ad7a2e14ff1324c11ee700d304732a2d804b72441f329a5e3620ad82c0ac928c2d7653fcb36177a3cf1ce6211ba061ea3044dbf2769080b49ca83a1d3ab89db9ea3f63b18a580240d823bf59ad3a362f93c2831963d3098e7bbfdb7d9af1bdaa888dd576161e824fb7d8865228d89f7d61a95d3c74decaeddce4ae2f2b3db3cc8630e482c2fa9da921d033c467a0ee98e4a7a320a99b40e4092e264c4366f7a70f5a4f0aa395f34b395cdf3dba42e868208c65b950fedf6745bbe79360e8dd9631e285db3d45539cb82858b372710ca0f015f7c4b1975dfaca145b548e45f0c438ac5ca5c6f329f0c4941335bbd6b9a841618686db86af95cea9cf64ac99ab32c9e4331e387a0f50b1b041c5cf470437917266f07cf6b6c9f921018bde3ee832e39c99ad93b05c788279112df8635c1710181ec02c9f079fe29c21734b076c3a859b7fe668528044032faa597e4fcb70d740bbca289b3a4ed326022af9af9cc592cf1ce8a46e91e1b340ff86913890a9a5fc8280538543ab281b287cc0290b93afe2ad0080ad948ce7f9853aea020e7f05fe9c8db846ae9625fdeea45a611e53aee8803bcba17d2e570d1c28b2438ebfb90b891493e48fd7edee13a217b3030079c62190e803928f6aaa7e0b7333231525b1225a6571d5494c0264e495552721cda296f38a9b3f907414e374edb94699362b6ff9afdc647f8dceb7f1d467c99f6744e384eb83452ee73e871cbd68eb8205fea82ff19d78306f3c487c53b32c5e5774cf1ce36b7fba6454f70ba0abf69d09193ebbcfadbd3933b26f7326e92348f5fd9a6f9402d1ede1c813cab311b8adf28e55279972efc6b8cb8d1cca6c902729e6da4e15ea9f61541af27b11dca9ba169f7e740e42f70db0867619fbe1b798a7343692c4f6aeda891501d4dd986688b59c3f3b9d4661e752695092cc1ec90c57ef4173040a8dce5611ad0b8a39737e3acbe4f948cd5fb1a69e932ca0eb6f9dda96cf0fe6360d2165b04fd84abc880afafe135712f7daf16e57d7fce56ae5369286394401f8ef1dd89ea7d491ef809b9dc6ec37196c200a035f49765741176ba7dd36db4efaa0ef6d2baf1497c101aa08b568ea56d45603190ea3c928884cfeb6eb522a8ff353d9a2c1e6263989e1b12dab6aac0e5082f350c078d7d6fd69740a3ee515d5efcc9053718cf11f9d546de90e024a46e6d96a5b26a15fc7222b96ada0802efe251fd93b86a4013bd7dbccc5dd6fab2f33e5d050cf895cb270806ade234c5bedffed238421404b0ea306d767ce84cb600e9d469a5aa0643d5957dd04878f9c1275e7ff00c10db0097d9b984ce069c2308cbcf698a7a5b022ecf47508a016ec0ae7259c582ef495365219d195d7f05fb74452e1bec67b51f7f5baea4a1c972234506cb634e7c0f221946ac352498a6eeba784ef618ac6302e4cab8e4a60e15bfbbe2a08ee01569d004a5d7c56a60691723187a7a2fe6faf559787c8b09deeb1b322a1276bdc2f0dcf869645246e3beb20692471f1af32127531df4db7e843c27545d5c643813638025858298b0beed42d85ba243fefa5bb42cb7d3bac11efbe33c0756eb009e79bb637e71004cb43cd5c9a8088f5eaabae8d7c42a92984635fa0b9fb3f2823622486d32629083d130a6fabdb7416115b2d3915e4a5ea5f535d9c1360e4ba34c8782e806c5852ee2b59e01a13d01462b27eebe0d7a2c6e997b863aaafe113ad84f87c5b76b58275a29d815c6d83b541880e003680deed34ba02f60e9788c41ef6040baba3fedaabf8c21b72edf92b349bbf126b3e650ccb21f12d1b67e06cb4c210895d20fa8d8c9dd0a67875fe9faef459db1e787be349d657fdd08dbed5f5d70c325652a8dedcbb78fe3a739ab2f62b109fe920cea305d0147e09a2984b68e96dc4fec790c370096df644543394cb8a1b4971c634affd5dac9a5c46c547b851ee33c888189d933fe98650d75f159fc7a928b8e8c625702a3cd8c9e51576b27758ffa246cbc5a86118f3e7cc34d998e570a5d030b39fce506425bcf80717fe80e84075efb3252683061c064a5fda141cdfef17aab0baa6acf02d43b00228370cc67466f77795535b866fa729364a12af609d8049cb6563c471a8b771697db92c19fb091c5f568af70fd95fba04b768213fe0e247043750267d2d918858bd64296efbc5f0d0a1c67a8f717400f846c036899ab338fa388f84891db95058b52da00ee9e6ab95a2dd721cb4967549efa9651b73893479f1ba8fed48d2485b90810f2c0036302145b0bd229462e49b69445404b249ee05ce0376e18f17260517156da83ef3cf421b944757670eed9c1f7b51f9eede07bdf2a21d356226b2f1de3631d9456416026fabc5aba9e2fc44179ef5de082cea4187e43e104d69551cb51659519475c4066e619b2b1db70cf32478369755675a58c814ffd5f9af6127da164c86203995ce7eb142a366361a76acd012989c8e5e90c4c9091c71fe2bc2aa75d86052d28d0d0be7ec0966995c8b724cc898462e9118eacb1065c19b26626841d02a8114ea453255f5ad64a3bec2b19b7fd8fe69fa5e7e83a852489b5c90de2bb3e042962d8b84c5c518005c0bba93cffd0ac10eaaad6cfa54e435ddbd5c14b334b4385353a58e21daee441d61f63d716150f1b1a85c05b9e7190e04e81b454ec5cc71a735ecf82c32d2458b571e5d9604c2ef0c545ffc715757ff44a6f55f0a28a0df346c6ffb591b27c37489f398ac7575fe9f04155386b40a8b318ef4496bca5ff9e43e4f78a39d66a1a37de1d37a5fa1d0d01c2cb2edc55fcbddc5be201fe9dc1ea01a7f0658d3580bd7ac3114dfe9e686ca1121813e76ae9dc692592f7ee6c72fc407ab345e33790000f0a0a5d6df847b17a79956b6557be17e1807bbc6e24047d992cae7489f8efa3bf6a02a665c12b1ddd25bb72c5395e278bb005a38b934380e4ae010ce5555563933f785bfd693921a57647369555ccec33b66c023ff9dfaba746ff482393981ad0279ab26e7101b6a294e94bb12a7e705e90dfea0473b8655155d29062554b2e829163e24f686af2592cb9079795c67de6cfd4395a29fd74dc42ea3e916503fa6d8d0cac1e7c77d70b0e3427496ba680fe7231d52ea1ac30ded2cd3128ec91fc437f029a467171538b7fc8472378e67ef3946ffcac851cc02a68305ceb87dbca380cd1863f24fcbf4da831b8308d7213a7df965241f5d075c227ebb2ef8e76b07328f4dedda70827d00d46bd1039d340772fb37fd3fa4832c04beff7882ece25027ed4cfca89324175752a6d479118b87a115f91b3ae0b9c845a497298036aa8e9f80f1ccf0a19b608dd0ff1f5d3748e79825a933f4d1190339b49e235966f301499a8cbe880a3781960ad52c531cb4649f49bb250688c8ec34742067f31ffd1125990a975860f9729ee374064bca06a4a9c3e147063d146a6b22dcf0c07c1f0645d3d7a7c89de4cd4aace3f952c30d157bc946ec73af227b1d286cc8feb80906bb4600da4e7bb41afde798dcf2ae5d9723f58af1342b7ea210b404fc618a98d1bd83412b3a7b5135bffdac5f38c5b1aaa21f53f06558a566e1286af4ba95e514fb9a231f5c77df83b020e9dc035ddfd123e7bda367ea69c87a717ebea0919ae03923dd7b099c17eba2298851261bc5456617d2a0bdac581651667fa58b0b763e1daf30f04963fee4a53130ab93a39eeb80721c2b9b2ebbbcf373796e749627aa9e7c0746fb5a2133852e0b0bf6d1d79fa8fcd4f8e066471b75084b512f250f10330fe233038c3c96f002d7f97df476b5173ebebc3b76aeffcd57e3766148d8e30b0449ed43e188c64eae0d5165569a3d7d04431fa9e5e798031220be08faa2b9fa9bed2a3d13f1e137df598b1bd8d1da321203e8e6779ee6f3cca5351a973fc44fb1f00b03d4ef94725bd593ea273153904c9db6a75d77e6eea4e86a55429009edc201f91666847670f6569387e0e2186a836bc26a6f135464dbee3839aee70f159da015382e14433ee87abbebb1e0ef1f2193cfe6db1dedd78a4ad7060d2902e30731d85c121299d667075d022767a7660b1cadaf3d0d04fffffe1d858ca061d37a33f35488ef4e3e1b1ceec2217f9e5dd64f2a586ba89ee471b6b3239315f89cf12aa7e4261ad75df4917372c75185a851161389273acd627cbfb822e7f731ac999e3357c0cf129a497db8d01e948ee74146ecfe5788dfbb1b0d856f73c96e306e2481605a6326eb13fee9b6f4222dab5907b80005f4b077310fcc38b4d3aec5790aa3efaff238a571fa93ccc52a4b89605e89a6a874f65f2211dcf89058fdb4522c3743c6ea7e9f07768cc68aabd9ae160ecf5b9911874e32f5ad26861e224f85cee7795c92060cb3a1b8361556685ef0cc9a7d614a0faef960e4aba8a10d2837cb0a268d68b6e228a7a101289720b31ec14b7aa61651f3a6dd9acea4b1aa63fc3c7daffafae7c7392f3174c3cd7e63d19576244dfcf7e1eeb07f4cddbeac9aeecdd1a36386681b7fb7d0e00fe43d66a1d3a3423cb391b2e54b92925ca588eac917bf0d4bca9ef8dc347e393af2f6c3afabbb33923819591075a022690dbfd9b22a2b08d6e69fe961c8c1f5742dc6c49e00e8fe8df10212622b5835bc32a7d9723a2ffed335ee144accfbd09ed37c1575505430e3f2c2cf6e6ea4f390a7cc3c207edad6f43e8377ac649bf4a88230257625a5570cfe3c8e3f4c8f2713ae5e20d021722937e015544a87bab58801c46f82079a6abfc84b24a3d298befa2a557d3ff865a97ea194173c861774b68565919c4cf8b043b13dc0646250f3aae42b6a56b49b2a62715ac4e049d954a361c587626e24128d856d55d452bbc0f3be6224ce3404ccfcabab29ac1c6f9c6ad0d6cdd21e1a2e33f9c607b0ee86bb2e6cfe3db55a0263028cc1ca176a57650652c2ea1a5927efc6ce5068bbf3f278dd334cb6f942d5787e32b05f9f40a23555b4d357cbf81054f7285a4cbca9ac577e2d2b2d108c69683bcf439fbcd043ac8cd8c77d827ba070643521bf09ce2d2bdd6bd5880693c4944845f78e5d40f44d4fe989bf611bdc72090a39522f879843492c253af91ce45fabac08c026020f3e207bde2c4a0daa48742e17e62039a58ed2be675db3a8333b9260c97d577fe5e6817cff496b93d24ecb1ee8262ef11d031edaa270006136f9b11c4fe69e5418f993029672b6701da71f6d6970c2987327b814356620621c018ecd8a2ec1492dc162ab53c7ab843d6c35157704b92e6b8153b1bbd040884d0b92f1bff928fb4e90c6fd3a1054a1791253024b8801acd98b9b89216fc942c5b49f869672e6005d63fdbd6626835364161ec64d499bc29ea5a59b9befd13e43258f4e85e52169d48e0c5efd0d92d0290c3e4a531b395c58843efff0ffec8eb1ff6bfa3a7ac0df4cc43d350d4b380bb0284333514826259a53b4fb5c84e87dcb058ffde7bd732fe468865a425083080217466b50f93991a632676172da275385bed3bdb83e81b2ee58683b4931269c2358c0476157b0109c6ddec6d1f3dbf84aaeebde5dd658a75325d7d2766b7f90dac9831f79294a82c22ac39d3b9806fd9ba78c082c3d46bf0fda72116bb2c01a53905d38eba55f761a7f5465adc09e3cab1bcb61a8003de48a2e7defc8d158d4165e4f3d025ff80a9efa385f30fff0c0253a2b3d4e236eb08028706d929e4deceb1ac6d239d89c7ea34ac9b47c21c447de55cb0afab103b845d5126167bb3ba1cea14403fc4f61abbbc8c365f1c94ba80d38a6757abce18c2df37186a39c10d6bab51339a72a5d72edbcc35b77eca71932b33a678f8093a22a23a0300f70b8fbf658e0720b8f6374b55e5ec38fe6245643abec8d710914a355699bee0bb8c00d4ec5bba7caf1354e52f200167cdd4b5bafc4ed497cf6b6b008d8d33b377db635f836a0be93f87df39e44d0c15fd3c417a1c668a992e57cc2711469eae132c2d2afe5b51eeb342da032304c480581c8d5a0c5814ed47925a86dd2775fb32d2404f5571448c4f2843214db5adc9726773d4a4b527367e6eae894622117ea503ac88f01007610c21b2a85439b2bb71c2743ab02404876735563fde95152d1b7302f6051b65def31846f64f7e0048b4fc24e54821431922077750a580e397f718d365df27b42a77155e6a3d4e113ca7cecf8460d61c4ae703ecca52981191f4f4735afa4a7a226970e5472db0b2cce6d7bc8b11fdf873474ea1c200a41432062d5e6ddaff2a8ac900a9f9ce04d4394df9cdcfac882c1528bfc7f13116e733e97ed091d0e026fb7122d162dc769cd26d3de1a74e838b994314ff1f2ef7475bb9b7a16b27820dc89b3d0776dbb5e33b16faa0a8bbed8f9380060ccef66b24f10a66c4355b13e4ee84548f64901d6db3383617a4efa916656c247a506e57c18e4e704b74b4820ceb30be1311628729cd2d44f9dcc9f9d5e9d67e28095b780100e1e49ef378af565f57e77f977d2702c27acfe171d2cb7d0dcc50b3c3d653301671754d6ba1e49ec28b1cea6e3f06f285ad04049a429397e65080adedb4cc4bbe5c7379c5b2af5fe7d2427a3ea57eb05af05d96a06de4ad8dfc2f1915771a510c5c1e424591c976f7d5db1e8541c3293390efc2f3520676e09cad5b666c95b8c9d9feac74d886e18b4b4563ddd7972523e5ecc1e4bae4b781f0917cc6adca188dcad2103c7fa0650adc1cf8c459a20e8c4543c9a7e7264d05c5338ffc8b9cafe7b8e3abca45d4b2c230654c757176f6522528270b7ece40b53779ad0ddd508f239f459fa2dd405539d68cf4cbc777a427628279520e258fbbed45e040285729a5c758913db3d587ab4e43d04fe758b9822fd8cf3412949f02243174fb632783bb5a3ca32347cb6aaafadd0edbcc8b403187d7dcf91b987de513ac6e1e190600f69a8d2f2523f97a278500552fff3002a16a031ac00be26e94046b43e624e49ce5aa2fdef75814594a5ea45baa6ce4a6bd3b1c55304e5f968aa994f0140576f3d29f0ae73e480b660f2df7071a3ad13c46696324e9aeed6a0a84bce01c1090c5fc1aa909e32d53b37523b1a06cb7c146fca1fce5d291fc5c6fbddce5b1d10f590b228236d2d63fc6536aab8166ea4099d872c99b9d9dd591d62a1762d0e1acc147e4c0de8191359ddb1e9331b4e32966719528b667b09c46b1332f136e370f921676410483febc4d243917df0ce3165fccd9ccf2cb9923fde7606d2236ca68c0941986d9b7f2677a362c7db0727971bbb57673a75d221402bafbff5970bb529aa77946ca285682827a07a919703d123c7f0569764ac135909d551b43167592ff441a0f2db1164d958cdbaca24dc21b93ec81a879158275121fd07719c9686fca4423f796d5bb62a30b2d1996c12924326534b0843f55bf5c11eb2c48e9b2337b2d04a6c5ed94292df4b3c69af71ba632908625d3cdd46da4d8d4df051a079e29a16b3c0b0a9a08f30e5c708c06aec2281bd09ea3728b9b126faade3aea2fc5e969a2782256a20e37a627cb73244ee4dd0f0e9d547fb21e41ca8bb32cf4145a5390c70c2f0107a453d69d9079ceef3448f5e1634b81aef05f04f3ec9428b614fc2d9c7521da7e0692e295eb86765a040cedde61406c125ec54947b4e93337a192e348ee3238d1ae6bed7efec666987243511061e748d1f5aa4c959d3ecfee5af30df0980b7c1388cbe0f5a4efa5fa303805b62fd0406ed2f60a3a1c35864257953b8039554ec5b89e325683de6eb62d45bb16821e0110a107839942cd3786a9599e1380f7638a7d8c57330976027a0bff9edb9e0ed45707d19e62bda1f5351a4aaf6269efa983ce3df662008f7584ff69ca034cbd5dc933ad2c85d123f0a4aafffe0e241cc1a058eceb444467ef2b3259c26cbc49b2a33435f88de046e43d8f297cd0d8978ed9779a414cad28befc4234dea6ff25a0e83e8ed5d13be86c7e91853c617c31cc829e65781c30d99786219e1b60f9b47442277cf074c3dccf97a229c6e97d0e1d17d30b7dca547462280c156153a9e1d8d428407a30c886172cc997a9a8e72cd51b5f95c634c5760bacde6ffa985e545bf866c5de2932e23b8978943aa49f8ef39a762fd30479d2432a3df185cf7c76b1a849adad25ed5bea1fad4ee95e661411d6db966c26b10d48f9c56ec99da81a70c9218e57533baa18bcc0a008832b317b1f7aaacc6f121ff941ea37385024860af734e4cb15ce74ede11fa7a5d83696e34a98ee225ad940e99aa584850e0e17fac67a701808b340d8c6442f0acbf39b1e1bdcc503850c603dfc970ab15b754a7883318977074f16d76e2b839dbd7b426beb2d901c6f0ecb7af2c21c2ce51093be5726b5aa56f09d687f5738fcac4e06d946803b44838d517d891e2b691a17aeb646d749b73606df2f8cd798e2e4e25bd0d78a04cc53893703f6bd88c2a3176a6bf8b3d17fb4d0439289ddfcb8555999c4116bf914f9df9af5ad6024b7cad677716c29075068820a1362f66eac7a91b41564bb5679e639e9fadf1cda83c864e40cf7cfe9a3b706468fe05e8197b81a1366372d46987bc7c6358001a91e05e4d7e40244123e3483a3fb8203cd0ceec6b43cf63986d2b2ffa7b5f07c2a9731a6bb1bb74c77f58e866a7fb2d89e9d6d11357b2389058220d7f8909c8ca45d19dc14cc77179885e9527c172a5673176e496e3d8f760839d0568363b36aca0e62ce29f7994361cf7904212eb0ee00cb673133e7c309aa1a0ff57852ded990cb1ae282eb226cdba35572fecced7b68e6d95a6b8fca3c49e755ac9f3743993e7c855fb438b5bd24bfff16f51b128baea260acb5013107f09b8319366c1159d2dc9c78f24290ad7d685e5602cba6911615e765156613ac010af99bece16e2306354777a5033537477257243e0ffee7c320476b7d987b3004f100daa702a92851d687ac473de967979b235b1d375fe9ff2969024bbe164d0c2384c350fac79cdcb610a8bde868f76e7f02e6cdd6c21c6e29e9cdb60517394f39a95b9770c11c85767c658d495ce16d4109696cd8f65065277e055301d3c402cd8197bc469d1e53d8293caf8ec115c2abf59c0ef1245a497dcb074f78af788a2be858e4e4c8afa2f2056b43c77a7eea7f4d8ed8aec90ca32f4321ae3ae4e7a1a54cc7da8ea1da5e4337b0ebc3ebab9edb8aa35d5c0c526c169ff3ac91b253496cfa3a51240c149d2cb2a3470399499a6fc962a06cd1ee0a79b25c5767cc324f229447f00934c7c49ffb80b066a420480376961c2550f3d7e0287d2a658427dceed26248bdfa0b4b58c9367eac211fe96ae40a56c410c504f80ecab72fd8b817a6b3d730ddc80800098b4753b7320abf2ee2ac4e76913692db962d2a6f9632e8c69c04f90d029f4dd7ba1e6d07163f1a97923bc656e549679272e1dd0a869ad47e265ac738e07938a4e4a1eb498d201454e6bdd48a9d2c65f28b00d6abc9f842a8427f48348a5d5c4c2e43ba918108411af80ff076f71321149e7adec8e792689cbf37484f6b81d9ec8048bd3dd497d17bf662ff0e396980e627350afcaa2daee49199a3bc113ffcd05ae5587c7e1137b9fa1d946dbbbbcb0ee86dfdca6476882c9745d031d167790de0b936b7ffdbd62c6e294c30892abbbee34022d6450bcbce38abeca1a9d38cc095102a997c2dc4ee3f0df7dd899471758f2298fe267d72105eb6bf0ab722c4f24044cab02bfc78c2c99b2e8aaf41d754d09cb8e0e2ae8233cb9cf5298aeb093453ddd632a10495837ef4589793978219160d1e0e2855f9b41aa5a100b80f3ebf7dcfa188aab6e05941109f71bc98b819971cd25db5ffe9d1701b64d3a3d3679dffab54b16c872ace4b11e7e7c5fae864ac114db9b8248a2759e3ce6b372d31cdc4fc5ad4406079e51da0ec11da237167747e30a22721c6be25e84376c26891e56b96e6914f4479b75f391c5dd5ed69c1ed866dfd64f36295729fe6dd6e265649947f2a1cfbdd1fc527c4a98001821c1feb8808eed3db36ac207bfd37e099938ecc7c1e24b8ff098f5c8ddfc7383668a89ada294de30c23cbefd51d62482c9cba565d3c8ee7dfbdf93493319389da628f1e4e4a234c4bc154cbc61e04f274c92695325f0ed6736de2944e0b2b4a9add2bd6bf2f63be5724200b9e007ae5bc848e0204394ae00bee5de839e7bdba7d787234abe456266b2b10e71b26f1914999b0a352c4023e46cf76d3941798edd133880bd762a66e4d52612b8c3bbc9948ea8084e49bd0b36fbe969e5ea9ff25cd1310c3d2d7cac7abcb49e4031e6f560cc296b721ccc47d2f4ee721be3de24ef129ed526f14daf7db6bed06174cf6f957d4594547c8fc4380ce7ae30022948ccd65b4203e81935792440991759b60bf554f02d9420c111baf17d8e65579703fd714b26c4523e3b09be820027f5d9f81158b7891dfc54e03024b6188f6f318132d66ed7efe596233e07633f9b85c2ddabca345ad836c7558d7fd0999669960d88770cdd4e8ff76a64d347766afcd38476cf1d283da6e9e7a514acf2e29af9668f4c18ae22057ed1db77e37edb5ed02424ec7b55518b91cf235e64d58b8de1459786c8244374d8926c7ac2e92dcaa57fddd90ab6ecf4b4c6f5d5f5c6cce96d854b31e87d3b0ff5917fee1aa644d3cb5f203caa2f4a1acca5dc8465b06b0fab9ae64e378a6abac9fc72c07014bea9c92f6708358c664a15c1d521b827ef882edae3641f15bd5b38b9ec9f2709b933e8939ebf526bb4d0c764dec70a8aecf0e610010eadd5059019ba2d3fd8780c0f9a80d07e604c42bce74528f9220a2a543fc7346cecc28c6ff0408683e7c32a7993f9a4c3b6c7faef9626e8ec22be912ca7c283ca282776eae53837090ca13eb35968e4f1cec38806430c395f04d9e31433789abfe877da8c35866f52084d44551ab485c984f4839dfac1f1deb651b707b6e3496bcc9aa2a3c934db9fdae0c87af9e157a781c6e50f6dbf13fe3a7f4a77f50152e4c30ccfe3f1fc79e1050d0151c2d9dffbc8a3fff4358d90381dfab07b4f081ac219430c3e45374ff43eb8687e715d76e62b3baefbc4607a391dd3e860b778c7b47f92b8c0b92547e6b52e7d8e6f69d72ad500473ebb9e7b5d0e330c5831b0514a6bdd04a241c0c7e97f96250f0886523d44b53bdad6387fe7e4a1a29c8e585041512e2c244ef1fab73c23a03aba6b6b84d284b0019d4f3c3826ead5b9c74b6acad4270dbfb9abc78ad38f07e8edb48612763bbe90d69bb8f9263d1791d21fa5e8490b41baeefac840cfd2be1ebb6bbd14124c6e6bd5219c1513ff5314eee51b61c633e78b46de0c6a9643d4ef270711b9288aa185b9bff40b105309d57e184894bf617285477ac8cfc66533ebcc8364d7a5a3867b85e0729a3f47132ac9e274f3aee42b33d44ab525e5c4b5cd36539e86c0f95194a5d507178a8384f0e66909ff6dae17b217c041bfba1786db0f08dd17b219003f0fc5f52ea1ffcd70cb15cb5eda3ca211129702e5b686bbe8dffe36fe26bd25fc8e070ab335fafca32c4a05ce5f4250669c2ada911a23520fd79fccf0a6c3704e0a8e33e5921c2a76569f7fd16e9664ed0c30b3f49e101dbe0abdeba214a49b70ac6e4adec1f4116035b836f670af42b9f52b2089395a88cae2f930ecb4683c8445c372e2e3713e75f8bc149ce04d8722f9af1dfce050d9e26572e90f409e0581fada3907accd25e4bb281919392928bb4700c4cba6121db892db5d44fbe7dab412b52738eac3dcebb75560262ef9dba45f0322b708e311a5f37dae3abca979dd0bfc014fc1962b0887b43a01249726e7ce7678f31fe9ac138a49284936ac0f74c833ed461de90201b276beb5ff3898dbf615417a215d018f2758ef24809e2d6686f6b2230b046ca05a183b51512d2360c11f2b2e4c890e03462665cfc6e32b348595d543b40b8b6ea08af6a35469576df7eab181c4624256f2f9b367c4830973eef5906d434419e290e5c0130b623492ab7948ed8a1cef4294c8ad0e2e9b5abd17c25434aca8cd2f171b18c8357cb958b847a49a28a43677c27771933ea06c0daf67485a9f2fffdca2e87daa3202a1d410074b333d4dea3d14256abeb53c88a15e146a824eb53aff6dfbbbdb09557c2d94167af92230822b3212a02e5ce4551f5c6645b7fb57f491edf606f6a6e305b14c2d05d56cfa0c5e8622bdfc2f881b30f0d2f18f894f3520299a2b47a8c806d5f9c9cc18e4cf28ba4709b6a8f465a54eff83b36f83d8be6fe6624301d05932cdc0e323edcf95f920ec2075bb48f0c30341c4fcc5e05f7110c10d6cd2255cd2773d7dcc00c432c1f9dac7dba807f5167a598375ab803b1dd335dfe11e0a5991af1d348d2b8484c7ad873d9937d5f8321a152f791ac974e41f7f5904cca0151c0d1f5689b08085ccd23d3064e7728eb0339c99d7e3964e0dc51b4c937af2b5019115022dd1578ed226ec4a364a19f5e74ddba2c4154551ef7a88bd0fb6ff18a646b588a092dc97408033e5a1a6006793fa73a9336a1a0cea23bd5e2694659f13b5090d1d08f5231e02ca6b2135d755baa06d072368758f47b26e91fcef84952b7b924a13bf01470129dc5d14f9d32d6944b6664de43890a4b7d40ca52de567a5a7ff990904a3a9025d620029ec873665f272f74cd49869761d6d5b883d956164dd1e4c7430123ef6167be7325ba04970ee9a19f3bb3747d1fb16b3991db0d0eecc98b82d89bdf49441663013b54d1bb54faee8b29086427378c6ba03e7a413f084453947feb09583fb2b9284f83f160b69d95f972d05a5e47c0d87b2729b53ecd951fff301d16b1e7ed3467f61d419c0272600d7641e6643fce49ef91b244ba1eb52258aadf599598888e2123ff7dd72d176400ed8acaba5de90dfef725eccac2bf31828e306582fa98975d24b15ab6b4d10f942cd186d529be99bcb0506f93bc8d97c694c646b29a058136ac8d44a797c5c15ab2a1ee350a376ab303f702ba53762bdca6ebfafc7eb0b265a2041294f967a94c841737b51103d0635b17adebfd9e2ae0a43ca6ef567dad8f2f17f5590f4f2f6fffc46609368b9859dd1a80557b63765344b361e298694d3b3a5ef77c693b8b752153963b0c9af0495beadd1e01a22186cf1e81883712198b83b5f88b5bef7567ffb67fdc740be55ee3ca5e02e1e338897011ab04eb6bb3653d7d16822f00eef620f3d30176a83403b9ffc6bd488d05c2c4586122ac8d5d5b0db05088261279765918686b108da23ea65269030e7889afde9e9358008f2bf01bacd3608f527b2b997dd2b28774aac8d7bdcea6bdc6db683e50e32159f90b18c46bad874c17006f02097579c760c14b6eeb94d4a0862f351a305ccbb7a162736d64b3ba8e5b62d196d55b13b139c74618f5ed4e84ac513d1cfff15d9d7f3f7ec2e9aa5b840019a1a552491a129f2fc83a44070f5eddd238d72e01d08021f03d2fd4358eb65ac0a93086016ddcc9e68d46540a4dc1e569873b0cd6e68a13f0119fc7c9b356250dbdbb6a9eadaa5e05aba3a7e8c3bed505c5d87159dc0982fe15eaa273cea9064a968c3444d66bd79647d0e2b8bca99cfed531ad2ff08dbc4bd7c9b2a00e1de6a550742a82cc41ed8c271616d4cf434c854f8c84fba07c6c61f6f5de483bee626414a6dea4ecc7c27b1b441a1a3f8fd195a6ea210f1c50e208cce9b4a436f19c00c49f2fc8ca73972422cf202bfe5209ba803a684117164e370ea4d7844a54e41c1c6e060c69e51ee4ce2de6e21fe8a528ef0883d37772dcb090d5e7cc7aaf9c3b0cc4633973553bf3a6a45327422d0091a11c167f04aa96c6267ae4fc1de43470e75f190ddf7f3dce7f4ce414e85504a7a139d19e9082901b0e731c6b227a589fcb174cf1aff53f7855a3bf9af36d42e58fe8dff62f56a9581748d9b9f8fa9947a9a23287db40a5427112843d00f36685e74880b3b56c80f380dc6dc7e4b289ca529b54118693be8371894d8bb57dbef76df5f6aaab90b11e45ac5d5b3323c91319f56486597ba1abe91225b00cdcaebed48847b9d950e3a922d2c32534697142e50b16cd933044e9ec973111f7f5471cd5642b25b394a98c290a751fe3e5bc8e5afd61dfee722d1a91813831d3fac93d42b9bba8db2eeaf097898d3a66ea1a5e9b7ca1eb8fd69b6ca80edcacc67991f4c13b94824c1697292354e0e1da7bb21746931c6a272bcef06befd615c736dbdda2bb9b478e38ec54dc0afc64fb167438a4ae8e307271ea72b1bac10d0ec5428dc1a0f58abfc05ca126ca7ea8c8c4e4d5629a256b5e81ebe0bc89f77b8fd66d0140be6271f20116addee4b1600f7ae133d7a344db8766c50167abea6d29f18e8fe4b52faaef8663a880902b3498a338a01bb7777dbd41a3c2b8d264cb20ac8fb2a6fe49c6e34c001361545e09d5a6df8f20be81e9a7b4c5cba41af944ebdf2187d64dfc2fa3394892c8cf6c69b1bd15633a2b0cddfe8b9611980e047e7a155ad244c0ee2436e2f7a6549def1d3b0fbe52a8b07cec07e9b05273b0daa42d6b7b1bed0d72b649d61e928e5e0d941f6e90849e6d760d8255a1d502555a5dafd969ad4e80f53e96f541ec8527fbaaee60e77c54a76829a9fffdebdcfe040dffd71f0413b3918810a9b6026d3f4a3d8203bfea92d0ff978684d61a5226224107988cde30e8a239d51d1215b8fb9a5adae9fe51ba9470d022ec9fe893ad2a3a538524a524aa269c87e13febea25548a53dbbd5c199067a91aa451bebed27d867f7b0ea537dae8b4795e7832bb8e8e04e297a12056fd850f06045e57077b13ecdbe9f4a0d13d1bee226d0627f2c9c783de390a63ab0393ac9b2a2a8a72fec0abd14dd323ad5d0c702b09eba9c3a8691a46dc95ee13f551943464eae411debe616597b0d5e2c23acd62a1055ee7d00885a5c40fa6f867402dfbdf29ad1700e96ab0a81096106af2e9d2b0ac82293f9f4fdb11417e56a60c642d19942bb6e6ad96778775269aac4dfe99d48755d68b443fc29428f75421b4ff7eaf6616baef5c28bac3cc84bc602607d8b05f80ee736ddbf40481eb88dacd70f1dbf8ddd59019910d5234fb5d3b9b35c38ab84f8878ae60176f173ed7d48e27660ad22737adc9527ce2e1919eac5c1d2d83d383cb2f2e6c2d50a8c41234bfb6b9a7eb5d81e33d2ad510ffa2fe2fb1cc3a36284f82ce079855f6cfc194204a6e11fe9a4679d862d84295a6b353bd585cf0ce550375ca68c72017fc88a62e31a05dac7d32bc3d77c8de824545f296c89d2aed0c356583ec6cf244588422b24442cbf5816e60d4e26c189a52e75c61164ad91fc35ee60015ad7f76f703030d83451f4992baf9657a7955133a7604bd9950029900c4e7a1fde179cb39d154ec4df7f783a76aeeafa4ac32c81956ee592c76a5815370ef5b70caabebd05d1c0584b43ea9a5fbdb54239819a8bf9f9ebaf8a4afc3c3a62df9f165327f31ef33b7964b4329ccb78eee649bd0a70adcd073cb649873578f7be70b9946fb4e4125731aeed680b6f78a5b63e7e9f69d6eb04a2ff9cf1c16fa284eb02e19c0117f265626513623ef9bebd4faad55af7cb60e70642e4f2bf97d9542678805ab1b2dbcb312893c6a4d1ba889ca0bf75b562edfa827f257fea1ab316afb5211d893657503aa1f18de207d92b291a39efa74e346555fa1a5a761de80a022ad145b8bba3bd5865612b1fce5314e509aa6bb39c5432feb31b01e9bccac291e76b9fda9f0983000e40d68bf04e95c3f6bbc8f084f139e11dc2b39070fe9e3668dc65905b2687db53adb20d7ff2baf2821c4583e02ca0d3e157715fe92eb944b48569d9cec6016cef839dffa9f13f11ddf93b2b3514d6e53630c6937e73aa82d4ac5bdbf33d15417f2a0330105f4afe1b62489e52a7d619fc3611636bb733077b1393d2557ae45836f2f7917a239f8fb82cec6309ffd3383e85614ff5612de3ead4e1d7b31c6479c475ce77fdb2d4c65b6a2c1eb6ddf0a8472bdfa63d7357e217cd38cda93be69a193bd0095e5aaf5c7cb505181d105f8a7eb26d5419e556dfc00336c964aa508a5df9b64470591e2fb0636a82aa06cd14492091acc5efb07edb50f0677b5bfd02f4c513f8ea991e89722463bc3a0dc5cb9de6aa4b2c5c00a4879587be1fcc2f33c3c1ef801b5b8b2ec06af4451ee2d853018eef151c90fb10a9ec974bf4e18512a4e1302eaa99fd56a201942758f53d26287d4602e404599344e2a4bf4d7f1b5e891bd0a97dff22d118f436dd98ae8d82486690526dcc8076f8fee3334f9ca3e8094b89c73672e128d24df55fd2e38eba27ba62c5d74f9b74c072071dac1a6f963bbeaa9ab4f72ba47d6012a961fa2e9e30805141f1a6c8d990c4b2eca9064250a0583faee48bd2ad9ef6083e8c97236d2ce1062c6e4bcd880015449dd52da17ab891d09e22794e4ca50a7d95e82ec51b777b4ee0ce45fe50f9fe43c423aa69d6723a6fb585bda72697ede53b36878f65632bf23597d0439a2e4fe39ea8279ec50b852f54517e4d03a718f952af5833c4f49c5c0c909f595da8888fff3b9905c0f96c39cdeb6e0b53774424085972d80036c57e856d10ce3c35604c70fd5bdc2e8df437f6fd37d139b9fa0773c5f6b17c1a10ad9774b6ec611fd52557f1daeeb1e18ae06407a8f4b2c1dcf1e2ca8bf708f4b70f756505762d18849f237bd43eb6ca4d01e48453e38bbb2c7c3b4a1eddc20483f102bb1dd995689408790f77c0f102bf20e2b0ab90ac156965e4fb857b3642273e3758d9e278cee4697a342030eaac73afa70ac34ac5d551c54c1b0a599806754a0841475bfa6a76e587c7ec7850fbc68ff64e36d0f6225bdc6162373f7d076ee9957729735aa7a70acbd764cca175e52b8106b7fa18acdc83e66c3da74ea6b095e4cda72efab1c6c7b52c96e006e3abf9545c513ac95cccddc5bec2c9bbb4da09429fb10e01576e3ed05f93da5ee3ddc7ecaf73a552d866bc42b9b65b11c2f7ea8a90e76d69b808f9aa31487305ef618357d906a125b60a33bde962629cb0fede2839844a275fd08589040e9f6824f4483f1584ac68b66b95377749be99195cab301f80b68898dff286c2944e61b46f4c761d2b85cdaef2de94aef46f13d4f3c7cf0134f26389801e03f654fc9505f3ea1ca194ee14a3592f68c049260a301883ce6c53b03df4d7ccf0aaf68f3d1a34b93ffb279d6bcb9e23ef04a47dde45b17ab4105fb17868a08c760b85632741f3f0892848807a75cb6f1512bc34f00042433e989667780f87004d56cfe5ba05b1a1a8df5ae41e72b24392117d0be54c5a3bc965f114d2c5a65797a4d1b4f9c5e56b0abd7ba5fe598ea4c25489e0c5e270d07c3eeada4b7ac1d3d5d9d919e7dffd45fb7ceba4784a96ca9d71ae0b612ae11e49242d0cf80e76b2cf6162d119e849a4bd998ae63fc750a43362cc040563c8b61d69cd45dedd3d50c5d352213f1aabb5124396e180f4291275348e56548e4f4fc8880fee0f7baac5378f5aab920ad3ef6b54eedcd5e9d394e438a6b74b2240e300e03e5c3383b15bfa1dee34d1a1306b768214bbb8ef61200d9764a6962a7dcfbdb74d6660f21c291fc9502755875ba5a1120380301a1a3a27d43c798f4a077d598f7cdfd0d8450579d603328605851f9e687c21e7ce53eb7f125de158b39db477fa801a9e6318ce77ae8468fa6375f8b40b1f8ac1002de682e8d9b3818934ad7d24a5d86ad00d432d87951c1a132d9b9b1b66625d119d92d346a348a51d612629c249c2f1a2d3c4ef7bed31bf7d95b9ec7f7edd5012b6e672e36d28ede8b774a1bca9111add1438e81b3b112fd60e47319a0cc8707edc7a89bdc3b22e62b61df87919ba91a150708080202c8f363ab979c71b84bba56124318d6eaef86bbfb90e00cbc602a9417b4e88c321d4077bb704fa5a9024845a0a0678d2daa1ddb000acb5d00a90982479c7c3ee76e270f491380a3d30c7bd7b80d4940ee2f01cbd1232f63eb35793c29b6bf8ed93aa6644af44d980c4ea7ee85fb722bba6a9029db6109eb3b6c44ee9fa7d41ae2e3c791731a296f91328bd03e33dc2727574d66c5f07e1ed54829e72636f130ee4a81003a4e8c0d065dc3d15e477ccaacea409b0d9827df60653b4aa5845a10f0f18ae87786a1e9d050478def3d9017bb4140e713a40888d120134c34e2af6ce2af2fcd08e85e841d35c2736121f51ccf1bff39deddd1e31884449f17e3a236b07a88a9742e9f4e10c88793b5b3a8d6dd046060d89dc5a2c782ebfe60b413eec9e7e2f8b3ee0523bb3073d5c6a1c8c358b47657b49ed4dc2eb8707a809cdb6f19091508fd0f0da3af4ec2ce1e398212a9af7f45bbf173896bd9a550cc10ac03748d1ee6c9c4cea17561d382c8d902d737af4803e5bc9d9e49437b285ae0c286ea10b3b1dace4d93cec0bb486fa75e3d0607ac9833f8079391336366917d5f6b03efa64b7860500cfbd973ec970aa32af88a54c0547fb4bbb8b8658ced0f743bc6e4f5ebeae9d5b7b5ea62df3613a24b1ed7217006a905bd4bee374c2d24c79dd230dab95fb45cd9306cde749637255c14f319dd97c7b7726321f2fd41f8d4f71248ac580b8c460f6949772c58d74b5f53b6a0037c866c522b39e9ee7673ee0194b1bc8abf16de9c88a9ba3ed50ddbcd7a6ddd0e51dc75a91dd8baa08830dccd7b49cad8b39c86a5acb6cc2dbe82d164caa8f53a92210f910552c124721f1b42ff705727dd3586656a396be6b8a280ad8e3c7e670aab025bb667356e60e884607fd4dda29707988b11a227ed5d89bfd4ef5107c217a6913c3f164e17f73ab64b169931e633552f5d0c89900553cfb4b976310f9bdcd8b62b38dc99caeb3d6ad78a5e13555c01a41f90eab085f355ee531edd29f987704db819dc00ccc3da7693446ab04d329acf4bc5a3bdf58f9f6517ab24fca268b44c7fe08664d045253b722f5bcc1f069356bdd1e37636bf4879aa3445b217f44d268538349597adb705f03dbd5327bb5c2c9e92447aca5db226747e877106157487de81ea1481118fd0225777269b292b3ff13e6a9bf70ad63694ff6cc62e12a5791cba6e5b25623f9b553f8d99552a158893ce903270eb61311b745a27515848fa08c4146080d1db8c88f395bab0ed1904b695cf2cd33602c7e8263bfeb8b50548bd565a60a5d05799b7c728cc99254001d8795800e3856b053a55dc17de307d5812070f9f4f61ae5efc015072237d97e4210c8487e7b8b17f4329c77a5c0a173a59c0f9ff0344d047150f30727ec46abce184d929c9e23d8e3ec36bc4f096d5090174998dd73280c5affc4ef21b4232cf6424c8573b4d9805816182c3a023ce2ab55d5082c69306de04d4bca8c8836a9fd04271c24455bb02ed87be3b45ee9d0c539235c40cce7035484a01947686f46a809c61be8b090aa5cbe40ba102c06489d5658b028d8264dcbcf30dc4a1cf2e6382cedfbf9a4f073e2b48298794c715eb984598e5eb96943c80ca1023dd864e0a2a4fec02e277787d3c92b59380f6a1478805e67ac2dd5ad08ccd64b4ef89abd9acac2dcdbaaccca5806d473b28e9da0def7340a15f6fcbedafef8bcf1af7a618552beb318f4a88c3040d9399c202a42ee29d0d24cb82fb1109a00a3076e24b70db661343bce8eb205a5c5d340a784379bb19b6d4599dd9e9cf99c49677929ce815fb9c689e764401e094b5ed6bfa38507642d32da9aed37bc4d721a21a66f236d9a0d694cf14822e7e8c1f726b0ec9397088b383db1371ab37467b5bc4c7942e1040a47f9caf8cb44a31d5c823f0b6eda73429efd32e620a767b18a5f104f84469d204aff556a72a316bdba969a25c9f7f8c96ec33411a261bb1436b900305bf3735c9fb8441ea97c74abd8946035b9917696d4653e580fea68037b6161533f45666dc7cbe7b0fb33ea9959c46b125b5b0f1e684825aed3e0ad3682264b771303941726e600da827dbe391ba0e3d7bc126a7b41498ee34bd8befefead62ca307fa66c8c1d895ca2501f47b9743b72e6ad1bc9c44cadeb2d1323b528db3afcb6cc85b8e0637355929c694eff8dfe90e99ef8a3a7b92dc3aa4bc41272303f66ed1d53d56ab56f17121ff3fd0f8966c7324f31caf62e8c53190815f73418df012b9e7436f5f1e22dc698d20df3e79681b708038fb0bfbbe1b4c4c926bc150d7f224d65163161df27d907e2176d8c3291d599ba24404c5aca7d3a2111284e0433df530044be17733cadf587bdd79b056ed1fb90e35f974a6f6e2c258ef7c3639f7320869c78d83d3492594073daea6258ed6bf88cd3b25246638810dab12c811cc103496f025165fb56b035db36ea2e8b4d363c35cfd6a12cf69d27d7ceba8125d5ecee59ac42cbc87000f12c49d94c151382ddcd60191602c02949ed9c88e08e57812e7643988b68870ea565ebaea4270438f3a9029b74759badeebf3fb59a25bf7821c13ff4c9e07af4e97d0cb5fd784f4be34156a763cd55f9e570ba82a95c0b3a7f75e57cb45932697f1ec34c21ae8ba21c7ce735797986b3e9b80d7491b775ba65d22ba13a60ba63e0ffabae4b23ef1a439e55a38bbde891a42220a96a1597f091e24afdeb5be76cb6e33ae8d0f3e95d97679b23f6e1d5e038f82673b1cd39f3d3005b817da12cab14455ee07358ef8a55c08b1f1be4c1e3f20271fff2f39e3e0206ed583b1555b1ede653d1b6a4bfb730d147f3b81d00df38e9ef40e1acad042d282d8e9296ed3df86f6302fca43b6c4f3ce8e1622e2e6999b6dd1b8e0002d71e8db7571aa05dbebc83172d9a166ce9bbf20e88fcd9c586c91ecd442a8e64d297039d39e765d6095de0668cb33cf66b872d0cecfc34f1856f22eb7d5701a9980b1fe1a1253b4510e67680b357604e81455abcfbcb6503dcbe59a78cd8c9a5e653ef56fb142f7f7bcd8f8bbb04b729023d13a2a8aeb7f31ca9c3d08fb9f09c07d23f3a5190b4bd07b2a11f12ad1f78a89d0b7b0f6058c2a4ed5b7be96647b6efa0c4364009b2d518abe4838e243d3f1c4ba1020821742ba0149a29dbac0c5e7e9beae2f7c4073012e2ca762a71f734d98cef13d1c7320c5470a21f62bc69b5a724746bed52a5c8742fdceef4cb48b7e1161297c8f8342d3a5ada96bf2e0c3999d4ce0533467a72e859cf57128b79c94d110b36b0f4adabe89eb83a62bc1997ade5bc929e7cc82eb06aa8fcd893230b18c17b7e6a5a306eec7282c93b59e16dc303ca1e9496d1c669db59cb7a9deb48f234fe66f145c13a567e34f05327b8d0d4175f2c3ac15fe7eee79031c33c48d815d5740a415a9df832cf2aaf2f817dd4811df3f1d9ef3ce9fc4d51dd24432175a2260b9ed3d2ba0ab2dda41483397b8ba278e07e648c10f8d300433267d7d3c05d9e7903085d953ec63fb2de51c38a0d54c339d6f6fccf1a53105435509ff7c5ff9dbc6690c63b7f844bb8b49901b9988d386611190dc722271d84eb73764d1b0602b8ff3552910f17229fdd4903120093fa781d9bbd1b92d42df6398a121d88a7bd01ce6ff907949aafff47c8e5fea24b9003c7e18503b5369d95169e136d2f6edd04d1a54c85269bc9c315e15a94f89884c603e6819ab6f9dccb33cae83b7e0189f0c6ec9c39bbbdc057292b932bd9819122aeb8539d0bb51e46254f28b911b9ee84eaca58b1f885fad93a9144d5ae57af2d090280d5e646715fff74f391ecdf9bcd10a545b15d65d45866b0bdd6f990600ee858836611b885622694f42b62aada43f263f92b9f2276f8db39277e5ad3aa1b211fb7a0df7ef89c0f0990dccdcf396bdb6610ff4f16ed73c4069f61af34efbe99625737f1e1f11a2234320d91dd08af648c6943646003c329e8b2911716ea2a3e4ab5ab94a5cffcb3ef69c7f37bd2323bad3b26045307e2ba3bffc7d746779627776baca6c0caf022c054db60be9be5e1de4e9a7abe373ce0fd105b14b59bcc5a392cd77bc02803f9903c380fe0a24d27c5386afcc240e494b1e3ec1b246cdc7f2c17b996b020f4d153312165d8cf2ac6798671a297cad5bc99a6b92c56c9911aba95eb8b82194634394e9c55f162bcb7a352cb063fe5ec4b186a2b6a4a39b4a0aa4aeed82106b8349c625022d97453b3e02c034a6f8f9600addad16f8e7a113fc24a822ffcfc7b3facdbbb1c4894766b75db0a4de160c028b4c21089e58cdda4188a6763b41e72610b84dac07712556cc9ecdf1ac8555f86d6cafae5c6fedac05f3934fc2850459a2d7b4ad05a603676c86e5a696b4771a8e3d2043e98c9dd4a85cb131f800e6f43d86fe0a55139a4a2e7b490087212353c420090a06f91a5d50400b6fe90b090b93f025e32212c0cfd8ae135fdf9dc5c832c23cd7fa10ebea3a0aef94716a55c6097282268e24b971cd914c8f2f588691dc88e6209f7858516649db04be972387c9d5405275930accb88854ab2640617cb82c69787ecea84992cff2620af5e612b5459095e097d84a91d02bb2670b76bfd9bf0a174b0c3e0d8cc47874dc48cdc8c95aa708003cfee46756f8b0c0ab74247a116cbf9bc35d52b78cf4855f25cf31af491ac899298bff2fde3959fdc49c6963dd7fbac563216e753a28f2e85b4a9692477fd4f1d4966814d37c1556187c8452ef3381683e2f94fbda789efb161cf8f093c772f8b06082107a9618e1b182eea142a8841855f48a66b87d586d2b2f6755da3cd10335e28c71333465857ff8b05f9e24cfdf720b867397667b9e2c8a79c0e0abf0ecc9d58b0869979670af62dc84403e7ccfe064d43931bb5dc09d1e8e962d85d8d29b089987844448c5bd0494893dba5fec397ee8e37e778ec50ce6b506cad4868bb016aba26a05548a5afaa217de635cbd53aa41d5fd2f6a427591d7becc508f9ee28cad2f6eed0fa8879e0033873994d99be041461d44751f7e435cc005eb8c4535a0e5f9d79808c44e1e8e08b9314c17b5a1db0f95fca9ff82e35bfae4ed1308c257e97310853f48d63f9218a8316e185b1f1a5486bd917889b958fdd4d998b12f1b20d5de8d5eb048025610d3de7ca98ffff1e72cf9163c2b982a9290cbf1447371e80ec69fa32de34d40ddb75dcca9bd787e177fd5de6346583e02233ad2fb3aff0447839f3c08df46a6bfeb4046dc6202818a25c946e9c3eb7321166dc09633ce22f60f6a049e9cccdb1ed94b0a4104e346cb7c8d4b408a56a8618d0323dd085acdcd6b8e71981a0a8f2da21d70af105398ddbf8b421c3aa9dd5bd88bb4200ced880392abc24b12e4eccddedd77c1d265baebfcd2fe1d85616ad24011610be3fab41b7f6535b1915a01409560b147bdd205f8cb282ce3cab9877ecb55aa48777cf094a3c3573a460a79f02205b3e8ebc3e0f68f2ef8bbb4ada182b6709ce3292b55094b963e7383d594a46b43b75092510ac821d2aede87f717f90539b46b035df3203477dd28151470552d03b9040dc1991f82ff6f7a78d1ea9e71696c273afaa561a4a58c20092171a9b356ac7f741cc87ee2d106a67864a9731cff453d8c6bab81350691703f2327657c4b499ae3a3185adb6b1a5311a029f61688365af2da09e56f34d9b6cf30d0c738ab320743a8a0ff09f6b09afc64574ef38dd104711019106920d715033f615ad649eac10298acccbd3c571f7c6bf9849b13b2c32791b15d756efa08a9f5c0efbf7bae80f0ad751eece888678bfcd3dd81a091939958683df1c7ee2d31d68d700395c0deb595ce7c207fb028ae3d11329ecb199492d3840f68d44a436433df7e7e60ebd16a0681df74ded1e7aa89c9f67d073571398a0b8a0efbbea216b4e514d83a2f4cbf830cc584b5fee2dc7bd3f390cc9741304959aba601fdb9ed691fe7bb48bbc1c4f66e886b463b401e69d5fcc28328d15c34e57e1e6ab086aa34d70a7e430904315c5ab6370938023277f0042025fb404f10ad094fc9c5945097bff4729bd8d8e2991c23d9b0f240f3ec3f5c6332b0bf8279b6e152a22dda51ff289cad36f781b55f556564e39de26d51c5ba8d7558a66884c61fe3b90a4d805c0a47c6282a1f9b1869df887a3d5c6c8e407937729c53b34de4ea433a78d2c1fcd02dc1008ed5a7061f9c986cb100d807d343af54ea5013e9611e96b2a54ae53ee6d78d8c069dbdf7237f030c8a47320cf9ce889ca2b4307455f25c88f57920f84b2aae3a55db549de7d9c1f5bf216a3402e8a9c885eebceb1c374f89b4c8e3740ce9ac5c43f8acf5fa1793466c4419c0e963dd090fe77d1083fba31e8b3224897f7588110a94efd223e6f74d6f00c5b9e5b26d76b2ee3fc9b4cd81767b71624284cc0184c0f4cc2e8be56f19cb6f542c68f0b4473d9031038c4cd6f3b076d889256fe8799efea83c03d4fe0a8f7e9dd87f36396d6664741aaa0a2bb949fc9f9bf541b34466ec5671dfbe19ae41dd0f55af05e9dca9a6dd5ffba2a8f17647f63338dba276e17f16092512c8de30577fdef3ba93649422a2b8c9e2202138857ebf903872fc1d3e3aad1fcd54cee2b5e04b6c4464246782347b515f22e9c225bfa30e9911a06d341d8654a82feccd4e700a8b2c97da4549ae7d9b97e488a04b38cda1699a73aac53e5bb29e2bd1bcbddae0c4a272a5ee4a724358f49b1d537a270e53e1dcc539e1f7dd711c4bee1615528b7962e3b18f59826841440c0fdc753f0deabbdc4c4b845a64a6f5ea47d4c14cee6c124d4223a7032d1f5e05e3c9c8c40294c435effc54f4494d0eff31666c631579f7eb7d994f63f93922945b24e94b0de85eb4018a6684a6a78f44f567762cfb8b449a8bd114479357c538620f2bbfd64eee3735ad28ecba374ec744eef61b8aa385ab324b8891a6b947ef9c6dfb9a06c7a6efd94ab2aca66a04dee567e53ce38c4fdeb72dc7fab85057893e097c36b4751c2ed0f18d0566bb500555910c24c803001d053529053a55bded0dfd7b569c257764f0480503197d3081b3abfe2157e412a68205a02f2071e214d1686fbe0ca1686d0aafd3c3a5f6edf37920512fb04cde1b6076527901fa1b5daab0e49949dea9f54d04542ebdc1ac31a8e67894593b6d8dcd7fd5069d7f26f6ebe016e89d6e5b3dbfa1e1157d88bae794c3f758bab870d614069b410ae06c97b4f51dc1425144ab7eb47f879e58361ced4e56667a3a3b149a3120a94dc08eb6bd7f236f27ff5ae719c83b1635c768da53b1231ad0286e511695e42bd554b6d5d9ec43ce04f6d619f418e15c967c57b98340d73f92583eb8b4c10b24d5a003dca51b04e4206e8ef2ca349eb2ec714ba73cd52134dbc920a1f5e8548a1c364fcad3c9c1d423738c901abbbae35633f6585d366f51903abb165fcf9cf9e1f11caa52e0849ed64e37d901b57434416775928c08abc1c52ee1b30d22ffd6ed17e18378a8c26f91ad4086f13eaeb11e7835532fb7b0f001f0f573f930dc4547fd411d5e8ddd506ab7424d78e847358e2a386b8824ebac3f96518b68cc2ca5b050ff82d6ae683a730725903167c941614f628912f824c83e82f5d2d2fe133e23271ccc9257e63fe4f215258e4dafe1f18141894e9657d930fdaaf7e8f4f3793493bff71c2f50729daaa0d3cc5bed4e373c511ed897439cce5fd1e68e4513e3cc3bb930758d5748e43e71e1b8e43aac12c3cea73115730f062ae6dea0d1ef19f52b41d893e8a62d6153c35c967036fde9e8ac99acc76160732ae52fe6c46b7481592da0596fadd36cca8e5d631980dcc54f2130a375554ad57e225ccea26031362ae4e41d953fc9c35ff089b816423248f5243dfae57b0095b9e89885c91e70d20c0fb4a747b1c346d94d4c55bd160cdc602b95c434858ae333fe40d0aa39b5bd99b4c54c12bb30f2ed6049f5b731ebe5c2cfa02958f201618125e3566247b529d8ffa9e519f102708a26afbce7ea1f29253deff188f14066e8b59aedddad72fb4061e9d99b7b3ae3bef0642a442744d173a4ac6b34ba90568122b1529a3eb98d1325824403b77777011770fe04cb30ffb6a789b154e1d1467c6428701d99422bf71922d215f9ff6eab6b413df4faf523b4587525986715653e23f3f7100cd473b476a68b2b5da5373df4792f14b0f20eb2f3eba32970f50ae0e67f32dfaa0121ae38c1b81798b51bafa9e409d05a66cafbffeac4d2587b988413745942dbf9c2e12f1f6c8dce135015d27cc93ab1797be5bff185ad8f1475249b1992b7661844c1f07649991892a4cafc3a635190de1f0c3eb3e8c7a597ee04dc1dcb4f28cdc52975d9fc764ba76fb535598a756dba959c266417c33e984ddbdf2e2ef43fd19c3686eb6d54cb84073ff1c5bd133f3c66386f1d3737fb691142ae22441255791493246bc9c1442de1255101303968df075b60406f24a219a150741fa57bd945286791333bef546abae25eca3912ba0e7a8d9fc64994163cd25275aa98d664079de8cdf4db15d1875a604533861251fe6c1ce1725912175b8ff9399d6644c5e03715ae41a55741164493109aa65ce9610907739235e627a50767e08832ec32dd97225b3c4e52381ca935ae46e3c8b8391050ab16810a3f5aba8cf36ec293c18b9e65b3ece5a1769f08ab6775d47aac9e758bf4c32f092125eaad259969f8dc4b162cfa92fd078755123edf78773dfecbdfdd5ca00bc959bc516c0ae15254ac303b9630ec4ab7ac626044d97518f3b0eccf173fd14ed8837fad6b11a8a92cf190e76eeeecfc3c51d3c1d586995e2191abb246fad77276d9e2f5f18fdcfe02296594a2443a2c1743f258f6f4b828f95d900bd424830af4d4159a457b1d2400c77e8d81326812c6d594a2f14adb757689ba1b539de696c2fed7b53ef96751bb8c418a4b0f7989657fe8ff2628b5bac9e641c13c962daa46b4e6c9aa137284f1d9d185237b5f3c4200c1eb04d3f6144ce4cc78bfd0c129b1c9396649007c5a72ecde616a34330c9cb7538ec8d939b132277120156675691600572e372746de8585b0ba78acfe433cbda8f1125c41e830e48e2a27922a368a82ae00a2cc270f07efcfa1c19f2e85241466134a05991cbaff5e424151771d5194a037e6755a4a8acfd67664d31204bd82e21f46b0ba63b72ed2ad30cb6e1735e8035a399a629a0415f4275fcc9f54a3d93873704896ae3b42a8920bf897171d447b113851bf5f6b6201591c00c51f60e68ec96d90192cca34b379d6eb07653a8f505abba5f27456552539be14132e82bb8eecbaa79c5e5aeb0dfadc98b85f466291c52d28194d80e8f358dab97950691452ed26a6a815535a751250e85ebe0aca699fe3dbe75a143dc3d93bf8d1d79e9111cc9833fa10bdba8d7b2ad91e4084bc2cdc20bf0b43f746ed1b10ec60ee7f6a9335e5dab104087b26dcef66e502698d2cb27e0162ae1da0c590e17e681547cf6583361524739930dee48480dd815f7941aca33ae99e6643ac2da9f2ca4dddcd89901f8ac07bcc6b8ca4a0f260b4ae6ca1698ff587d1f5d62963fa8326e83ba212234679bf4139c45354308b20ac6479a8bfdab9b327e3442a2d25b4afa02c6c9ee996eab462b32c0b86af890f7e148801355c5f89d6dc67142c6ad1cc710c1ac51306a4b015c4318919f9c774f82ee482334da7b72e915d15ce13b957f970f171949da152034b4a44695caf6bc0607cffb5d66f8414b4ae12615962415a0f3c04dd44dde79f49c084d0342c56410271e50a48ffe822bcc5fce747b1b706cfd291f5c327a11e74f16e8e5b811ca15bc060caac6a059f7c021e65c9f6647e177207ab894172572ba784bebf038fea83b609b68ff33c61cbee24b6678741cc3fb963b6988674b2c70791f935f9d188410ae1404ed6de7c402b2085d81000cf2c7ca4bb3ac60415120716b4cfe1d8015c3cf9474247edf6a7f4dc82ed8e4f74a0d025a8efefba283d5fb283b6291e513e564ad9b5a9de6bde845606566d597fc110b4397467d6b3c351f59ac100882df0494898a2453593559a31fcae72e094bb34dcb114361a5a82f8501577462be25d685893ef135f5972e3d7270f1f3c50a375baf07e90f3765631e6bfe03331362138e26a783903c175faf11a4d0e16d26e410d1373e65a9ed81e83a5f9fe712ed4b3192c73a2ea18def51b9f7929475b3d004232264bbef708b53daddd9db428d5245f9d5dde3031a245eae63e79d7d491db2d161ee105a9ee756ae7ae047aadf69caf70b9e975a96e3ddee487d8f753b70408245e64e88604ea627a67fe486ba4a813f96e0ffc909520b533cb2390e17bfcf4ebc48cff0c903c2525240c7ebe2f597d42e04b20f0a368d6cbbac89d6de65bc410afb5044f303c7ccc4f59ce492ca547778b7bd5ae9c9f61c05d963558f8639d4f39e550af40ae7895422b3c5792d91c0b936d926bf05a5b7e14ec373b4b9950318c7d06edd21805d7a04d1237a1f5b40717867d5f4a14633831b8a6d05b19c5b4fcbe44b1612ba7e03921177f2d3e5527d9179025954afa2adca2bdf9178ae8cbf534175dcf9fe86aead6cbcb934cc8cb009135f5e2306a8f0844b6435581a207f554176f99649aa42edd77c37fded5f5c300837f4bc1635bc6f3b7ad11f39b25f04f55cfcdc837dc23e8ebda84cb41cd75849370f5cb72133d13d7ee4891c355edc23adafad154c923bf370df9e0311cfe7d77d66eff8e79d1c8fdd342a12ae222e0e992866eb3cfa3f294824b9a36c6427806a8561b31a84a9372d5988bcbc7167dcdaa1bc2cee9a74eb52241b06011c950bd5eeb7596cd4c6471fb9f68193114300a4757a77960c840b4109886f05ef7e1112da3e18111a1bf935d225a31fde3a5bf44a3946785ad999548ea22170bec183cd98cdb5f9fed7aeb87e300cc583c9d931add99042699989862c4451059a4bfbfccd2953a15e488a630e2673fb3c9e2ffefad3021dbb3aebd2a8498c97e7136268bece3b7616959dd138660381a27a450d5bc3727d4da8f7adf37ff10818ddfe37e4c42771dbf4962691034f4ae943808dd258cf43a89859e8526d503f6214ae056d016370bc746b30058e98746cc14c6afb0216a669dc0b1cc5a4f80d426bab52502af6f13c5fedc6b7f25f68eeacb10a6f1d8761750b06dcf45fd9f32770a26184b7021a7cd77228d64bab3eea3a3bc534755f5a97c7faceaf7e6c9cac1473bdcfb92c1ab4908a9eb5cde531db0943efae19afd1e6fd5b1417e7592027ea03f4cee19544263748aa98fc2f65ee15690ba1ee2999ed301701e1e1af08f749d6977420bc4c02c41402dda1c1abaf8e0b648c355842d80292cadaa824eaab3831111f13ee0a634c7ffa4ca5f497da3f080a93297404f56c269c514e16d16fd9f7eac5c6a6a3e0bea60d5dde03ff26da732a253a7a4708f43944a874bf061c4daad4d6c0e07795e8a32ebcf55bf1e2a953653c3c2ee6e3778e013044f17d971bd42e44e62cb2c4ebe2c37876326491a80b79f9db2c6c5b49b9386d19d06c513145dfaaf6954c2c1634492dfb07b2074a944b5cbacb4eab1765ec51e4428f3467355797c8cb029bb6f96e1ca64a17c91ad4b87b1beddb290264aba2c5bb604b5705f2509bd8165046ed80de975f5b79d37b111ab5a070bdc628a78db3124bdfc1d9a084b9dbe5dd5e7b60bf27f6783e9650626b9f036fd249c724ea8414fb90a11530a8528c9dca043cf96b904fa63a17639f0dabafc09080bb9ed75fb69b42b51e7e484620ab1b1dc30d58cf7d8f1a9cb8e3fa1177600643d6a07eb53632606d5c47b2a1e07f65b2085691ef6f265cb3fa3ade30dae0645d8f4fd69d8fcb396a22eb5ce87d7d1176114d208892c4657ff48fcedd2643ec281de0082cb96107d8ba33ddf6f34cb6bc2d0a236e9b344ea522703a24f22326eff970cab0b32bc8ed60dbbea82e2e93751a991cf274efd409cf083c5b98c2e68939ad590e5370170c5148d72ac6975feab4eff667bc57de349def86ab7c7e4447d8a4c7af683003dbf48c2371f7bdada62243205faae7b9977e8453a444f503a4941c6dc4d8a438b5b1f06b4b239f748854077013d9e8cd15777f863bcfcd51a44c548b9cedd8e53d8f9abe72b260f776ea8391beffa3a4a78b4b0236150193176ebc89b530d9a7b65d709c56885a164aca3c2e119f8a342eb8d37d44237885c16af1996095f91d3d048f8930c5eae6b93da451b5b5cbc377290ce6fe2e26c2a5faa6c67fe268f25c307bd11f4076d31d57a28073c5d967e4cf147ec720437adec73ca9aad48a6abf5676f9f55ce6528f2ed1e293735b2736a7b2db521936cf13f0f515f8a313ed047bac77738dcb962ebd02d3153e5b509f08e5b4065b0a0ca4b69e66431f011a8e1bed8b979b82443c74ebfebacc8ef307e6ad6b7fda19ea1bc60d0577aec11d6e017db2b317236916d654af98f5117f0c4e84bff658421f88290999261138e84b2b9d43a4b3f1c54a88b76a02e9519d67ae2695d1685ab9c393374e0e966e54f06614f288ea07cf75ff46e20894ab49995037c8ebee5051a2826f293c5556eb1095118f472456bd66ad4809aac1b2496c102c753d06ca0e980910c0ffc240d9a651afb73cbfc29e6a882ca2197217866bf9cc69eab9a3561cae186e042527da96ebf32dbf6b08c91aed97214d32a6aba2e1b47957fb788eeea33458fa34c61b3cd30764219a928dd469f76304495733bc51a486939f95b90d68c413cdaf996961271c743959778839dea2830cde8dc089bb1b7867a8f446db292ad0f9fe37a5ebbf01338e9ede65868b341b4a24e122bb63ac5c61eacbdea1130618fec4bf544546e9594c516e8b765c734e84679e40055d0e87d91db3110e51dcced212ec83cfa095ba0f517ab740e79ef9222128ef0bd82ebbd0a5732ee78b14631d27f33d36aa243cd2024e9fb753f64e772f41c74a6b7470bb0595d1a4b285152309998d306dc09513de67e485d2ef51c0d6ba95bef5154cf3073df4c6677f7b456975f8b56edc4d00ffa145af9ad3bf2bc640ee4cb08dc38cb2e0c5b8344c887c411bbaaa7208ff6d08e7020e0e77bc78dac420c6de5bdbd02c9295773834ec5b69b520d58ee58ccb38086bf92adb1b9b53ac08fa161b7774dd70f47596d5efe5ca1f04cb536af370d8cb64d30ed8f8e9b8a4fdb6eac998db551b896e3e17f4f53ea12c6cdf59219a49e0fa09e253320101790403dd269844942a513d7a006e69b4d5fee42da7af054f4ccf6c15f6a05f009dd183ed8e134aedb1612b7125f5a6993c48c74c495f2bffaf65ca26c80d534979c2c05c02caaa6407f9d28d629a0e430a25aa0253be86d92434a8091d0d3c9367de1c35f425ba2f332d43cab58c43b3c1a06b7566de4d2e3bff446afcb9c73ad8958a0e3c74a68ab607eb0501cffaab42305e56e66a6f03ecd042607c60ea2c99a5d15697a5f777e44b1606696abf8d4054bdaa5a0265b9540eb26dde0bcd5047255591598997abbcff95d0c002d943d58dc57ce1d5ff7a08d1b240ec35774a97089a7e127212b514f71312b34e3ee78b9bd1d3083aa48f66a1e1fa9261ba24ed2f87c79a23f396ad5299668ac95cff5fbefb0740ec9ad4ab5a0ea1f8767901ef531999722cac51f6be00e8adc43704cff3926bb8c134c5e24fc9fce074a6400ba138b56364c97d82c304658714092f2102a410dcb8ea5641e8d01086a4e72aa671b07f6a846d8cf3175c9b21fbcbfc1e182e958f875613d2662faecad99786e578156c52a2ec89ff44eb5a1e5847aaa96c6409375fbaebc183bd219113a0b3c525a70c37480cc92414a3ac3926a05211d87b61c5e2ea1136c557b3cdc110887ba750c363e3411e3c3a477829bfb8689b78255e8993d4b7e5e52a18893e33a2693d4c912d0d102d038569a318f019127e29e1658a39f5c6a9bf01c9c104e6b8a3feb037a7e97daffff31c2a75944d0f4b039dc95f43287f34251c8ade9ce7947e2182139ad8f7df79847702376b83b260f8520280130d9367af02fc65b99de5038d26cd8abadd3e84cf9055b88ef18b58ba28b49b1975c4cf0e14b1b7323020a41676612e73a00ff0983486678dad34af80111a18246d60b26400767ce416b1725adc1dabf65907339f5c3bcd79f1a28a1622087e80c0d08091a7188283ed04d68bb949b82f698c9e21d00d7eac49f8e3f9c4523056227f747e4df6be27ee876d1635cadc5e3678bc9d7f446efac37abcd2955c530ee2cb96318a185ff45549b011bc124f9eebad63e0b3879ca35b34d08266e76677c8b52525506f532b0fbbe1bad85fc6b4bfea0b5187ca0bf9c8e8f1632e6b0d2fd60b824f0921b4b4d17e945779c998aa583a3a0b9fd8e6278f5a077bac581dd8063c99b81c456da079cf8e02ebab11e8aca45c913802634b5f6c16f365b43527053df7b9dab13a98757b6d59fa421e3efb71c7457e5dd1782e0e5db5d6759cbcc40a0e61e67904bedaea7c9defc256428670448b48f201c4eba19e060bbb6891667e19002056d1b13bc19e4175262b086e6663d694cc9681d18ba23523c96e6d63fd74fc624cd0859eaf84e8f51904082cfe9daa6067dc88d12beb15dac15c9862466884d7ea64a10893208ec179e8a1c39415ae7804d4accc882b36f2a296af16cf8e0a7e0ad7036ba52c759af077ca44924c9fafbb9f525a83aecadd80a1e4a972e12ab6247c1e506b2f67eb47b78aa000cd41410df27a8ddc08dbe58559ee4a15faf59a411cbc27224dd6dade1dea8fcf17979209cd778413a30bc85cb040ba75b2aa3596f2ed7880def16107279329a83604eb1cbc0faa5663f9ced1c96af517a85b156d73f227ff759fb873bd8bc66706481b1cd9c7efaa9aaf655a6c00e05023070b98460096612064804a73bf0094c9fdfc5ba68f0b13c76233faf9d6068d4996409f2d590504cb85b79891ed16a2cf99f8b369f95ddf738ddb430c82aaf5f3ee5a10324093dad1f514636449ea9b33846a53eb6bf750e058110e54ae0e19c21644c5da7dfe01078c349b0fa2e6ad112ce44e93faad0a96b50905804ae912ab4e932ca54e14c5e0c54a7bd93363654ff0ad2ddbe99293f2a1de02731bf770a6cf11861c9517d39760ca083808255c614b6c41b327e3fc7e190f413b298dda80d4a97e86831067c68ce6634d4119752578454d86da157b0a0a7d9c8616e3701c25ba9a189a23b55bacd359d80a6c820fa0a7ffa0af553c10907b432cbb9ac3d0d92d769dcc9459e2b21b6031fd55be1607220ff8acc151d02dd6143d48cbb06557ccd4e890c427354de58c8135a193488ca9c48f780fb6fac71bb22f380730242fc7d2b23d1826b14ff152f0cf05fe6c44441aaab384570224a2e834876791aa795201b95a7cfb3f8968396e67d09fa581775d798c2aa4d27f5d93dfd853ac722e9da0d3d118de0da41cd5d4e4a46af1150be44cb76aae30f6c9300b741e4ce23f920fe5dbe9d0c23e6309fa719f29643ca025e6e5dcaa4542ae3debf236ff7ee013d5551d3e9fd55db1ca9c0b62f70097025d7add17d727bf23d3cde96bbf687673b3d9093564fd6cd9adad34986a2a955d0e674033d4f61c2c5d758a25c39643c610044da8d98e790c7bd1bb741d4d2c306fb14bb86970c7c9e19c095265bc6a347a470b70d5089ea926803a9a9a0bef42bb154b23e693cc174c7008534e5ec0e3d0f08bebbab50bc24508150151256302dc3f7c937e6b26fdb69572ca72bb6dad391f100bba64b9b881b6ea82951771efd20902db449c177445724a87040192d5c5080dd0c66f5d58e626460caecb56390b4a7ad7681ad84c3592ba02530634540e9529d18044b44c3745c597a70ec55da109e01ce530ba1fb592d37a28f812b8fd8742c32fdf57ab506e415f1afc7343bba798111407d58153b20c1ce20871fd35451db08e40387cc5be19a9aa719b59190c372e1970a27ec4c1b13dcc6781476012be9ddc311bbfa0c769fa499cb4cf5ac298a03aab6145fa576d150e2c08a4ad938c8e4b6096fa3c2012d729489c13ba530cbca6764529ba0b9cf28970c047ccbd1c61e4f65cdc09debe5250249d79c7c540209d20617f0f09a39691c41632335ba9805793a65b2df786d6eece34402480839304e3b496f6a2b51614690759b413d250eeaafe0245c368810d1f895327ae3b600d96cebd66cf35b562d490bb2dc08f964f77a2a4dd919415c95f53d4af462f95b9cda196a4a57103415e6e0a31a53d371218819df7c444f479e07a88ba65a237aecc87ef596defec675d11100c78c73425e8c9de5bd3fe6256bbf78aa216c619acf3153da077bb9ff0e6791fc92cc114542c6bb635f31dc39d2e90f575decc404ed77af967898bbb8619753dba645c4b2be55992f464b755b300566f1c27c389462e66057fe69ca2ebce7c41e0f21e8f1aed6200a00006e139f8d4372c75e278e282137ed16b94f2a1a5fb9c03b77cb3027e4a56b49c8c9993f513640ed378c339366fbde2271f420efafddf42b13759a619c0371812b1e0ea90f0a1b5ece30e6618a68d5922a64f5f65b50b642ac9df564a8458d4ec1827adfb0912b2baf39f16dfeb2d40568523b3b8e83c2adeae206cc695b24e8738a770d97c6f19e36a3a6246c28b32dd548574e7544307776893d74721ab46f7518e4c4722984e9b9375db72681314cb0c8b91288584811fe1b99999ea92fb4edace2a2369a51eba6e03645cae53a1aa9b86a7f990528542a7122cf1c18fd506528937de1c72a683de3c91efd1d65ca1c1d72f9d84f59f63b1b49c34adac8170713946ac3d8fcdf6a8ed811c2e4ce2ce0a86a145e1ca4bc2aaf85f7449ed43a17ea21a8eeb088a9db5d57c7b4728c825a0f70e4cc3ff7f3989505236d2a4737de29acfa177589edd0bae5ff7eb2ed96a7a7ffc5ca947e9bf50d18713d6689a4dd3db20f5add4d516199b6104b77d7b02fd27ec96e65dd71edbc21c795faf61bd6803b553d500bc419af0af47762e67a237c9d2ec8cdf54aeed591ad7bc0608916bcbc77fe71fed7208fe1264bf215e09e9cc095b91b221b6c871ba869f357bd2f102fd38131361ab3f677378a5a27f4797d6f456516179a8352de214e976b2e49139ee2b8e5494f9b0d60a48598923f01042acb9c305792359f5fd46c52178614fc6a92b4d2b7da78f7fb15a77c4f6e0cb6456db2477d79a5075674cd088b5cfd7c6b6b646e651970e2e246f7ffddeb17b8a266ba8b23144ea0411f9aeafd9128b074901ccae8f55e022cfb5f66243e6589e5156ae1065c629091d06e6e792884bea4cfe0e97da261edeb9b6837c267399043750655c7738294ed373971a87ba7ad43cd11ab01fceaf0d5964ffacc78e6bf25d105f422fabeb10da3fc66a517911294d5ddbb872a12c217b4994eb0d6722c415c59015579db5ca0405900dc18d501b3e80f204003eb7785091e413f4467628a250c79a260933fb8f10651dce11de7fc20cd0259224c120d4b3bdca74eab8b3a06401be26f39cb5b1cecc91fd20d0d528c428a55aa617d54cd46a5dda140e6713f3ef2ccc56d1d60e359056069248cb0e86b20e3e194e9b8a3912f525e6b09451ff9b378d16dbe6d933efc082316b60bf32f5f93661561213445d44f5eadcfbf9f133c742f739412d8befaac75febeb9726dbcc985cc573a1ad5993606c6d14292d88fa0ca5ffd2b328889b27c4c2b367e354ef6b927d67d6761831718be011b96f8324188acc9c6c7fec8ff9a1f8a2d230778d40e154578a45bb5c9592e16b94a8347fc2c2ad706316bae93d2c54921459405a7ce6b1c906055b8cf686b6ec7c12b925b0c34a77b959bdfaf40e4d5c50f1975000aa044a2cb1b49eabade173fae8f7b9afa0bd21908a93e32a93a2eb88bf07c50f13f8cca25588cb5e04cca02e0e1c6aa38aa3724feab53790e8e049f6265f1d40219a4378dfa4e370d56206f066cd0e61f13a3a1686d27df8f65e67477a1bb8c063a7d3a09defebce181175f62a5ff594c6a6506ee4d67dff5bed54c3fb601cc63049c3aa53bfb06a6fcb52059e4f43e7f2c7c2c32c8d793db2333112be8544ab6d1cc525435447f4c4ea4902c1103434d7fb4accea0d758d4641302be5abefb3a537d237331d3ce339183581c1dd78b9e5910a52f83a0df7dafc0288f08a40e621724cf4436fb0ff4f19dc069e27db37c1e939efa168960cc54c724fe51a54db265722d702a8b9d72662976b05b95834e175e2fe5192ba02a4d153458d719d5e79fecfcf957161ccb51e838f5068c8ba6745b5546206a2e69d5a581c70791a84f990cd9951a9fd1d3905d49bb4f1d6d5f77453d6ab98193ad76b8c7e5e6bed906eb137e686a72eac340092daebc8d7cf06cdcdd18ea6de4b74cbb9521077df7647195c55e0587d6d3d10a954a075ec6722e4c564ba35c29dee31ebefbd99bb5058b3351785e935a08161975b23260974c717c41bfed637734581ebf0d0c250838850a4ed321daf6753757bdda8ba07531a0145424800a332e6c958a04e71e139ac44c6a60474f100b89333b44ddaf39362c906967b601aa2762410f7d68a74028a0d7ee150859a1877f794dfa2542640c14533b271fee54f059907c0085b3f4e07d22be638546ff465d244c27ecb37086a84d7953a75527f96a163a995b801f67bb06179de9fc0871fe0ea3e3d634a3638fe2e8512003f84725e596ace23e13a14bfe456539a4d0c92ed82d33b0c3be61cc6044efe9a43ec189aff21aa47145c99c8a9f0e3b7f944104e54665e4f6a264b2b10c32bdc8916949d49d89ec9aadc92e60b0b8f83c0524eeda20139b6fba23b54b834abbf3f66361174bda14ed337cc473ed52c236ba87f2a76adae360d1a9161da5bbf1810c850b73353ea3e50290b42a376fc2db5a80a22777bee1b26f97cb806e957f7480955d617176ce263e781ce0f6b2f2b09f3f1e8e41bbce38bf9876bd14e87bd6f93951e2632e5d57dda0daa61c82d432e0b2178baaa88f9b76ff348560242e4680d170f177671073010ad5d4e84be915f0889fe3e3907cce6af5c7cb9c62a22d4fb0befc34d3aab040dd548256bb120ccd5860d86bbaad25d2ca1d133c2bb65e15a3292a32ff474d2d2dc297cb5b49ef29d929226d81f58bae59f819a54d90a91057a3feab8c31353bfefc01051e5f434029d2e8e9980eae5ce0aa3795b01c23bf3f71186789f3ba58319da893ec4bd282d383d54b925a7d0d2b2bdc310630213e0077dbc6c0f90a1ec788ee14867b013943b9f5057598599f40edceb17d52c52fd1e0bd4fe981a28834c4365867616fff49be7381f35eb1d340b1e54ffbd8726b148db16dabd9648ccdc1143daf69aa7f97159d70e354b360e807e396d4b208d0f39df3128aa6ac2606061a4770fe2d6058a9337404fd71bc1e716aa2351147be3f72851ce1c28ae8f7719d1281b9420bf01e0d97a09513b8f4033e13eac71e1417d858b831876a207f0a178b4d52b3f58fe06e9a5f2b8e9dd4c3ae1d0cdf05b271a25ca2c12b7dd04c7a7b1d440a26b04516dd849cc417c226a33fbe8a2dc5d900fd1acbfdb79dcc8b424b21f4bee42e3fc20d7e5fb2738e185de3c416d55cbcae6bc3ce74b0340fea67ec958363f1cd6ed9473a84aed38def0b601640cde4c54429f78f627633893d7a4a91cfac7acfc756303fe8555dde52b0506b10717cab2ea43e9f0670e0bbdd4f766f920d4543e303d625e0cb35420e286855ee2a59f9789910ba49f9fbd243cc440576dc35bd2bd6001850f2cbf7809623e23accc86b4a0bd3c469a5bd2d612facdf2fe28aa27a8f03ca8aacf1d61785a3f669521a3e7166bf247f5250391570763a36ef2b8857c8cfad1edfe2f9ad16bec4c6272cee69460c1f1de38c1ad12a000baa1c61f8fbfd4542e40fc54de7f7e529c2b66e2b077304c3437449b4e196c69b62443bd9ed616e157d2cb9a8ec2ef48d0218fe51d359ca6c6024519e3371f3ebd92a0a0a45fe530b5fae4ee646d59ad182f2cbb0bf9e41e8362b4453b2ecf9b330ca4ac0ec0aa5a07250063bc0f2de54bfda379b1fa257081a8a592d9a515d0ed610d569845f435a6eabbd5c3ada0748396509e4e638357909e59b4e52c7d56cfd7fc253447f32c5ccc98add9d9f795de8f373e43753529a52760ac9ef475f483e94ca032b0259b9e7e3389c7583b22d0ac610496dc8dd57db47174c6b99b6951fd0c81fd960fed0b5ae6e44cf59d508b4c42e3e0f573ca732fbc092521ae06543981da90981e8c53db3ce39c4d88609758b003c1c29a0d27c93768be082deea55d5c5173d1dd767910700f72042b971c222f5db0356a27de5dbb325c914a02c61785985766f0cc7e971c3e2f6d24c89dd17b42558ece63f4af0842055272bc28aa78fabf24de8f888f4112e67a947809ece2f581135c7a53ac9f271a19f7f5bc2474d02f161388f43bf839ef05510d65a7e2b0d1525b6326fbbb38e1e0da130900b903628c913678c4aa21820c2c6c72203654882e71972224be81a74ba310f55131b3226617313c5ef126c39de7903e0e76ee47aaaa5d1af7142c7a14308e0e088a2dd7331746feba1e17e8ab3fb578921cc3cffa110153089b17367a0827ecb8d74af39730a5011cf8e308bde84111f6ca7b0ac850ee4bc7b933c8be154b743b92489221db3397064b2e110ef064a9738bc73d5a651473b3bb9225eb174de3419952f8b8fd8dfd734a3e7453f6e0ff079b16630c1811a4f07263435a20238e3ea166a8345b5e36408b4a1a8fba55e9305f932dc2afd1c9bf4417303a58a7e1e032cdccecd656ed29de0298addecde468d7a3fe2c6f991d561bf2252102e38c6220f5a5ebf4f49d8ca5ddb2e6c6fda146cf1dd122a1f1ccf579da3ed8e9647f776ae8e3c98c45ed8504752ebcac7be2ce2d164a4e1dc124b049c785c925687ca2fc2e4aa72868e004dbb29142e5bbbd15a3d2830aa3a04fa780d42d1659e4dce0187df9959f7acf92064975af14c0fe281d65baa2eca6588e9d5a7e3740ed1caeea4c31a4422521ec2122c2f42ad4d46357334386bded94bfa339ff0110b2b9810e313ddfde16c3ab689eadb42c5aa9b08d7ffe5ce29ec01702ec46d78d049338db02564fd5725d2886de2179aa37f6c4e3196f0c1bd3066ca744cab3696c1a8793cd17ccc881deb4723f4a3eada78c45cc23b86c0665464d5216bb998f9716223321d3936b175ae354eb8e49bf6a5a125fdc1c6cfa9df98d1b7924f3b40b46a7008f2da22b839687f55883cdc68636da2c929e4af1cdcf02b89bda0629c42c9303e964533b7ac257dc395970f6b43a6bf52699869fa81129d7bbf844cf6f08c5c454b1e737ba552b08f0de803d3836d43a30227ab70dfb0e1ffe7c04637dffd60b992e80b1cb864c1f8837cefca4bf9e54be661c1d762791b9a807559653e2cf5d29dcba39480387d3444164c258f539d956190ecf05542d633bfd94756635e9f98b1f8591fad6bb99f112c3c00265193d994e2313b5f352b49e199bdb196942482eef16544ce6698702108b6df7a8b1e45195143cb42e05ce92b40a5753ca51c235f57259bd78d12c7e223a44f5bb3683c9e3498f500d3f592162f18e2d3364520567e5ae2e219bfa07f0948506214bbc93b223ed08e81a064003cb275cfe659db49d3e22bae015d0af82a38255e1fbb0b9db0f4eb3983b4244174081ac9fb6122c5919b8fb294309fb97cd1e1076890f507a6874cc530a110141f61ee1d5c9fc439fa7574c0c8605bcd9d1401375fa353c5e0fb14dd68da8e2d290358a4ddc21d10b28e8ab992121ab780fe5b7c4758743d101abbb89dd3ff4897959568a6e7b323d6c376ace099039d685ad57b1d10a0f635fe2b7927be9f4369e9c55e4d66858a7888f920370e1f9a3ca4335e5a33f6370a920d4c489221261f8b7ab773fffcf52cc62b4ca68c63b845ceee230b37911c4a233dc51a316929eceabd27d79141d7d983d8c49b603a5b2914658c14f5138ea61e53da1a61b63e14bc69052974ac8d9fe8704980784a53331b473c69aba41e312decb4e0cd429114f7881f7db36c288601d0782b5ba41b0113d3ae2c905a324fef6e12526468c5dab06322f4a6fd29419bc0d639adf47e72a8f26e87d4115ffd75924f8d17215e1ee341c3f5f5fb411f8ff1f91207fecac7e02e8ea0642d339022e2a2242ebbdf988a2c50ee0adb6bc5bedb571e022dc7c8d758bdf0b6472b1b7c91a90aa29c7d9c4ff94200c42799e227f19f92febf7f97368cbd77e30e7271eb439b00d9b04b4da5056441aced7895d00bd200627be4ff77a032291f3637c6584f0b81da1be973400abcae09768b62fb01da0d296ad54d5a9efbb8dafac8577258f04b412b61bae5d44c22905d3a2ef16f0994ec536ad0999892c3a9f4ccbb5cd00424057ae05726a8fdaeb9c8f32baa043e145751c83dd3766bc39c1ec5492f101b87a8936487d588ce286ba0956ba2b55a924918eae5564c65ff4b8f502def589b43e13f669dd6599fc87aea603eac5338328d31b44ab245682f6d9d8def5db03a9020656d8f9a6a9428b3cbf66cb03445952696dbee54eced3ede33d441f5240d7886950bac1a8019328b6ee06f8e424825d9f8a1a321f3f403cb3284f836dd23ad1da1d78cc44983e41dd8994277ba9ce76b07df7554e83925a2636c490e96f5a2b2f7eda99d999f0bf91b7dc29d9c15e1f989684221dc41b0674519e1a410d7955214aa4f14c5d6bb7b99be5092b884e768c60e643c5d364983876ccdc7aa943c04592e08f62c71e00a86a4cea21c63f731f06339918bcea30c729613c58b5ea06e332f81ac2472a15a79115783bf6a7eb8353489d6c7828aa119bb376bcb04340ddd297d4a0bfca93c4018dfcac728f6ab2e37ce9191243cf4f7c970b801b662e1efbaac337768e5191557e192197e09efb9a3d445befb22e01e691d63e0910cf6b8a1a9b3b5067c24eeb7fa24968ad175e5c17ca5615502384cdc29756c7f5678d85698712305c8b2e103e702d00dcca80730c4d2fbaa84f5d2ceb0bf6f1c7f404b84c4ee2e3f7a3a92a74f67a3bd4c30476fb83aed00a8513429a384ee39d0ef1f78849cdf4d97e915a90c3cd69ca57a06b9aacf0c093ac502f22f60fe3edfd0a6d51da4df75fc70346e7d74fb71b1edf4aa79098718b20b43f43a19a6b363d64cf051a68b3a96b266f89d56679ff47099fe2e7b9c7c8d08966b73d254e487614b790f5c2707a9bfeffb597d1369f1117c7d444393353ed8f7f1923ccf472c3dbfcf3b85218cee229a723402897482aa6a586f456c22880fdcf0ac530b5e00fe0ba3bd196fb066df700528d9abb57e1886658535fae892017a954a8a9ab8b8471e82d101bf968d1e531c009972c2e01b70313cc8eacedcb9dbe8ef3d67db97954e9d68353987a079241aeb11fafcf2455638a379e11bb40fa760db4dd9ffe419356d832805d9864e20af762812f04cfdc378da7e3e635eacb3dc406ca59940267f663d82a2e8f8eb2dad414b337708a6b9ad37ccbe75f3432a04306570fa843b43db08a00b6bb14fec29706f7a93875e50cde8ad9c0a571b5830650bcc9ce72c0929fb2d10558034d9b0e022b12efc708d2d7cff3d9fc1a509dbdf6d8971ff996662e7658217dd7202cfbfc045c648e1aec1476660dbf0719db4a37f2455365824ff1536c6aa070b17527072f5bb0b54e39d94404d05c335fdff5847f61c86597fd47c0e800e4b6e3be8dacf71e0de0c2d2828cc3a34230af1f76930e3a205efb9deb1325dae8e4c53bd9f8d68148ab28022c1e428703eb4907314269acaae435d13bacead5547718a9e84684de8c6193f4c3f8b474cddaa93224b9d7c583001db389b557e131e9dd15233f39c4131340a77b77c2d0923e519ff67e13490b3d1ab05c6c2ea5ec17daf333646cb4064820cd1c857b9043059f748a88e8dfa62ab3bad1fa6d3f513c86786fb800586d58557d5000b59dfedc09261e5c29254d9868ddcec1e05326fdbf471bbfa46543c57570578ab9d71400ecfb0cedee14a8ecf61cf65654ab7672a5a7ae2c4bcc983dd39345b1bccd782899d1bf19edf70dfb29d018aafa34445b151c4711e47691fc6ef56108bfc73fef627c16b629dc3ee249b42edb6fffb61121474161339e2658cc33625294e3c8fcded650cd36ae8c4830eff0bb9179ef2c36643aa9535cda716974bd77422ecf0924fdd8a7cb4e06e0c2177089627a3757d0402f4cc3661b64be3fbb5c94bbf29dc274883571a9507e6256b83028cff74b3bb4986711c309abbc8275954e7759970702a483babd5e788688630fa82b473d180dcce81369e61ff282284a7811ba71c834e25c63ff7a7b491f9559cd123a114924bb9cc618c262363087a9e2c4b4b65f35af6b278a4a9cd7dde3f4b2c92f4a68a82e25ef77810a995bcff9f836f5b2368950f2bc42d2a8201a25d31d146f30df24149812fd6d5f217986d1a01dda16b0f513b4669b18071b6ec21dc1bf2d9f30151b95371605f1cdf75cd52d6165b5d92c9ae37010d85411ee66bee22b6b7cd415feadb06ac6c280541fa1ba0796744299731c758e2bb4f959d697b4f7a7d7ff71beaa65aebe3c7e209bc6b73cc077432829c9e5733b67aee6b7b0a3aa8cff0fec8ffb50f30e5fec3919cd83d8edca5089e7b7ed645906c090326b3db224548fb199ef4e4eaefb013a36c7776b4cd0ebf1e6555f691e2d062a8547d57e0f99fa4741e6eb7e811aeca4702ae2bcd02f16e84828e762b7fbf94b69a351b7717f6d261ea8d5c39dd1e213d1eb18a8580ea3026ce639b431ff603922d3a209ecdc2da8a17bd5344accb350cf7f0b1a82c0147933bdb29890d6900851910dc486ba1be2e677bd92fba7ff08223165fdd514e59857d351833e9450dc728660b4ef997186ef52d7d73b29d4a979db6d7551196fd3c712d0df79119343aa50c529006bd43837a3863c4c967e7304ba66de5e1d6c78005cc7358612368df63138877dbbb6a6c90eb507ae40333d987d866650f4bceb1d6eaccef823059bebf3f31402800491dfdccc7b08947c9eea4833e1f899e3ed820ee4edb97672fa7d189b938658a3db92e54e3cb56305103d4333d23677e8b8077edf54c94399edd2db22c2faf9edbebbd631dc4137c6f30260c399ccc8478c2a30c96d4ecd301407b3b409487c4d0fb9b9b50b8523ace1e5d1bc39582253270e96a03b3b3d21fd3da8e74f7f147fbb666e67910065106b0caa44992327df8d3f5f16e58bc7af1bcb53308454abdd4b327ce6b3a49815e7b482a7d6d50ca11d631637fc95da26ad436739919ee2de421c7bddf131d38c78ae00e276e56a1b60baf6a9205b195da22567a6127976d901f1d2aec2938486c9027688a7b18622a2a1011c8cf57ed2726c22c158bbfb9dc57f0b835a0fd096cdd113301ca67bb9e61e4bb012fb23aa82b4c27cc50968567d175632075735ce86bd593a373e474663aba8210ba80df508cb4d961aa0a82058663316fb412f510aaede7f228584460321ed352dd62f03a1f2adef4ff18c5c51c9e7a0a1f530d497209774be15caa1351261b756934330fe4b39545c87a413e874e29d977665ee0abaa3cc20f69ef30dfa2178fb28afffb103dbb0957a1d6639038fc40799af8c126aee6c000aa6c111c5ad162b438747df50fe066c3220734da6fd6ddb0f3c6095646be2e507a2d82c68a753a4d691185018603ea8a1e5459d705c5c8bb009f75faf77e38ba51dc593832ba4a63ef1ddff54d3e396127ecb640bf2f78b32e7a292189ed6a02bc36554734f7b19c024697201c7579946412c03984970e3da9247183a093b074797099ab2e6fd83b90ecf408004655bfafad588af1048225ab9e6b65da4da17e51600c168e4969a462ce1f28ec832984ed7992fd2d6faf322f3eabfbd66cd00efef6ce7d0635e6807bf81dfe8f0cc463712b2b1eeb971229fe886a31ec2ebcba5a56935adb65594a507aad4dcd3faa124c13ef42aba30cb1b119208898df82c05c4f4bb21ef64860b28e50842f2e3cb574b07e85949c22a24e58a138cf7715228f52976103acedd5b9861244b1e3f837409e562379b70ed4f37e2fdc92c909637f58da6b672868839efbd16f79cd4ad7ce8e94abd1c6ad7d3c29f215d0c4c94ac11d9ae3c902c7aebc4444b515dddbe93149f373f3bfe8fb3475ae0f320a7621df24f870f7d044dadcc2f3b747f53d942a48e9aa9de068b141d14e8776f44ad96c866d132b965843e6beee0439cbd770b4f725a6d61cb681d97c26410184dc39a301e7579e9fbeb780c72c0df3870623ce32cf42b96b95ee63cde8a726b2a85566d8aa8c70af1ed3189d11bf9f3814ab518189a31fd214d6f15ca7dc66c44e593d3746f563692497646de0d79cd4eccbf90b27e8ebb8b427bc486320285ec9f91e4423f0587a9ad8b6522f2571e00403fe9afe43a95d45786ae9af76d3eda5de0c761a0b6d67ea4abcbf46881154fe9c98e4a1a7199efcb44a003d60213a87233b8df4c19f61ccb8d3aebbf56c44ad8b4751c50ef619ba7fc63c4b1f149cf144f2f5709831fce283fe3d68221f5275a6d261eb365e847eb180887d21c3e36add55c9062b915bd75e7403c5a9b5239a9099ee2aaf3c988204ff1b35bba0cf0a0d74f92ddc6c8930e320f312b2f85f0fd5993ba0ecb4b2e05e4c96ff2a695fb6097b35d8d81cdc903e297667b569d2fcd43922cc2d21902024e31d1e7daf0f2f08afeb28ced938d6baab059e05a08193bfa5cb146d6e8cd0c2a10e3f3d8b0893d1fcf93c72abe910f128c4a9b5e6e801bef3056b761e973bbb998841ca7e2b53e8f4419104ea5ea3782875069618598513345a6c298523973d1030e9882c88f9bb97090156fbf28db95d44fb628028d53b9b034815d2819afae6ae7a61bab0b8816a93b33a3ec0b10b01b317e28ab6ed441f835097b652b43d099ae5b2388a25de79a525c15f98fcfe13e5a4915dc6e3752b302d77bd4e9549c34c5c8ab3d506bc074451a283d43a54d31e81899423a01d5a49b7fabb192453f81f328b91864a8f1fa03875a4648b09d2bd90ad33441c18f6c3be4aaded1f105004bee6737457491f8cf4f8a1e5151663f695e2251eb8955655c6d2fdc1076a275f6ba55d34605c21c9bfb2b1970e141c0d671c08f9ea21b938be9f5636a1c0e5cc0e0b315fc0d5d857240a2c81ea49b0124c68661dc9e9df8d3c770cae0ccf5fbdf53fdd79ce0a8937f299a0264168b65271799673c3d18adbfa1fa083c5b9735efd6aa4ec40cbec52217d41409275517eddd1d188aee4f7a0ec814fe96071eae7880e9f298415e1b9e9a983a7c3046da127cb711b9cc100fff112a453e8552dd63356384c610d8249b7881451d6362a3e8e21d2b6539483f6655bcdc988b8ecee1b5c8d0d35bbb80c2fb2eeffd133a695fa316aaa5a14c809955431f69dbfef5ac8bbfe457a99b75198317c4eb9d9ba0c01f46ad096a61ad730de6c01f35df939a5489e39aec7711cdb147ef3e76c3e4a146b28ac3f5cfdde2f6543a08ba09c0dde32d971e020314ef9bf68b12e9f2d11a0766032aa1df0891cba87358bb39f698b64447a61c66afbf1881d343c58d847ee9ff8eee56641c3048bb99c134eac3481bdaf16f4960f2a39a5a865b867fb34a198c33382a2d8ea78ab611d09c2bfdd9714173e46088f7d1f91240bdbc213398c04b79f69188e47c27f6150af1e65ccfe79a3b8f3d213dca107c2093b78088483699758edd64fa8f76a848bd847bbfa6d64180e8b4019307c6e73dd5366fd005106213f2612432d42681fdc53df0b6a5d483e52d764e64816b07c5d1db64c470f522fa0ea68735b6ad79f807df49093dd53f1f7cabc0c937506a5bde716aabf873355285fcaa7af2fc74f36d159c6ef1a209ee1ecf8a766b6f7eecbcc29f26ca6070c037dc4ad66db7301918902cd1d52de2b6a75f0e9c37d01ec22977b6c8ec5120a8d677c365364daf05d10754698eb9a9967216bae5599697b9ffcb84c56c2648f9cab0580e9b46cca61fcd3f79d0deebba881b2cbdb6b4d2938ae15e22b54ae3e321290ddd1e21c6f6d3c7beda47aae276ac5ba1758d57f7e959eecb52e1a598b7f3aeb87997884fe38ca82de1ba4c5708cff1ccb7cee6720df5cacb78b454e4b699f27b7873adae8e62c0ae3a69068d63ca1fad581b476ef40b556a3a2f00c5952a06ee57d69ce5c80a9e7ef436582e55870a64d0e00c73f79068a822a24d23bdaba28c697b24154e75033dc8fa086c205b058615e981bf24479b6a54b51cc0934f9051515eff6a08bf25b55aa268158b01820731a5e45fcb934205c2136c6f64ab9a66dbd25491b9c169a937cdf8c55a051e019e3f1ffa967f7992893b65af57baccf5e8aad263474178a852acbeb79b50c77f1fe9244c3c7259e2b0550dbdbd8bba491c0c0e8d0fd2155566be47dd56b19e82f8a2f7e0bd08faaefa3f10e882264234e8304c7d90f0a47764b322877e56d4185664e52530fb130719a130853804a9d4880d0aedb58d0b527ef22ab5934191ad4758d971aa76edaddb4ab26242aad6818ff72a4a67ec0985a6f2174910d04bd76f83fcbe87c9e387775e472bf7f340ee149bc011b73a58a79cde64f7cf8abc8e0aa00e411369ccb8c3c3e89707a4e4ce4d82f2b2c7d22af81219bbdef1ed72f534e830ea7d80141c82ee9277bbdb460ad40160d8d4838fb6fa107b2020b65613e9e8697483580bd8060cac01dfdf90b32896b5c181080166ebbe39137ba00ad1922b574792950c31f70038af776096ff031e6d202f5943181095275eefef5f141818ea74323874341bf9d4430d02ee5dac0925b45c9935a25d9d65f32d61174469149b2e54b380df33b7fa9d26974d2c16b315c964f67675f7036912483b5b875a9156f4779877198fcf525ff54b58e497ad12fb4d8e9f61e16844e9be1e9327bb409ad907edc84ebee31641e754ca364e7f078757d6b6fef8abf77e78e99118d4d8c96abccdb57ed118f889bba9d5a575a9d54731f316980d86d2c9fe091bae9dee849fa5ad48904ff9c0a27b4f09ae5fc5d8f4146baa47df70b61accf5f06dea43dc86faf4af3ea43b3aafb95af9624b7dd6eb224ec30117ab999bdd0846417030485a6eff08130625e9da6ee2963c4bd8997fa796f694cb089d100708c1a07fc3afe3d9419a7d2eb7ecb22c1311d425a826cf67dfc2bb82c7e52af4397b1fb36fbbfb72980955db4fe52a74eabbaab67a82bce77cb7e1874221dfcbe39ed65cbd66d4c1897b1704dfa1db683d44d1c64a14f7852004a592275ffc3dac01bc3b3c4bc0cf8c512ab0bd977f627a9a56a4dfd76f3c4f383340bee5531e35829d6a9630e07ebfc28bccba68b8e390b685fd5aa5bc2a5ff9724a6fd76af337e669a0e1569a794e494053f5503d9e1e76d46a0372a24efe638a8a6e12c5a18f7f2bfb1067eea7b64b3e2a576955189cff5b5d51ef41f1793e1839d9fb904b015fbc943c53605f78f86b97fe16bda5bf69396b0697183b960df06648c014a9f134e2a72c2181a6882e0b30960e003a0a0e6bcab483c375340aae3840677a98ad60142811107be4611ffcc11b206d37ca22551730c8901685c7c3f935c6e728fec141c5909f0bf7fb748167eac6c7bc2782b9f55d7ddc42c0e93d4edf7782fb2c7883e4d3bec195aa44113a9029438946f13c89479104f546273c761a1c5f60eb0dceff19c08b417ed52b197079b43eff8e8d9f3993576decaf1034b19d4b7ecd6b48ceae12b4533e46dc261fc518a1bd7cddc7075604e7ff9bf433251872ac0a4a528b19084bda6eedd845dc13b07484cf939a4c6d25dd0ce00b815ac5357887f7fc823e1768ece9af1e67a235064844b1290160138cc7daa9886e22846c3f4a2c870325f1d4cc225e7220904dbe74e97a22420fdeaa3dad8042cae288e28228404057c8b966cd01193438427e9564ef084b9966a6ff7c17fbf7c6e54f5fdac940b1d1f2df1b70b26461ca5187a048b698eda3bf65c7ceb2ca10a45bd933fd0837eea12fe98421e3ed26856a574d8e50cd6374030d1e904a29abb9c26e958ac3313243511532901e15769778b9f2a597fe1173ebaafcc1ce875330cd01877824cbf7e2de46ff79a4781eaf3fe4b1d1fe1c12f6ec5f2c5fbdae5be2871f8e6826ac0a7ca99f609e754399965c20639fb49d22d4c7b9fb7c2db9fd0df42679d5e5d7479ab83f417cbf3d2cbbe6fe5f795ab4113415d1220f90718a7eb708537ce16c4ece94908bed846738e3709d6c82c359abf573bf70f69e31a955ec4e778dbe0e9bff56900e079b33bf09cec201c3b681e11ed2d1f76e7ef65f4580d1138fc2ad52f342726fb42fdab7e6f07be5cd4ddba205a95d9744de17748bb42c1ffc32306328070a9d5ef605d3ab6cbbcbf6201cc367924ce28bcbd5d474ce783edc8c53b7f81570cd1117797f39211a0a3ec96c63b2c1aee197daa453b9e06d4f6f8ad12d37a22ec490f8b84c487b9cee2863c692131803cc284a07f0afc0660e2ef9fd5bd9249f3e4a978bc26dffb5033fa8dc0066f5a46c6973ca2cd4d6a52ec9a3e24b6771f2cbcd733bb7cc29802e755a2ddc3068461af261950552d24bcf147ac50ad58778ee52c888c12cb0a2f8629130b7bde326637b49d3d887f844ccb738bd9320a5a2d81981197416729e8c1c6f5eb552149f333dbc5252b0f4deeb65c8cb8e23d5dadaae80c2d769f450c4a9e9d61fe7eb21d4c17a0d7885e6c569c897feb914c9c0cf5779ebbc7ec90f0a343ee9ce1922301e3e1457056b08e79ca2da37d4e97f5753c728dd91cdf091a917ed937ae0563ade5b561c620e8ee405f6b81241179f0fad2a16a485a07b37136723374b976999654c7dec067c42af4779b5fd57bd5c62a01773ae0208c0c788d23b0570d2ede57b15f20ddfedd86c2ccde3b0b50280d6ba91f64715b1434e86c15b1650bb7488e793c64400bc5d33ef04589f7c337f96c1ad210e44d62d29f982fc635c9ae4ea1ee6bfee32ff658970adca2ad741b4301f10d2d49f11c9caec3c53fd098d6dddb5c170a6f0326c3c4323ef1da47d1b5c3bddf21c10ef45a04056b873984a59c363eed1c4f09284ab27a520b64ccdaf020248192f49c8b18c6e0d97ead3ff93e5ef683086ed84a76b96e6d7925d542a67606d6b332443b29fc220f5f2a80d242cee1d8ac8ff532fa7866fb3fccda166a2c5dcd7d055103e739a21e8215c6967b211ae5568a9e8890857cb50aeeee3e028514a636f5077c4c7e757ff3e93bf42989ba678331cfba10a3b61c7625a43ecc243b14fb913a4b04be897129286898b78feafd7504bf59e062479952aa8e6d38de279fec278f29cf0124579faaf475a22525320924769529ea86669e204a4dbf77c0a87e985ef42c52e471de0eab3a23ce3c66c7731cc4cb88554f0950f5af1bd01d6d927b0169825de07600a47411b82c691e4638e1fc557712408ac0450c66017c7832cb6976860f9238d4c2d22393bc4155e8c760f5a5202c996ad07d558e636cd040f4f326ac77e524e62dfa5a2c622880fb2c06c4cb023f225716aa906c47e2eb701b2e80fdce5f02654a3c895dc87c0469f30fb1fe1ca379ea2ea410f23178a363da4090ddc8eca503ce540ff290b665987d2b4f10b08bf6d75268b689744a2b06d1c3c0034070bf16a3dba91f5b4a36f0f4084345cb96b989edd5c9d0a8f246a3e7f0fdf2290f0857b9871d0712ffbe7042e937a4744a18c8d2d20106777d8604e71a764a1d6bf19e01c3ec0c91d58ca19d6ffb929e4421597eea20f63d9011e1e4fa0bbddcd82efa9b121c2812b9e2ac4c6da9e88d3742805b58f6b91ed87b2e305f961e0476c36a209b89c91aa1c99946ad03edbd41a411878dc07f5ae3dddd634bcc7216c82dce5e22cb8a15169eec7e2c2b0bfe453bd8c1fcd5efd4eee71ccc85afdd892fc04a023f1f6415fbbfb8dd418a2a2fe1990164c728f716f9a5ef44709694e9f549674df84b67cd1cc4cba151a397b414d003d3efb2cc8935498f7b0dad14ce4c70fd3c4c6bd67af223e6295d3997049c8af9f38a059676562f30710c186b5b630fbeb765f17a6c800ba836dafa869b3cac3f9f247e4cdf063a13b415d9c548f8d19efbb5b4a2d5ef69a9f8fab57e3a2e866c9c4cffc9a4edd41da347f4c2a9ffa7a7dd783965b8c166c7e2fb508262c970d8dae07601feb69a64669a8ab4796351a0f2d19796c957215d40cb4ec35a64c6ae153a87922d13358ed74076ab500c86b76cfb8c1a2b55e4dcadb62230dfdcb617ec5032ee95c198a53a86382bf38298121feda3418804e7144471ab70ea3f00aa9b37d779c72b3dd865d5bcf3e4e703dd67c970274b71db5c35a5eb6827dfde775aee46eb360a26a53f5594d8ea44acd76f7ef07e189ff4f9c6c611ff85c6f6dc3445e701c7adc6e357edae68ebdc9173b324dd082157e7b396b5aa999fef85c3f66cff875a56dda0de377d59af0460b8a75e218bde3cb0c2246aeca29071021091b6d92a8fd432130472a49397ad86171bd551ce258897fdc10476235959a0a1ad8bb42202d831923e0fa78249622558ed6362e81dbc4aa37a2a32a25b3a80bf635e77a6a6d7637a583a2b3724a7477e0042f06e699c2adba3d61757ea32492c8a46382d737a0f60214cc33e2ce4616135f2429e1d8279873ccbb6a0fc87c23f7199d6ad4b856a0fff9a0e4ce63733c99969d3548017e521fd8a98580f8a103f18e06cd47c46b76d3df08b386314620f6317cc2038aa55fa374d94284330d00c9aab8fa97f65f400d534851d4e513c94238de60b8ce73d45f682014096f29d28e565ae6b3e0d9764d5b774016b3d96d8324a936f1548708fd8d1e4bfe895b226975039908cbf70caedc6ca49c3ab5934a327a61791286862a6eb7ae3b0feace575f993ece38837817af9b6f1b0580777213bd188bc7039bc2d1ea601e4472c483c4e83ca23d19983ae815c2c2f526bb7992d16bda0ae16a2ceb4dbae3a62a0a0754d988bdbe06f0a3a7530cef378864ef6e381374cea6ebf8f2b1d6064dc372a861fe0066f20f36cdd007b106192a7b0477eeb8738a2f22f6c31dac851010ebe0e20287a79cb7024226d9d3041436488cf1adab6929330490ee060d168bc6e77fc89e48825b74a3f2429aceae24840cb85c5b739bbd74158023a0ff11f0ea8ca989da3533bce35c31b6972076b6e69565b75780dd34429619e43c58f38c9b4d2d1549221f14911415cf88a393f5ef654242515435433e2cb3e36b5d996980bc8d0b403760d26767fa44f0da74f90d32b8cc2441e73af9a9b3c674a022ca1d4cc712a5120b6909bbd2c1b0fd2a5f96fd10f252a23bd00df96411a7d10b4d66923e05035a8ad004c9789c6494c1a36f6ff6355fa353f535cae98cf414dfdfb4f8e7faf7c22bc4cd793cc2fb45fd6cc15809cad5481fde6386978d37bb0382468de5d302fc80fdb51edf9212cf2c36939e4486798aab4ce17fee931efc9adb6c42f757aed471d6af9b2824149737799f64fb8ab3b7a323d34bd04dfa7332374b39313bda9d5b81bfa88c4fb79969e9ab72babb1029a893181f4e7304f30224110f040d18ac5d52ad870b4e705b3715aa92ba63bff6550006c453c683ace3e13ea60897ed4bcd6e49b6ff1e5a7d889a0e358ab851543a1890f3a1b8c93570884067bff165194431816037080a2b4f3ea543274bcd627c2be35a599c0fd284595aa87e47a539d0224566fb6239bb9f4faea0b23fd12fc9cfcb60ecc9366d620693b8532e27e836db119df3cd7eb4a3fa98fa7c7217402349f5f2595ed6621c7ef3e0fba9fdb1c860ce63fa550dedae04f3bd0dc1c7355c759f995c086e8fa04a9ecfaeeeaa9c32aedd6d7d15d7506a49ce050fa88cc00e2ca9be8046c7dc62356ad7e826b7f52a87a71c3912f5fdd6ba6b7dd6e254f01669020a4d8617b0c24521849639726ae9cddffddecc1dcfa951dddb7415ebe36ce82f247d3d98fc9054fcf9a762cd7f896918640a1b53e666686f80ca80f31d29157137dab4f1ac7d7d2544064b8d7a4a407d16f1f92fc593a0f866cf578331bfcaf6b5a31ce444cdda62cd038bf0fa3e8b2eda2767b7eda965efaa1ea9719fa80e37a8fbe9d217889c64d354fb8d753e407b2e59f1442888b4c2aaee508407adbcd34a8d2f5c7a2a4bff460be8a622a2b6ac17f2cd5fe582bb0e06f3af88e1e12bbe7e211821a640f3280b34f38f58d83eeb5a302279b045657cf0c8a909279920f7742a6d0929ac0c08d37cc72c5cf22c0a495c0c7682b529db3272266dc6f83d02b44deae204bb0602716f1ee26c050fc3efd126d6018f9bb8ff3410c7d49fa5db69b551b0ca5817b7b59ae6cd627d98918f2f6fc31ef110f25472b7076e37fd520165bc15ddcc5fa423cb11a7e99f30a2164057c0ea7ba56d1e198a83d0405efbc2c3e8d32725bddb7e2679717be3ba626373eeff6eb2cea34bd5b0ed20c7997dc0bebc51313e7881ab7f8f45edf43f73780ab9ad6f31b6559361b062fa1bb04a0e8f3093bc39c688c0b1b4ff0693e113fa9c1341bb6f9a34f1a77cc53f50d502e92a3cdf5e3d3a2f7f740b405632229e2b120e673c3cb3aac89085bd470d48049a13a334630049cc846c0da50a048671fad2ac7abb5f8bfc431f28e059ff03a1ec0acb841382729e3d4958d13f03f246ed3869f6b3e8040180be0f26b1ed705bcedd342d0ab736d68e041cd0a654544d09fe91b14547c25211964f18e12e2f6ae04be7dd1833c78d6a49803e484f693fcbfdb000aed2be3e25128c72d965c68ac191c4a105916a4545ebd1537c929841cb945b482a772ffbf8d54ea5ad784349deccc5ad88b06ebc04c285573e61bc57ee5fffd62d17b010445c5d786c4d37c3b0228cdeaa40a1dcaba6495fc7035a0638c755c0bb8a800ad383bda7005edd4d7efa34dd5b7c8c00b9ff17da1950458afc3d8a70dbdc9f4b3ab1cafb69e1a113e85af857a4c10ab3c3c8970ed775d20fbd8f108b6b496e626dee5b052218912db0bb07a03c6e29a52b315d35912b1a0b3b0acdbaad39c492eaffa47cda718195db4f52a278d17a678683dbc5668c65a2744329057dd0e7853dd983d40d6c7ef0b5087001736633963183adc2590c2747ac64a45b96a77f6c834fd7cb716bebca86c90390b626c458387c89230db57e17f747d07a4bd58e68de2608e3b2708c51c146cabc78c4ff5402c8b1989cdf357248c72a8c500400d2033317c9be8a04734f43d92c74edc39235e16c9e64c0f0939ad86451443a0b5eb44a9959cc431d8b8b126295bddd0117c3f3c1198b35fccb642f9dc8fb8c6b07494a1f334dcd80c387fe4969385ae20c19da5e87b2ecf3e194a06958bef5678146b44e05e1cc2d21398ce55f053fcb27d7a672b94fed7f2065615ac72df72015012d297c6c19552ff50ee6a0ead5e33fbeca4744392b6a443693dcc049beb354ffda173ecda1abedfab7cc0665bdba6abaf5829c829070fcd9a7403d64525abdc107bdea0938c344ed87b586d55ad745e392c4ba94fb5dbfe7152120fafdde4a6773d423f50fb113b19cebd92cc8ef7d201610c461073848ff38a9481260bebb189958473b5a8de9215a867c787adb4e9b977705a365af09cc700133553b170445a909a55b37164d61f89be708df4634d8cc8f3c6c67a46266273a3da678302c52b3fb55ea8f9d50e5d2697c4b3bb5e9156b36e167c6fccaf4f51f0b125081f52ed0b2628f3390f81cd08d0d137a7f84b7067a1d8642d1a43167c910b2e878277306b421e715533b062b0086e15e7dbf07790132f8ffacd20b20316ce00783a863d81d541b421225eb5d5917142764c4edc6a23d8b265b76a9465833b8f8db0de16ebbe381f87a5f1e44b4f5d46754b009bc1d9e4c2d7ae7ba145d7e9da566c17726a759ab024765caed1d951d7c279e0a0c264a484d1f5dfd51a016c0b67f2342f7d1331a848bd9ac365afa19565d355951ecad51fc34cd84ba273fd2073eba1b8d8e15789e845c5d8379ea839d571bf2266a3755cd3dc80f44f11bee26d4ddba3528bbc0e62120726f5e5848746c0f13914e1f8be421fb4b565834ff69ec4c77d6c83fd314df7365f164984b047a601af6b5030f84dd444665e872b2cb47efe14a87d18a60c450d4aa32e33c7c631047a22c31d06511a417108e0f1c4331c39458b91757f27ff66d17da0c04285d0116be81abca0380216915e707d636141d97991c4f4a009da3ac88883b0276aae6056e38f1c78f06bf53dff855a0528db9c9e75895c971ab194eb18d41c18e8ae4f7862fbef3377430811bc18b9f92ca945fb668acfd7e0615a57deef998ba6e2ee15a16cce0b1e09cb22f52ce27535bf631cc051e40af758328adf5c0a2c4dea38230e21b0d600d487dcddb09eef33fd7db15e1a2201a4cdeccfcdbeb8632cb6da67d1a35ed42263bb9122669e30d01c71b53914c195bf8b2ce1f3bc0ecebf2fa195af4b36611cb3b86e69e4bab0b82d7f83c527d03c052a7a1f43bc77ab90046ef082cb5a13dd842449a22c4b03968dea7408d38b03a3131ab6b8e6b0e741e729eb72223e808c2b0db71b462c04fe0a254be8875c57b2eb73ae8bafd8edc1cde9854ee28b42533294752ac0b298176a5534281b8fe62d49087fdf057973349145e2fa49515e81f862f5d0d290723fab244ffe031a93c63e4c8851e43a0d923bc1a4ff58e6bfcd9a6daad959a1a448a15507abe10a9976675af08bf289298cc800dea463baab6e00e29dadc8ff4a08adf1735683b634149829ee5a822b46cd9cb798b1c15b133eecd372353e86b4fd8a6f7ccdd15f2c9ab01d0db564497cbfa01b952da4ceaeb68c31e9d86aadcb3964f511bca8b73053f5eb12ef87925b31eac2dfc9c193a3220ddbe606b6a8bbf8f42478153400435fd2ced0750ecd48719c620fa2fe09389fa3948f552f7b347bf79de996c247b641026e2b9a57f43869364f569ca4bcc4ed4c40214673b0acc00b81fbf8a1116f0838baec37d9d9ee88dc57143f6274d77b21a30fc7a8f056f27f672386cd792dc8ea15976e0188c7c85ebd7eef7147c3262a90d1fe51d0252c48d4812d5b9f42562d3771cb72cc49175d60b936d25e6e08bb0afe6ec08ddc079bf6b455bf91fed374d5edcec75518e6afea50719184f9a153bc23565533904f06a3f2bf5f1c1e0a72fbde32bbb32b322e6b66db8127dcb284b7cca96ac7757f135ecb2d613caceb9e9efd92cce995723f874d1150978668ec513b396d98a771c25ef2c1d91914e8c574e809992a00ea9b376cec4e1198e3d4fa2bb7da4c91a91651be928edd405e2ae968a8aed7bad8c26d1a42024c728339a87c4d08b7d75930e25fdfa7f9fe40175b2def4f7b491846efcca41d015d80bf4ed9b44e1c4e5a3d04b6aa94065b54e9048ad27f6ebdf5f7c86ce0532257aae466254f28749e312a10e9a23c0c37e3ce69337db362b829c2ece430ce39bd59aa8e4a84862006bd8519242c638f27581138a9d5c83f83addc088cd32601711aca5fa8b28746ed290b82683eba624cab0bee4811714893fe783be01f5d932f555ed8b40c6f71ddb265c9dece6659a98ba270ae4aabb042e3b3515925cd2ffcb1e247d55043198785ededc06d16628b2e30e742a21ddb76e3a0bb9dcc9dd9645f070c695717d123775fe9ee617f49dc1933ca58b164f96106b74d8d958b943eef329ef29dcbb63d6a79a8b61008da128083569e9e6ebfbe3b11b11965796d120aafaf1f10321e9fd5330f62f1b21cb0adea553e18185c83675ec670c6e25e0f047d770cd3db0606301ec406598a4775ad569154827758f84f84903fa7d9c8bda6ec7a9a1315577461a769d65bba4f38d989f4983459754d36d6b66517024211faaa4787dfe5f05f5aa79cd4578ad0fff4c19dd48c87c481c41c81ef449bfaf029a9142db8372d9963c50aab4466decb03a48ec44a453a2839387a0d5047cd5194be7f92c51b4510a7fbd2b7771438b177868e70493c0f2d8bcb714136c91bc395fce02f5489d4f48e594f3d93323fb33ea9cbefa2ed7104eec35970bca34a17b6bdc7b54bd4cdbd63350058e6c1cc3e4a8dc42884f35a8f009bea51969a51cd0681a26588ca3b968380668bae145e7d59015f84a78559cc5b0be2d48701101b75231a09a18f6c45062990cf2a1b117b5f679995c46a44922b46a8d45fbb8d6515447b5d1d7c19e90e93725671ed61317878fa673f8e8a668474307681b382e06bbdfb738cb69b447f1f815e1a8ac7f6e3abd818e505b4d844cf8f8b3a4948a7040a9a1ea23c9aeff485f25718b6c310cfbea4b59195f972fa2c2f2a22a80e175ca9cb25c433ad7ffffe100390c3024f750e7cae42101694291c7b7d612a1595686970b82f8aeeaa43dc1d95e2eae511503012fa015bb46bcfd070827aa95ea96c8038e917b3be6663cbd1776dd125ab8aa6b735ac2336d6cc0741e9a06a4d41c93c7ad31e0e75da34cf88c708b4bc67c9cb69df64836c7616d93e689d4c74e99086f55be747d21ee8892bebc77ec28e7fc30b510970babd91d3c8a7d3a0c93e68c76e220c3b1d2095d73c6d1eff0457f23b0e6295f0553e06dd2e3ba61dec97d06e0976f32be06897e85c4b832e2e0862f62fec593ac73d58ad512f38e8c05aeee8241a420f813cf66d06fdfbefff4b0bf5b2499902043fa122658abdc608c05a66bdc41894683e31190dea105e6fcc898561172fa2d380b27e38dad346c39fc9629bfc9280d3738c6044ce3d8f24752f9466a66ddf68373ca95b3a089f83411c089c642d41211973f01ac3f8b89ce6d5e622fcf36b14a6050156f2c837d8af15a6b5523096fc90ce1c526844a89ac33d2317ebe6a468e0b5f4f3fbacdb94f487ecc52078c3af31e2e7f98ace9a8b67115fcc874a3455256a55ab5ee15a9cd95c7b6209da4a25adcce7f8f787ec8427887abf82828801a2b2ae287ec246b3ca1292c384a52ed32d5e9b2bad0ec686b9e24c9620275588986e9761002108c3ca39aa54c53fc3cdc2c39df75a7269e5ce03c86d91f2fd6dceebcd3beda58f48c44d72e89c8585d199707f15f22f5886b542c37cd597b6f5c7823c8866857c2100c87928beb218df91888b8fa89e81539beb96b8e927331e554e31467e202f15bf4142854d80cbc5b63c28b69ccf72c14a64f5564a1b356dddd5904b876cf63b024fa09427b84e7dedb19d4df8d706ac659c17d1c95a020ee46cff80182138d46a5030022c20c6391bb95b3b2097ad062159d1cedbb8543f20a622e580292187210a3da88c1744b77ac4a28772c692a52c08806279a616369ea1d5183f265c51afbf9401f8f9fcf129031f9959b6e5a0c2ba98e2bf4f15fdd939b7b80e21da9ca286c6e0d2c4d190d18a9c492da2e83f9a8ade69e3b194c6374859df44a0d8405d305a74123f41dad4f52a755df99f955fb8b47087529f352a15dade81748adb4ef563eb00933884628310cd50d294dc8f28cb48e8572c96f6b7c17299949272081f2b988d748cfe45c5e499c6d1bb5e1f6562ecb21479bf0ab9a80007e8bb37fef4772055cd22f14de40b25368006dabf20f4448d4b9d5eb2d51891cd1d0f9c157b4c6d3e019eae88257fa54a1d8a0429dde6e951af720ed68c3f235f510c8652316f39ccece2f87afb5cf3e24fb1c9c460fd34df80919396f53a92c24d6ac0793fa75fe99357db35451cf7b70d8f31481879dfd674e6c3a9be88ad69e272fc79f377d796cb27946bddb08e6aefe100ccefd4fbdb4372feabeaeef273dab54fc60e87f2a7c555d08d559c21e455fa1f6ba96064fccdd4199a918613db15a1fbd47b1e77c66f588093e37a7d9908f25ae8548194914ba940980d3ea1bc431c8dda245b7f2ff190fee6b9ef688841eaf595fb1d32418bc9e3cc9f21ee974fded7d159647ae9cbbb89521288ded203935d3e0fe67be8d690509c1d5c7ddcb8b9167135c74bf6aa3196557f41062cbed7d69310873ad1e1b4a670c626ba4dacb99f72aff8b5cec18ce3641828e6f208f67676cabf602695a6a0da92789ea959b6312f459675814e988fca70b84f77a31777e17a8b6dfa0d6425b66aef6fa4b37a5bfeeae56c44ab1b0f8bc6ec203521cf6c322eb05a6538ccb0081ec29aa0b60601c87880908aa9ac86635d8825694b6b86fe02efe394c26339f3649de380d5e751fc6b8d8356ed62676dd6b46c96f7c0f2e9138b8be5152a50718592970e142231afb38129c4d0fd1648924824fb9644e836b93cc99ce5d86b4a6963dcb1b8763d66e3a55f30c81de54479dfcb1b2b5166001aa9bea18acb2f258eeba15a279e4aa69a741637696608642d21d833a256e9a45dcd004a2b7cc51eea8943a4bee1a94e139167291eb922d972cb6483761e8c91633194afb55bb4c7155b8a29d0c6ad2dd7d59bd71292deb0036fd9f561a734cdc2b6bf6fd0e226b12a896b3b743f37cfffe8e1f4e62bef52db122f7313e26d6851a7af57afde888c8724258ce898add4d54e3158a9720d2d191a0d7ba6913a3cc23cf54ce085f24d1ab9849f3353e208515d932355a7c0548c4aeacc2d30679d795836fe9bf8dc91af752482506e91d6050e8452d24931574a82ecbff82d053381971ff37aed12beff0cf71d6fc293ba30b6f44680bd3c78725887b581d5a7bceaa63d2dbf6af8e67d0ef195a7dcebe9409284ec813d64d4c689ca23d96e60f2fa03a9b0903490e0e48dbc5e77c3d6ac793963a1ec134da900263f4707d78b35df6d2ffa5353f784ea9770d8d0746035897fb22152e68fb14eaacc3c356d0e4fc7619e12e53e9189b306014798769a481b0e735f213effc92ea7a7b9d35afef7b5408cbc2f5f467869f369482ddb3fd0b0780e4dc7bfba6dcc8f01b686e2400d7c71046bb0ef912ce36785c8ddda9d62f37d3e6f4b6454ad405357d5d8e665a03b504218168608a01f31a9e7d4b69660b80367e1c3c794a10fb7150814120bd2ba68729efdfe1d5141889f7a62632c4847bc622e52fba1303c52035922e8e22794c33f858c3d01f783c905fd6e1221ed963e745cc21443316dba30bdb9d095cf7542a1173be6e85c844c97e7be5759aba78e66c2902ff6393f222f0fbe5d8bf0ff9881f93bff1948a42bc724fbca199eafdd791da59860fab1b25ba99519dc3a87532524d7aea1e8ccf580f3bde37fde210efc1372a3c852e32b32f5625302840067ce9b6f32e973c0de82053dc449805df3c11b1602a1b7aeadd249f3c2ed49f927409cefb434ade74a287b1ad0ce7f1a2b55a7d23b6b4333a2b305a9e6d93a1ba561d017cab3fd7b6004eb5c15f99498f42f8ee7210b6d6e1bf5ebf7a4d17e28dc4d2f1c1a647d529dc4f70192578c79822304a8ca31a0bf1d0b8a1856126ca10fe16b98193ce0b9e70561e7739c117113673337b7521e85e594b564b64d4a5180d6bb6df70aac5eddaea3004d833299d709d9dfcf121725cab33084e8939387032a8aa5a972a9c262801753e159fa2f9a9282160754a2b7bbd925e3c8008fea4ed504afe558a6e25ff1ec6a581de20b17bdd22ff761547278b64703e391ced5fe0655b8b4bd1352716cbd833bbcc10b8a572364c7ab0ec0291eab9b984025acb607c67fa15ee6d47791179f52d36e176065dde233cf1fdee6de82d1bc4d0a21c7b2c0ffd3f8ec62746109ad5369b83c7963152741f3e7cb194bcc5ceae782aa9fce3ae4387c5e707832bcfae4e68c80ec1ab961f6603a153bf4964b4be5415f883dc0da2f3ac7d150c4dda8e4b4e07894e90fa0bf90ae63b291cc9eceb8107e9d3ba62a8ca798c7305e0b6fe6fddf5b92d74ec791aa4ec57544571f0bcdeba02ab46319874a42cff942e8aa633cb6b6e7dc87649a36f3421061ef4543f0a8abda39c328b2cdffbd16d8826aa09e70ec2f90b0eb3dddd4ad2b1d29dc552b6a4d4ed0a0f6a232030bbacb84c3ee370f5d43cf8025935a8e88fea26a5ecfa506a120330a013dee52ed7bec9a3d66fb79711fa565399dedc5aaf78649ac1cbc9d537f66403904ad033611564d5d6891ef3795ff7c06bee29bd00dd2adcca7873e0f9353766798e5f649553c898f3acefeba82b361cd259ac18d618fd822f374c30d89c0959dae7bf448638be19029302347092d11b05fb9bacd8a4b7aae5de1aae6da9d556aa2151d874d42acf8d5bbadc6a2b3ae487311f5a54f92b5fd1325455e5e2c7af758f467cb4ae90dcb1f8adc5fc397d1a8a4def8f047fb9077dbb103ac18a87b979f8c25758e2840f98df95e350eaa082530843320816f6a4a14a6a605826a8b5b1e00032a1ab35426e240878ade664afbe781173b16b28c5bceda3194c0657716a707f04ebe478c64dfc1f65d4f2e65a8a3e36a4fa78894c3724e3489f70c33f6f2fd9c2c3d129e7bc2ae7a7cd2b55834d2ae6fa4373fa2c50a77f2dcc6382519597e607c79e2bb139fcece5a649c9af8057f037724c9064630fb45953cf96e2a5c16be43c0a0be3f0ae0688edea1a2e796dfab211ee9ea7b8ec77afa83f69cedf23c49a20f8f07c6869dd117be1f94b1e461c578b6249b97be17b5740822499ff563a9e1b02cc2759fed997b3f5177dbf20c76b0edc4cbaf2aa3df55749acec49c495c99b195d95b704ad8e7d2623d6a4f13cdfa9a533a7b7e196949650a5221e2f97b2bc72925b455d24f1efb37491fca478903b0580213c7dff244b26c860a919c8599d4c5e797b5c07a5f36acbeba388499cae0b30a6ab726281eeb24d7b10c41223c622abb1f85052d8015ef82c2b0889342276d35e7d6d5983e99335240cffd0b5ae278581091e19d2d02ea1632dc2067bfb31be5b170df4de6bbacea712fefb4a3b2272cbfdfaf8b57c77cf108e5c5417c15d91679e9c488ee5f558f97698f417e9150ae342509a2a6c882c8bdaece4698285c8eced808c1e5e69c2354594b98d58b616222103cb8d2a8791835769b2bedf2e38f284b10acd4cd9e8e9dfc0c2985f269346cbf96c0b031cc37e106fd41e7bc16296b2d58a389a8a6e8b7315ab7a9b9bdcb7c535726d0046ba1ae5d1116f5889513cd295b4c40127decf9b51c1dd03f92ed93f2e03985e2952757dd419843880818a3626d9d422fabe866ce47185903faebc2280e5ffe253132dc3667b06775b4f8099113e8537624da01a8c8daa0775bc85e71a22c5732d278ccb2ca25264972f36d5c04c910af8b342f83c4704bb5416fbf2f6ac5a65bf66c0f3c08032bfe5a3a316a5e35d4de75185210525705d89eaa848c7bcc271680be41363ac9eaa5b4ce81cda6a1528d7d17bb42b29f7f019d802f59225402ea7c3192b2d31d1442616f96e9100d95dd7002a44d844799675af852b35f958691480d9c592b678545ebda224fbb55268a4ff9f0d131c7fc6e502fbb6ea21d962056eef95cdb49fccd533d966839d809d65ba68faf2620076583deb61a7811cda69e706a6f7c39ff11d6d91dcc048c8059de07c6167b41b963c5a79a6aa840d434aae3f60384e74ddaf76eb4b6eb04ff031db28a61f211abf3f9b997fe2f14f1a6c6a240a43f90d2cd8d63557e7bee4441115fd4abcf4d840e5eb20994e4f11c20cfe52eccaef017423a903dbd0b3c08cc68ee7ffdb929c036df53979bbf09d4d0a7757155623811132b7d5ae3b85388be732ff40b58ffd377e92797565717b5fb4e39435040fc3e48e4d9fd5fe0b6ad076b5b13b8756f10f1c2dbb04e039dd64d2c87cf399b7650768ff5c17a9e9f820c0be73579db0f8ea8a7fe9455f89ddd9fd746b4b8afdb6610a2dcf90507fea21c0ec7b8b63963e3465886af637e72194d1febf6ec7c9bd1aaf3f71d9c3be1c4b809737acd7fed70becfca0511ae9d2f84ddd8fe80d65086c61da61798660f90b8b5e5bd3b486062bc377a809e471728373a313bfa7009488730d693ab6dfc626e244763cc78ac9edb684976f031b0b8e25b4b410be4c705da1a0f10cd9332bdc30e97a3ef5000f6da9aa2a4eba167cca82b750bbab3ce8b17357a1afaec828fb22458303efc59b621dac7cb7efd1e45732a91127aec49008301481a0844a2699cc26ee4f7228d04895eb073d451e68ac837ac403f1c3e31dadbde0af19429dc584195ab5a216bfe720bd0aeb8040ea2495ba3db562000e6dfec294d2b8b9fc09ae2ec9c5f6c74297f0798c05d102fa77fc49481faaa08c5e9a9810252ba96e80728f72d2e360aab26599dd5c3eed5bd314acc1612de3952ad70782093791465aec4fd6dc45564e895fd8c7e4381fe8e1bf3ac7fbc354a2e2e4eee52e28b95fd0640c54275f7a1ffd03fe939de2854c22cadf6848112f952d40579f3cd68eba5e005e2cfb516b71e063bfbf722d1d9ac9b24a50a119d44944117a33d6a38a9c43c4caeb56ed584e3e24122fdf8108687e9a6fd53195e7ce5e9deafc17ad4d7f25af715fdb01bbfa60f6a1c3d5cc439c4c89013f404a3c2811eb4d99118e89eefea1737b8ff29fd9e87a9178ef6170a5a3423d337cb34a596f8e0b871abf5356c98ffa36b0cc0a57600686095da18e67bbbba0fa5b4a63ea92375128d35433473829708238dde3695503388784dd2f58fe513be84f0bef33e8d00584b164d8096d80c99c3398f7fac4ad49e53cf2c7e8a29e42761e0b72d366859ab92e66b98f9015c9c5e581d68c13c878eff36d9e1d1035368e80896ec1500d4e1ed5f1cc33d4f170ebeb2fb51804d317c16bc0195ebb9e7e04779f85d491f7d83ed40cb12ec7d10dc7adc4cc8da42204d01c63a15c14708961ff8268ed52798c4c699b7d50020b549d44be9d92fe2dbc208aeb88726a24080f3f4f3506c532eabfc23be8c3f431dc6122c3382575475968a4f298a7a799ac18aa41063e9c5d03f842090071e67ec27822dbb387534cd3352759304cb843dfff3ff4e36eae3ac623c0dfa2effa226f994ab87c39238fb298e8deb18c9b5ddba53ecc740a6a0d7a5f2871b6f0ad1266f52668000efce9f7bf5fc8c2499126468b863dcb18c3266a301e3d1ad06b7e8c2a4f49fda48d0c57f9abd98024762349cd0b0ef1519a4abc44cff99d17ba2fc61dc8d63e3d0f80de9b4d1289a276e940586b4239f29c3843713cdefe529a3390bde493d55930a1e9f2964d2a8777ec56c58e7f47599b3ba567e65da3a212bdec4597770b901ffc83596470df874f1c6b74fbfc4b7026accc391e7076e0ae5b5c594c9289f6dcc158fc17061753bd6fac35bde546899a4ceb56f6d60d3a7d5ae429990c90a6844e00130eadedd8ef1c2ea9c5859f05340b322f19cdaef9014c4549a21d14eb9c79bd8c73fb8071178253cb68dc6a18992a2cd3d9bd9acfdda589f282e4473ce28807ba60df8a823957ef6b84f31c71ca9c0f27c2f74ff4b5fb86f87b0797bb16e1747a2b3de24cbb0a78f0dd90c63a0955164c23634d7c7ec3080896ecd37ad4f84a683692aca4846dd8f32a5726d3f634ccdfbe14ee81f774f082fad9a3b35552667b38b009234ed20aa8d0cb69e60646a2210e10fcecf373800d809fcab77d0e4ec5ddca21eaf3aa372cd54ffa10a52fd835da49a210876ef5558a2fe5e786408ee2784e8bd5f000e4be642233b509d7758aacbb6523a6a900a78a2f364066ec8244c8e34c8102d5eb7e72b3e34996112037a088aab539f4f99f9d66f658fe9ae7b6629a43f7963fb631b8770f85a20c7fc7c1996fb6a7e70d10e4ce8389965ea6b6a451fdbd256c49f3f2582ad5b5a536f3cf6937536e71c4ed0435bc3d34ed0155dea3dbb2fbace5c60afa069a6caec7719e0137997d68fdbe841239a93e3ec8c7dca7ea52307af5b1ce7f6332a442d4ff3b88e9365c4d90bc97cf9d6368df5905cd9d561a25ea678a9ac433d3f61cf08ca14de7cd664e0430c2888b1ff3f3e649fb112c9fa8b89e1f6a33a27380e9442b85f8ddd322177fb2ed01491039e21812b7cb0691cd6c09dfcfb51ccfdd353134afae647348593f5732c91508df60ab6b0c70d609630e3c1bf8448c396f27de2b25ad0ab61bb0586f73f0a8b584897a114641f6423e7ed3c2dacdd3858ecce7ffe2bdaafbf77b84ea7347512fc806fb5cd4932b65d99bb789c9fdc23092e39fa183c3a6fbfa8e8a398d419b5cadeb90b3340f1a989ad14e2fd6ea3580333dfce749b86dcb63f69566c6a54913ae119244f155845ca56d4b8e61b93372462f075c74d20249c0193c747be67321fb5eb50e0fd2e0df50321a0c2785419c084ed4f50f1221221612ae39c6df745505f9f8e8e93e1d3bc840dcd32d577ecb8127e40c4fdf3f5a077ade4765c8bb1cf4c4a16d41c5c46f69bd8cc4bea5a4a00829ebcebdd1af953f7db4b9a8c986aaabe408d9dfcda6b47995aa12aa031275dfcc7fe75774e9f306aaffa8ac871cefbd90d6c5493ee55c77dd6e6c4215bc5389b2b237e565380f277dd96dbfab41fc998ea37c8d6f77eb6fe7a8ff07e6a3332af48b2d028f3d78318b2db87bce6159923c2dcaebcecab1a56d7f1e7273af7565f709cfcb2bcde1ec6ca589d41ae5be1997b93438b653ef19321e2a999887f45809b805079ad96420648e9cb8b3f1f0284485f304f1c8c5a89694ceadc53ce277a0e8f1b0ea8ed1237117f140f1cff1a600721c1813342df13d9ef433fd77a207ecc0f6613de2ab6855b6c3f23a2c39ed1c622b9aa222386de7d5905fa7318bcf37fb35125360ea41447ff532ab9c220c4939dba1df37344ee5e7b9a6547c3cbc3c79fc9cbd464753acf75072929562ec99a3f0fe1074984fc160dfcaca0f5c10eac7189b6dae0115a1b55ba10a0c08f99164fcf202449ae20452a6ed2243c8ec77e66224c011f3ad3ab1c79619867a170bdbb03e13288a077f87e3fbed4b5a883ff414e139d32b2a48afac52a006f94d33d62ebeb2d54067449e4696917813786092b6a700d4252007f9c0be56a683d88e56c006fe6a37aeae7d04db88012c38d043c9bf61aec6889973e82ff4ed80b5b04c8f8fdba2e75516cde36bd4b79ee805f7b8f8574908b0c0ba4b675e75b4b3deea9687aed1030084c819a1ded557d637ca172f946df0cdaeef6208ef56722fcbbdd601e1a7c3196ee0a1d3aa57f75097cf34ffd98c04c1499db54c022c9938dae760a4a97e5db2c5ee59c282bf6255f051e6b8c4e59eeb4e537ecae6d361be14bcc09e7b9733862595271012c7913d2bdefab5d59fac4dc22f350b76e4d5dc7363f0ca0449cb381fe0e763693dbd8170bdc6678a7776a85918f15e7e3f809cc1b97d1436076c9f2cf368c919c0a6bca753c82e07513068a737b3904bdbbd821e2a466018a2b447ad1611b30b5cff03a2d38fcf33465e3da25b3a4c766afa4aeb0ac2963c3a0e860d33c62bba150fac53cced9f1c6e34548cd8f54b1245cc59a3623f13591118ec5225f9821c479217b36680b00e9512acb037ccefbe47bb221e6e503fd9ccb9be9cad9b1dbd6c966d53e675d92c970d97a43265646bc79921c962d14f9e5e685748aa3629f90cb67879470f4e858fb67d3e3d20c80405f99d1b005c38200934959bdaf2466b01fd723238a90eccf1921d4f2c61bb4e236c7689a180df4f4725014b66eca3fafbfdd4301339f9e13bc9b47ba443662cddb4037d72b4eb93bdfb8b7d629d0f97b801e4a6e68642675f3872428938998f1bab68d00f97ad3dde47ef70614bb94538a853d7a2234dba9c69a805c348ab37348d59dacdc9aa587fd17dc9a3a7cf6edc17f1c9a9337fb92d0f6881c6923f5e4dbdf81a7adb1ef5245e3ed896dc9aef44a0d590110353f7b78240d349d3d81acafc507ae3ee2a03839f94f2b551ec5f4f51d9910145bbd8de9a5c8057733b53e47a123fa0cb5de4dac8582acc1880d0f4c479ac80de0270d2f72ee10d3934ab5765da15e7bd48280954592baae85456bbbf6cf6ee6d7c879249801b659d19e0ac3c65ae8bb79252d12816393bdaf938c8f327746c6965d5c271c873431e6f418af502aeeaab1c84caa5c31e4eb3b0740c1968bb903a312c6c5e5a2e395a4c0f7b488771754913ac8c03c38101e305a842992ad2ea3f0a81fda7279a86f33e4d04159da1430d3e49de4029e25148324d1eb73e45f6fb5109ea07a35e126d3974775892d1838aeecd3a05e9fbffa841e7cbbea5b840ab52423b10eda65ef0dc77d548b1ea592dcf9489f3ba6200711ebf11a3ca02580bbf98d4672d841b5ddfb912ca555a5f78750c799024af2100468262aaa5dd9b5416ca20669327483dee42300069d45b597d003207aa03507dcbb16ba4741407ebd38dd728d4ffa1572bd3d9da024bbde924c017d0b3a164a0c6a489097682dd8a34d952a2c315ea8b2dbf54db2e159c957afa09202e7071641a87a0e7eca0f7783c2f3ff7d9f9c9d29bf72295a74eb0174a48f3698224f7f1e5b4df0c44de6e44d5a12f2acfda5c7687c7f4dbb64adf0c35e11bbab99741b1a406ef7d30fb37f9dbc87ef24c86d9b54cfff1d87b631c32f25bed337a50c42e72713556ebfa81dd431f01bd69c30f04e5748997c54c66323f32ccde2617008ba00bf6555c429db324c50b88e4dbd3ea5f0038cad1b9f5098497d658c5624a00bc2ec1f6566ed4415e405c33955570c3d38e2bdfa6706e380d153dcaa8cde0c05d7509776e8f55b7de3f0872539d30c960b59b037f8592cc3af7c94906d80d6d8e21933933b708db66fc735424ef7dce3d5882bb1e06c1bdbffab1e7e530bc8d47e932b8eeff5f817e01c294f2894860224ee4bf5a3b1c9ce72f3a5977f8997560a9e693294c71a91d03269497a0714e89b37dce18eebff724ce860ea6c1a59987e0d9c36074ac17c71382a791a76a392d0abf2eb6d284596ec13991ce5f84b61ac0810e6abf2dcd9771b5a70f31ceddf9868a96328ed43224a3595bd58ffba5bce9392f61b923f6190fc0a25c3cd88988f2d04167ea008ecbd9d2c854ac07413c939f3c9ba10872240e2c5bb004be81658d4f7a57cacd25e2eb0317220151dd5b2d421044a92643a7e2cbf5fbd95f9dca8fb3c30a4609477bc8afe4b0e96cb1e38f7bc5c454ec316a0a36baa28f41930bcb3ca536c510345d384e5745eb7a980dd3d6b4f364cf2a937efc4a6157712aaab889896168fb0788f623e3cc34b79362969833eca67f7ad72ca6b43d5bd071329ec2aae53290d097f606fc841c12a3157f5942e99cae3ae11d81988a133efd3d52753942c455001ad777d71a102d9ab5cf5f42635bfac2ef3eeaafcbc17d403ad3e13d6f13119618cbbccb013ddd914f397f3e63c04ea3898a85768a133ea8de37ce1f46b61b623f9911cf021f1e2a697af38b9abc701bfb3a5bde585f42c3a6c65bd1ff3b9521a29e3117afcc5ec718acc4b1629c90d9a46786337d5fbf1df7391a27dd806adaf837d320f2877f62967a2f864fbc8fca140e6e84c7442460c539855fdfca75dfb457bc07124b48e3fc927223ab8a593bd6b70c4c58cc30329be6c627f222006bd2c00597ea8e6d2d3abb91adfbca850de523f7cdb1b5efd6e5fd045b96ad0b38a928c847f3181417220deb9bcb69f2f87ee0b83c3c9e92a153419cf01bb6e3738c7283d40240e745988283a4ee3f57aee49a0b90b7b72494d5b3d2311eb08afb00b042f6f606d545531723648c579e9303524caa85e4b8967f4fef2864402ab8640daae86eb8d5a2e660cdf4d51c760e3243289017f58dc8ddcb64eb94bbf75739cfaeabcded120081f6a42e841551dd6118315be50ea45e6f34f71ba36f974ce06b2017f3218413700eda86083d8e6fd35c23afed4c52df84ccd8d88d40f692e32f23cf835176632f97aea09c2b6d2e2c532913ac6b017a6d4075f2c614716a7f4a166b2ae956d20b2a8de1f39b7b6e67c05f589b3f47f9db348cd9c496c057c1c1f949d3d925d56231fa809f8e02621ad2b7777105568342743e099e720a0283850804e0f5ed26ed607637a30914b8560f04ff77745551b287f8c9f131252ef7c9b95141c6a1cd5125c7a4b568e01bfa1f942ab2b03478c97ceff53d79f70484066649809065f4171abf1b451b8656108330d68bc650e40dd215b6d0b05c065bd1451ce8ac973f5f53491c8463e8250f36fa4c070b38ea7916947677a1915433d461fee91c32645bec94986ea0f459d5464b89ff4ac221536bc60c939e631f88699244a80afcb2106574fdaca0dde2fde25aab8df2ccd00cf1f9f5b506d9f41a78a092b02c5fab031ea89659b6c810d7879b3a2759e699e5bcca329964ef6f1d53aac86b725ef03e9f0e3d74703fb6d1f9d9384f332d5fcfa8a778dd80543ceec7e264a5b23654fa100293a0f7e9c72d4c01a457b79fc2ca2963d7c883e514e4daf91adbcbe13e949e75e193c28818db89b6f79a445e97a03b6f76c8dfc9bbf9bafa7ff5e884007929022b4776aea2a99404a93806db447ae8e40037ce16f6cfc04057311af842de6f6aa601f017bbecc553676078cfa489d3c9f65fc5592f2c4c156f7d6a8cef0e3f92093c1c4b2a744d24cc83407f96996a8bff6915ba903f231ed4f59e7c356c0e7f72f56be79b63f96a0eb9abf148ab4d2a732294544e9e764a572d3b7c6029e55240614ff4f540d180110e4f12ee0d7123fac2de488111cb66b07d468c8d4345f18e8997f38d2e01d6a2f1eba9c789d8d2be0d6601b5aa650cc7b21c3cd7762b6b1761762ddc48a293426cfc168dc380880bb1b0f7fd9646dc9e0724dc0038356438263da797648ba6eb9a03288bfa789875cd0e93854c936558b5b3ed4ad7c0a3310ad0ddf73c88cfcaba099ebe8655d36101bda1fda0c25147fc9bd227ed083dfaf012c9ee838d4271d3078b6e2b72c53beed5d27ddebb7dc1a53490dee7e02234aaa9897b2ec3a5615c07a305950b7c0004218fabadad86cb0414bd2ce95936231c7509f4008535f158a3e38ebb7d15df95feda353ee53bb59a45432e1e7c021cfa795ece6efc82d01813b56e3b5ce7149f32b598ec891d9bcb87849b263be0ec90395f12326c166a8e8c0f251516bd06dae290c94eb0eac7bdc364e75f9adc02e1341f7de14e5d92b7f4b1c457fa324492a81147d2bc800205710e1a23ab9e7f18875eec61b5d945c673f0c18172dd5147d984ea36f5ab9ca2a6ae6c4e0182468d662cc1248d0d3c2c57e14a1422baee5a92004599e7ca82693072db984bf25d74d64a234f67c42cfbee942bf4eb2dffc1cd594ac816ec94a5c704a49e0e6d995ad6481f936e59f26bf7d732fc2b3ae9ccd8b171292912d05a478ff0b669c131fa7466108d8e5f9af51779e91af10d89ae4e8fec3ddcd0c227e647e45d1eb43e4181b73a0e5150243c135ac1beb5098b19823dd53bc8b9e93df3a478414ec70a43d619f39b5a6ad5f638323e3a75b2e79c0d2a282a94907b161c912130d0c8d16ba64b0fade4d3373427670638cdffabc1d74e3c6ccbd6077fe0dda8fe1dad28a79ca57458bd6aac8f6cad72cb505bdafcd47e8d0aee4e0b1c2fd5677af05bbac380f41a19e9d2b82ad4fb72ef929c0cbdf00e7bee210e414eed065c68299be97d8b579035f2cc03fea4faa318cab27f91ce8968afcfc89d6ce74778c71e50e059415a0bd0e22fc614139331094f9a799a19f4cd10cc60637bafe29fa614936416c7b976af8790c0f73cfccd27770b06a831dd8d62164be08f8eb6bad79b0bbf394b57e4ea04e9c76b9af79ffaaa7915ceb27eae6530e8c8e204b44117cc9f525cfda58acfd44c160f8f4757c4e5f91ad778bca2874ca6abef5f3a3d1d349535381ca4e7e327ea92f51b9b2265a496439e1ff3a5d5900bf124c6df748dd14addfa1496d9a9b01dfc4923a275005421f8cb96912daa5293e4c1f0e3ef3b7ebee3ce80170c12f5bf13588eb132729f63ab397300d1e2b6cb89a47cc96b50b813566158aa252c022d729fe74d97808572ee4b643e374da674c4aceb7d2efa5f2a660ca11fdc3033179becc8b85a2bf3af367864e3f21cf51326ed9b432ef79c460c2c9e80c2bf504d3a7956e305f42976eeeab36ecb4ccf8f0806c73239b54e1ffe4aef4a897744fab17805d8bebb27bd1e223bc04780c6f257b697cff789ced2eab519d7d015dca157c499a813fdc784485039b0ae9572a754c2e7f89af90754c0901def29f555ef2ef1e7f6b977ebe0b03e5c36c67b24a91f74c877361257ffa455a797bf967956bad228dd35a9abae67ecd84e8030876d5b02218b94c50463a5bcf6c7631d443f42e1ed8fea1cd42f8f752083f5f625f96ff93e05f156948029195a6f01f8d5f320f60c4f12a412ea44adffd069eb78f66830db21ae7df82feb066f0e09cc02cf0275ab612b185c6696483b48ef5d5d38fbf5ac6e820fdeae7260a393451d0defdef9a2c1a2ddccc4d0949a2147ed497c1f8a60e9ccd11731a377fde9596bfef8e9f08f10444af74c64f829720c824f79d5bca053f1ded98d79d438a9529cfdbcbbd6033da9d96d1be44116477f58e49dd61d799ee8562c379ba9a9f322ad1b1eb00efe0bc3cd0e8cd7bb21a151999a79acaf50fae6a8565a19aadf7be4b7ddcdc3071739fd487e1d526df226680acb0b8c9f7de1c2390c48963d2e35a395e406024d6bb81a1c65cab4d6a7463cbc97334b510a3d34f484324817fd2c7061a7afca73b85740b9bb9e5d45a6959394b06ca7bf0c6cb0f19faf41b276925731eff22a90b8d41f6790d11b7959875f5e4f2411bde95920062f5954e73dac69d095a4d821e7698841816959bc2252561bafd973130fbeeefc853bafa2947b89fb48057c574e083ed32541111c224eb6a3a9031ce86d823bcf22bce5f931f1d8fbab098cf616cff2857d9bf361053693debe6f1736da08db9ff63f9833baf1f316fcb572a1a63cca6070e9e1b4586b5dbc2f4ddca29a98c8f3cc0d3e56fdfe964af4780f7d4ea52913d480ceb53a1b2b3535774f74537c0715156fbfdd82e150330713168a2d520078c678f5a1edc86cb90bc38f51bc8617b3b45a220009915df45bfe7bd247ac4e7f2c6bf5173665cd2c6b04e820cb24adfcbe95416a7a9bf1c7919955fda585c8710f47c91c98df7e206bbf33d8bf65f139e57a6248ca69165c47de19fbedbb66628419cab129e67839974df9d7ef8aed7740437668f86e81c17b6d41e75523dd2fd60ec1fe379fa9ba57712973c7a0e86bdbfad09aa1a4d04cd0a0f1f42470e40f64d37100fb9c686b80857d7704f95bcebe8743c13e40568908fcd0c0758f833a99ea3552eb360e426742837aaf505edc3d8e281fc4a82b1720c9078c3cdab5cc8e135aa9147a09a8e14d1e9bd5024ee567c7d52a63800d901c0cf0427f9fb16b73f451d71f82970dba906ac4f0f97399772fdb11b90995e383300cabb50346bcf8299c3f716411e1d9b6ef40bd6fac63d9900827aef4343437e4a48d36b87dcac2525cefbfe1caf6b5021c998d986e9bcdfd863bedd7790453d1d664248e584cf836597787837f497501a5b908a5d07ca7ce2a989c0a8ca941b8abb6ee244da65afddf7739051c7a246fd2892d0322708ebed5dbaa23cfab048fd7d64c4a70540aa901329b9ac55303fb5b5cb228b457b3c11f60858e80adff83a37fd6c35e48c7f3948c4742ae52978433d08dd07a2a8e586b404887cc000927202d35546e4f2e6887343ff0606fd398b3c5fc87d5d1e5e45f747065c109e2c375356807012b471d1db8a194f4020a41077efb1ce31f046d3187ee28086a09d34e0849cde3d2b52f179f99527121938d9ad70711d7c80986965e3d6ce6147e45d38f1fa891ac6d43d68356e049a89a543bc6388cb037fd974a2b18c5b6d8695a6b13cffd4dfc1f9188a138910ba0781d34bb15c311c2f1c8f672d3b6d42276c925d33d5d0a50573bc26993f43a04b21c1099014257ca3980fb7b8f17c7b10577c625e5db4391278337c09081dec01e103fe8885a6b8994ce2d19adec025fd8dca9241f88ae3b9df53db18df44c7ace2d499c66ca0db1e17c45dad8d26786453d8f9bf8409afb56c6d745444a8da6a31aff926853aef1e3477c2904019195d51eb6681c50dc277206a3c4e87f74c86d14ac7acd59198b990c23e9155289cae9066f988f4f43a96f6ae691e52b4f1cfa61bd0ef9a4978d46acdc855bed41fb66e3e279061e49a89018223cd91e204ff86e36c0e4f9aba0c1cc4334fb8f035d010d05658d4a2f54491396e10ef0cf1ff57ee988467b3f335aa178941367991774214be8dda6f9227e6e948b6343fc11e8335af496d58ff17fa2eec4f8227b4a59c52f397a3ebc39df7facca572ca926c5dd07faaffacce5d12d74d46f787131ab0fe1f0b498681ec33a40be411aef1f236a1375acf3373418db2072cfc996dad53c64f570484ebe85c7a83806340f2834409bc14935b517ed092f340eeeb47ff27a8ba0245830a4ca26f58ebd8a55b8e1d5c5bc47264634fd4c2cc245373f8c51fd0637c018b4e9b936dbc0d1e563de094be192a3926a0334f8d94fcdf64440614e1cd265b343c56d7c56f608146136f549c655001f5d8b55066e034c439db54ec33c42b06a05b98ef0c652d005e7d5a59cc10670966f0492c237c615c64bb87992bf47b2d10056698171a641ba19269f13b8ed5a377b706aa61a826c52b3cfc749c600bbc659e848582a5e9b850e5d2bbed480777b99ca1676ff4ad03b98f1b04486325653718232e30436bdbe121dfc7e75f061015705dd97545d5c114fc9198f891d7c40041546ca57fc49a005b4e041cde966ef3d8cc09230b7498e1b8715acda168d026fd536d6271f9ecddff3eeb59715e9ab2f100fa81c849ed105fa6d1744ea46311fc110b54eeecb7e5135d7a4a9fe9acbd7a5eab653654faa580af3c3cc0104968d4fe6cd6df868168713a19f46d04d385558d02fd19045a6d9c060daae7da0ea51055114b394f272a734a2e562c5535aa211aec42cd13f7d3e7d6b16d8f930c16fc4df6600e4692221e5fba6c19672ceac0f840a1152f548dab8584896f21d4a456b7efb23eaad49aa8d739141b9f3657db81184d730fe6ff9fd4f5041d8cd796bef05cf10d89aff4a4666edc2e642167aedd568a5cab879cffb988732f2b26eaf04ec83a2f6bace9aba4b408d0829b94791a4e2f4ca97d94f0a08f4fe351a0222fff77d49aa4d0764903978d4538f79d69d95727649c37c74ee888b23be61a78cf653c5e5db7454d554fb09148531834d6dc6bbd3145f4da16159bfb3c48f9d6d56202df78d52f56e5f7e7dc26b918f7105ad76dc35b9b17c91b2aa3b2c0b693846afb34f9fbf48487344666410e1f321749bd46aafc14e24d2cd26d65c7e9a556ad30dfb2d2cf604bd6428f020e008dc440fd36cab6534e4db98f31e7e5da4d962580120a08a8b0be140b35da20d844b5956911c57d602f0060faf039a53a6d6be8c4ee48509c3249b1ff183b71d0361339f881af58b02ca82f8501a8a7e7b57c4ef494d49e7b7a894314b7dd9ae9723d4956af0cca976beb2b2c7edb2997eb5050ff587d01ddda254a6f6c45e9a5f5ffc479d739c0e87a3383b54405a4a84f89f7ecbde57cd554c23b440fb8439a21adefe21f79c56e301602b0a6ad7c1023a29c2c080e83bde97d616379951cfcc60090bf9951e24c3c2c6c0f8f355c84c330daaa857de46a5ed909d8981a81a0e77302d2d90fdab37c05e0dc577c9f18c7d0a57b92b42d7679911d1651701bd147e8a400c3a3caeb1189afcc807766081242ea336b4c3837f9f2ee974e2d396e80b7716d66d5bfd01884efceae6f86bc62a2dd65dac785d6e550fb575ac5b6662d923367324a31bfe59ab4f96be63bdf2c6a75e731a1a89f95a92a240965c5998f51a62d9d9ae3bd854863d3ca394f9ac7e43a39a2012821245a18387de9aea3f34750c303ee1561ec4bcd352316b886f2f21688b96f346d1ae3c204a80fa7e9ff45c737236c697ef9c78be02d88ee7d5750d4eb4b316b6bb8110e027521fe80e8c3600c1b89c54a8a329856b9f7750a303b1a86f726e7a2b679fd565617d487ac6ac7e3f905a85b47075f3203c5314f45cbf8c3fda901db4d25c24ee7e1e7249549f599b16828783da310a1744e0afa31fcb8f4ddf55e9421a2d5184b5dc5dd97409d46857df76ccf71f3d573bf3941a3a275b1a610efc710cf69e9bf496da7208a739598ba70a80254b38499c1a0f4386b4ea65bee57dee0054ad9a35fc73f0f98bff3e254f1d89198ed2e9c4ec4cb00af6e1c9ad6f43e824f2c591e3b16e5a2086530e7a3097a8456c8453756e8baecea06b6843edd13a3d8f86fa1f3a51ec8964b31faa01a9cca0533a7826c5e8334695397d974f82cf90f6049dc7639ec918c7d9135dd4466e0403662f77282c38df1232715cbf5f27dfa94c2cd47bded90ac580a7815735ee409b1be97a1129ea8d32c209ad349d317319b69835c7d75636e27240414dc28758627cddde2aa9a19ee0dc476a36a749b49aa8e2736371f15b23a96152cb1ab4ea9a4b8d205a0e08008d55238a167e6e57fb95c9be0ecc4d15a11be05530f4bf494233018f6692792a11b96f5aeeb9e5d01e37136973cfccee5ae1d704078e18c968dea402ea62564924cc7db07979a6669fb61affa245e9a139d4367175acf40f7c863c2392eede087165565350fc23cb1d2feaec6e581da13254e5ac008d716660ffd9c94879cd4102524ef9fd9cc289686740912f013e7489903eba63bfc81e626175465e7060ba054ce8ddcf5c7f1e4cbfc6ef3f96b0bef76bcca6ddc13e10e173e4a4b61597c4459e4c72b25c675d15951991ebb0ccf71a936277f87ccfcf10717768302158aec4aed48b85482d0c3d97e8a52223a866bf71902b78000cec9bbc1a85cb44f955ffb0880254b88275d79af7dd46b4e2ea9b850e388f4601c84ad292a9faa915f526f2e210a28e0e5d2763c4d95debdaafa21c1d0f78e12bdcddbc24749ded6e8b8590e5cddec782e25e32ef6170cee2fd55058ed2a70d6859740a78eea7f97b208a5c36c3495aaab5bdab5742a7133e8e0c8d2f349e9a6aae7ba5c0eec8d1461a5a66fc76b7924568f8a10b2bdbf796098566c5ca6f74203ec5cfac31167217e9fee407351898c143593425bc721ecc1141842b6f81ea42d74abbbd3acbd9748eee1af39d011f260c1399e5dd327bca2dd40dd732db9cd7f612e83c976485296d9a1f14e27eb32beccf655b64472e5c6d26dc6f25c77e363c40d8eee7c985eda95d9eb4d7e4007840485c6f1b047a2a217dabe13d3f0b267e7ebe097deefa77aef576940dbf1d1fe4ee9dad0e9f129e63675f8c3e895850c4e0ecf1cb34a2acb3480028a09a27c2f27fcf7acc1f7ce787984747cc6bd0a25710c5db2e993de96f42f979138c11ed92813df001e68131c7dd08a1ea0d002dc5556139f4463cbf5bb4e3e4de2d0f6ebac029d0fccac5bfbf4107d0bdb19abe63ba90e098732324ba7312831d403ffc6c8ee507a74d5ebbd89ab7cd2807c9678c26a659c80bdcce7ce0cb6981f1a1dd87d08fd04a525e30b98d8ce601cbf5fef7d1027dfb653fcfe26ce4581588a8eb19d6e786b2b6e9b7b560dd3f1bdcd705797cd5b3c0edfe8f665b53cf2937a973d44c3cef2e8b03de7ed7776f77c4156e757a51b3b122f556ae41ca93dc7010224af1dff336068b802924ef77c86ff42b2cc093f4872eb47c49d89e63641e2a789b6c43cfcd74b16f844ab3d7cccb9bfd0b108bafdccfa1b30d5dfa925ce4e106687575fd3e38d2a69faf7b8bf99e2233f23f220bad29dceaab8a833dc495e3c76df6a4319326c80f4002e0f37e3c638e865cba7a48b651219dc72d7021cf4386c6616b9594ff89e61d24c0f40f82765709f6dc57c86f4e86b58c0aad068db167021d59b0aca878e08085258c22c97124b5fe2dea159b6e4a4b1edfaafd4aa554c3b7978c24208fb330b6af197f19fbb08b6d7dbcb782c0e4ad6734ece9ec445b0445b489ca09f9c524efa4494f7a12582e623b95662f6afdfbd93d8bdc9b275b27022c62538dd5df8aeb7ae150e2888a7d754729a42e8133f550b2da695fd5c9c43c085a93258832ee90332f64548c73519b043670eb4887353288ec2936aef07c3f8a970ebca97d72fb7540dd290f1de8ba6cc3a931630a311b7f56be5851dc2a0a0e6718ad5160ab1d224fd18f4cfc9e70db813a6b4cf6f6b62ee3d065f32169e8a007ed02e9803be210575aa693aa11d36a9333c35af6b68e13b433f4b5d4cf8b1797c2a187810309732e619f0e9786b60ca3a1942d15c8f7b15ee78dd31ef5e2366902bb1599d6c7633de14ea7c94ecf026eb2afca1c03a0a34642c63d510809b641498ac0e95cec032033a7e3770739604d9d71dc985925c29ca8ce8410a70b08b822c689814777b3b908aee59560574ec7d5118a196f5646613c8e320c670dcc6b793ca3cd56d0590f32033a66110881d300b8566ca53ff039ed813b17afbe6e9ccd53029e46318c03aeffe5504be0cbd09ccd57679b7a8e5816428f720fdbbdd43f23935ae732aab3234ffbae5044b3715f071bbb49104a0af817a69625708777607550ac510b2322f00a6d2a0839e1497749bf5c24e80020557d5f09e16e0add70f425c7bb536f7513595801e5ae741efd13c241d0bee83f7a7dbd28c600762880373a6f9723f992f85dd66cb2aa1482b59b4190a2b0dce5fb38b046a095cd1df8712c2b3e2832d4e6ab8dc34203d382ae7f851934d55ffb3b20dfe386c9719232445d947b4147a2892bd3dae8e40adfee0fa32ed60c76f97ff67addb2a36e969b39f08435f0c0af03d668b2c83933646a5422a2e1b0e2562ca18aa043f55dc6f9dac98415eab4be06cae040f3947deae7ebecfecd9c8ac91f70c9eed3747154ce85b0f501f0ccd2fcdc878ee74a64f12e05f51524a8d229e94e4510c14f0f3eff81d1bf6f5f9af9528550bf63064e912068c9d1c44c6b9e7bd43833dd28050bfadfbaa7f7fedeb737b2e2dd8ef9743e17b1e3b56a9989456984404ceda307b58d0a4779a9f7a78d6e9e7b600a9c31c533346b0711f1b018a90390dc1fcbed666af509b9ad64042690c042e07abc065292b1e741b347361b18c2d0f103838f61d13f97b9f850fdbfaf523613c74240b1be9221ed97dab912e0a1791d9d541c349354214feb928e77ffb903a552830f1746fa094e0a2b5b9b01ebdc1311fcedcae558d79cc40c940f774cc32c9f3cb2006b2ef3dd7d0482d77b39991e6d189e118b7cc6dad80bd0092047e8770a6b8dd2f073bb8a1685c1496491fcb896454b9b2d692e942679d8e3edad085d7f27d8115dffbf07338e9171c1b757fe07b6ce4dfd8cd609134a81ac536227677dba719d6db6ed71f1f0316c57b93f86f21804be261f482e1307d27c0673281406f24dbca81dfabef9e3f91969cc23e77b2a4874961dc213375db65a9bf2b9902bb629a9be9accfeb84002a989c4478389963808f75bb9aa8b9d36104cc820b62fca131707283f3a85f26cbc163b0051cd7c29ff64ece098e75e1540bdf7b26555522e0d2e36b660553871a9cde2a37444263fee71b594e4429b1c34dbc7e0cf95bf64c3e69c2edad13ded2534e6f3a1c712c66be82b9e8298b78f13266ffc68838a9dc556173bf622046778b688c1bb6587c8eb50e6368ee9d7c23e7aa6d80edcf22d139095aff25263f30459020509ec44cbf0cc84b9c2dd82e91e723028776037eb7bba74505edc42ad2439207242cdf5012082841295dd0246b8a5fd9423c76955413f21bb19f898af45489e5874da5e7d5afa297c9cfccf023ccdd579b37b10ef8161d6d7c0be50fb7101ad2d97953caffc57343d2347bf1046963f1ec83a982c0c95ce0da9e8766c858028b4190558cf61e3c3bb5938201b181b196221d759eeac6335aa0f9c32cf16b15f9bd92557a9c91a80304a0756d1e4a0477b683327bf1f39367a6b3455176e1e890cb3ae349e22f32d7f720b86d3b5e736960f1b497ac8c6c20577c060abd3eaa80dd32d195b867e0daf9d9a40066e9f064262b7d871651e5d3383135ddcc106049d370cd914d9e0da8ef7347843354e7936489d3f06aba875fb0faab8f557cd6ecf8a104787fdacd75f257dffea96ad1eba7e4611278ee6024b86b2362777ffeaac8f8139fbeedc7c3cfd2108cf706907d8b1614b94b076a011a3a7a9573707d6fbec35f3b97938ec8a5792a5f4edb5b7d737f2fe339e623027d352d448bd1c6362670f6b04d2181265e456a55b972fdceb89e7bf75c067945c00aeaf0e27602612c07834365b7a3c84bb88872644a31ae439edc531dd95c60b22780a18863a6be427339454428ad6dcfeff9c99f935634070e5dfc2038b47300497ab7d30f62831fbe2fc30724e507185cd674152bc25067b47d4122983454903c973235818257d50cf88d58477db9053429fb6f4f7528a2729207a46b8cedc9e6361d36370fea321e63893bfa0cba88355f074a2dacae689c9894b1598f0213fc3729cfec5b6ea0539d27422003510d9aaba6176de7478afc627e8d7fe5d8d4b3d39c4fa37daad2beb831f537b088e4a058d48ffc16d713de121a6e1e997b2523576aa03ff49dbd39849ac7d3a3c10a2e49d52783ab20f8dcdb3ed1c62ef41d5f78942e6fb3df2844b048ff5b076103a35410906d885a406a494b1e31a4d1604b8ec196ebf9047e83ffeb38d2d798d678aa6f1f5f1ae09d2ba0cde31f01722664d5def539b840ed0f5b0fcfef4f966a42ec2cf158079d192dd38d77e5633ea2786f1b4a148b74c1ef5cef40b1fb16266f56b9ae9044837c063d7aee9dd30cada4f0a388833be465e38f86e59d265683473e9461cec169e9aa2e5ad8de4762bae02f73a2970c02460a2a2aa2e540c224bea5daa80c6678fcfbf3d00473305518818e544298e6186a0430226482deb6165c420eb5bcc42b8cb31e18845a52aedc47d74b90e2cad97b8bdfb0f260170589a7e72cf76347f8e4fa990da7c73ed9a8ff93c2ff48e598a7fb920a9a58111b7dcf80d8ae24ac5db60e187f1ae3ed9158a4c6b447a16cd046a270d6d681327c8fb4d1c910cec9172ce64169299ba2cba4fa19c578315f4f5049bbe5542423025df9eb3ea141936e9b349e2dc3c4535f030cb706f1ee8c14897b37385354e717e04f3bfec253193233e7caba68208e10826dae6018ad46b6dd3f4427ce7081a6ea626038239208afa94ed4c8f4af8cc89b9f2a01379bb9e03d01a12c02a4d3952c7ec4bedc80fa93029f29d04cf1479399a50e49b406a09e0b1253a1650276a2bfcbbaef597763a068cddde420322fe48b1cd6f8a512a7beefea19007ef7a3fbc2af171824b9cf843c7ba697de6c5a3301b045546a45e5beb3467729783a2cb3339f1fe2fb18ecbad25a178aa79f91ec524c471cb98e813ec3cf94e604f150127dd6659b77b68f729dc438cc4d66e593cd9c08cd2a24ef3036b438852e161d8721caa15cb1dbf16d5c91c6b17c8e2835e99a968aaf015436722a2de0991ef22d3514fbc6ab6ca45b798469afd1e4f6bf7caa25ca854c6b3ac42015e0b46c5b55ea27a00e2e300bf39e6cbe283294a64291773628b693977293de68a1c71b208c762c213adae5bc37879f0821a299413d3e160607a5db218b12f73f058d9d4418a52b177e556f64231eea3c4205e8c1e006c9a42b38eb2d4156f5b5c3dc60135924188f78b13e216b3cc98ac9c6374afa781d2f420274dd8820baf3b1cbba09abb5c1ca5c3bc936179733f72d0843da97d244811551197d189c8c89e9c923246937fd6877d97ba13c5e45527ab8b338a908553c1fada9f9023818b308931382d16a43a9b1b2482941ebbbec1f67f31b5dbea9f87467e4aa923bd26f7fbae40fba52e09b1c4c927fc646fd3ce6979a77c9d97d027d84ee401e621bf53eea771996728e9c35be13f5b5bf843fcbeddb6e0be90fc8bc30ef64baef1a5e98cf686fd28965f567feaff61ca7d0a1449750f94b09845a3732e094ae7db68c8a30edaeca1811ebf06003a906fc15d96a93ba947c77114e5e36aae7688a881613f446b3c8f695714d818d9df1f2e15f296af6cb1b4f0d74c2755adcc58d079e25d029e52f12b3898ce4f81c093b525a34cbba12ebe93cafd080cb4869c4d19d92c4be462913caa8bf8f9b45139d16c7577caf74583b4828c28ccd75184b53393dfbddec81a17f145d0baa756a9738bf4c6018607d3ce9c7613cd502093fc2531825c6645ab2950c98c2a9a4913490c847c95a47551b201fe123161311d7bdd409eb5e73180ef676bc423621485da68de5ad821eaa85bd62910e0cfd2547985531895eb813445bf43e30a18b2949023dad96ba76d182b8e2991fca06435a38d5fa7a58c783f2685cab1dbe1327498f73b42acb08e4dd9c77dda53377c2005a7b516cf3a00438f7af57a2b24d7f1b05733aa150901cd8b5334df7311d81d5aa16f4b8ae9af2ea17086e283643337cfa32545d7e3785642ed61d5992d818b815f1d836813882910f0643db9ac68116b75a34b925df9d9940f9e39921b7f223f2f1ca31accf6bbde1f578ab12f09d1f9c526920ac5194d0e21ffa5178243417c6264c46093c589f2dff011edffb3a8b7ff7f86dfce9df78ce97224d99ee73f69c87ad4902a6720c238ef111b7d9fd7c348d1beff85aede7f962d5f009f25a74c861246bf8ba851746f5538d65951b90d566dbb31833b1759f2cb574fe3c6c1920390adf0ea624432db1b0dbf0936ddf3d7b581d974374707fb1d748b91d3c94343fdc4e6b9f4f75a52e65fcbaefe4f45fd44617d061127870bf73bb67816cac9eeac987268fa3f53bae7f7ef848f5cd7038a678e55f4ffbb6c8fc6ca60e05da179672d6452cf82d58579156368067deefdae8fecfbd46583363f43b35fe0e804b214482eee81e5f843422efddd281a6672353891b9a4185233bfdb8423d6709778915a58fea42b750c4ba5677a8cbc489b74cce25ccb73400b3556181cb6bb109b508dcbb364efd9d20599d5ef34890fcf9149e24f8e7cefd78bb77bb2ed65f614e253252319c61ebdce09f291a5cb4b94ac11a1f1b063b5b84644e70dc2cba3d12b099bfc1f326371a072a2aadafbdd8015e7471575057642737d9dbab8818753b05e9d139ad90273e5d85625f1c0af40098e5f9b88878f25163bfd6a81c239340c832166601e48e9613764d03abf8ae0b869efa72db78db2f06f2c11548d49a560016434d4054288aa8c80d7ca600eb659d9ae9381e1b3c776788b13d0b4ca2fdb53026ad888058695a24187f58d3df91cfe1d49a8dd6cef6d518508eaa8899b8c373d677b9eb636324968ef022ec808f634eb1bf31e5ed4d5d59e2dcff7cdf332aa87e830feff28c3d1c39fc21d0a6254605dd9b66ff63e79e6b6ca5b193aeb1db636ad6c5438474d0bc755b4075bfaf96c14a888fef5305ea524c331024ee1063a314bb33dc6598a14f555037906b5ff8973e702a8af6d642f49353e922fefbd93680ba09742fe58f62f1d6a3d0223db4c8c1233c712cdab40a3b5103ed863ed9a21de059c25b265e96653385a08645432b42423bd2e7d9d543f87c2d12b28b6d70688ff3d492c7ab6475631322b9efc6583361af219793e4f0c09599700943428103ef52769aea474314279d3a7f662816ee8386cac5008b96df58d93deb3f8b3d5ca9cf3c6b79290bfa35ab7f99536334942700d5846126fe1ef86be830ac8a93756b190941a88bc4f4786b76a6b84d04ea661d98e4620c7620960acd07b0ba175eb3b7e68df62bf5e235cccc6c54548419ce809b84316679bd43a7c19911df86ec4c258c2a9be55843d4e7102fbad6aa8ca7f9da6cd036d0daf6d5a2615aaf5d437ddd869e2be7a6fd68ef283d81631214a63976e7e99e628fb1050d2be9b0ff151125ff50b5bd8681bfc545e82196ffe1e895a7c3cc12fce83406fb3938f85ab18f265e8c4233dc3bf935ccc6739efe6b841a56b4a41c51a510773f0662e0983258c5860fc887116909dddbbbcc15372f5bd4f71ff93f62ded34e1d103cdf59f95ad23f85a74aeaecbcc6785f56d644aafb6c196562d50f23843171644533b992ff2bc9d69540b22890c8d382babf4351e7dc24ac3d46986945cbfcbff12b6c2a96dff254c06d69106429ed3d959083d20150a68ce9274c6b63550b21fb7be63cd84ec22e479ea3f6cf172a8e7f2da2fdc61a1d519c859d43e49594c8dc5091837f180fc9b19b4aad736328f0b087e9e19e07ce35c8d85a11d14616b4269a7d8820956f8f8e2075ba1a80c9d15a80ec96a0223dab2d06cd4838d66e12c43ce0a269140a4253b5b27413aa80cae99708043a592a5245d46a8a365942178bd6308fc63343e72a59c1e0018d9731761b18558b7deb30f1256038f4ef6221acb93cfc5d52fe78d2f598ec1441254b3890a39b81e8f21cb6b5fb0b58da88cde7fe7a73d3a0f267ab0da58b371ea86537aa687ff65f567f86932ce34928761b79a4fc7cb89832b9f2e8a0ec999d0fb3f31a174c39e0cc899602892897cccfdf490ba9d39b561497d9fa3062569629643d9571d1db474bd306c6faf80a755017d0d56db15903f5ade1888572d5a2679201311abf1cbfa22807169fafabaaee3a20bc2931554e095b4e18b81b92c6a56b27cdf19256ccb04788708cc51da3c760f9a1246057a219b6e340074008630d6cb5cdffda280a9a1daf15ec1301518d2a8b4f4d1ebe546780821d95538f0cccc44c92441886014af29d372b63c4c5708d17289700bbaa9aa9e4e7be84ced94aef4e09d2bfa70a7ae9cf1d24c170779c0947d8b20c2c1c0e51638253e1592450c0fef400129f5ad82b868cbc9c789c591419da63ef058effdc700b621c88329c15077575105f185fb4cabcf6820b710c225e3c5193d029ff3c79a1a12cdabb236097769b93b80096a8936ad04e51a8023d2dcfcb2145ad3ade14f4ad9bcb6c4403e4f3cae0e3c1ffdee9b2b12bc570bb17c64a11b6582f2d0afa9e54c7e9efc263cb9099fb88ddcd70d16d63d9eed9e4c511986eda3050aaa2df8b404d9187f3355645647312e616b815faad28ea1d0b101d0c13ffa0b6fda26db3e0e57b74164b868e350b54f7f55dc8e961012782c72148fed4347d2b2f2103d6ad2ea9e5e41e04e76dd3c5a6defd41f5fc33413f61a0c19e3f6f5ade2b04f26c60a5661b75d8a59d7ec6655290f61441cdb16b685dcc9d8218e389c10339c1150bc1754ecac60bc5b26814e12beee8d2aecf42986dc826d8c928255896a5b7a237a286920fdd5b8caaa01abb9afc7de9387fbafdba38831550728240ea9bcef84df967790975caa74001e866ad50b8389430b88bfe4f6b83f073e086c9d7234f1f3031f5624e143751a451bec32f68dbafd40efb4b3081d09e7cc9fade49d6b0e592b5ff64191426a9421154aae00c19ddd9eda464a66164bb9f0e36883552babd444fd11d0c9513d0e8af0a42449b32f35df7b286341937eb3f0224258ddb8db015d0553cdac0bcb4796d702e6e592c480f133836fb616866e8653379774cdbfa5cb28ddf02409c782746a05171d31f6470b8e9354fef5c0b21863787be23f24adb7f9c70e60f907635796b424b651413358dec9023dceafc82151a489e7985a1bb4594b6ebdeda519b0733b481bc47b694736c6c85e1383b46835159530b931836376efb9fb65b6514535658be2eb4abde1850e834dcc1249f79a749264e76dac7e985434beacc2ea33fa69319e2e09957a241e67002fce2e5bb78e0500f4a1a864d5d08e9a39caa8a8e3572def317afeec329d4ad1dac303fadfbe007e897d93020c8492cb22ec70003effcb5f321b370e8b0dfe271911d229db969ed2e43ef5cd795c26f3f60e4b7c77fce56dd28635839563510a2aa04a116e20c731e92d74da54d60ae55d4e141626a91ade5dc4d9e5814a3ee77a1dd0cb0386f8ca03175f4f08e59525eef170ecafcc7bf6ed4dac1684e305077fdd33316e1c4a71ac681e5a1e76c37de5ec397fd7e3b7b665fefce8f7981621b5cd8bdddcd95597dfdd13e73f23b5e239c93aa55a1deaf66d76b7c370ebfe6dfe405eca9b29142ec448ea96221c4421e2f2f014668db31a0aa5fec54c996d41af3dec15ed830a1a7693923d10d09af3e82e9a8f9587a29c1aaf604ad8fc54bfe545f6ce3a3bfdd36e828954bc02ac5cd6b91d47edf42745c8c3130f35968eda94ccaf1f9a828be3b986705453359e71696fd48c9886864b22a097c75ef645ff53bf139b95d1417ca7d796ac2b46323e998f08b4787aa4ebfdafcc957f48d686a8d7fd9d93f92f536e4bfe0c0e75206c5cd460ff5a32b5c33a5b89b1f797b3fb31938bef8a3905522ded36354f35812b00ead432267a62166db76bbdf6f5b53143a1c9de2a966f694564554b19b7131b41fec3f08cb28fa30b0388b7b449ba1e4d84e7144790170d24200534e6f5a2f8caeb7dce432c9860ace25be0d294fc089f4873a2057ba1807fd5672249f4a2182bbce8b0984292a0a31ad16946cbec6f868e8bab71d9cda188a6dc221558e7e589678eabd2de28f124d4c0cc17f63c9a8e1a5e47208f2e225294e9f3f34aa6195eb5b42e423023f75d82c0f8c8ef7c0714bca34ff3f68c78d177c63bbe8d42da3cec47b902e937133608db3d65912c007af75c73aa6b3c4e964d7561e4adcf4fd7cb63bb4c9db89330e9ebd7871ff1e92f37b0c3ee4ba1da45b727b2fcf5e7260770d8eb46b3028b408270d339a432a088daa36b1b4ad0483ac7c6116c55cd84d029da9350302ac721d23472fbaf2e64588c311625dc2838d376fea8bf967873597dd7dcd89006abf4d0d70c429c2eae36320a956c9ec992ccb22726f2a1416c9cf12d9d3a5484dea7cb2131c4624614b2427d146f05c8f53beb281fbe427ca7b6417323ab6e5fbd58555e37552fddfd2e05d37e445d180cb22dcbd6cdc8123f1acd8d0cbed0f2e0dc9d3a5d5a73e85be4e228ed09746f6238dff1e5862f314432befccb8a6221b141e523ab9f57f4a857a32a87c01b03c922d9ccb6c0517790628a475b6aa62baf1e016b1bb12b33bc409c614dad858cf62e28d97c1a598ad9d24fdd5667670164f7f371903d5ce7c3a990259641403d9aa72b8f45ac4b85a9fd1e747b7660dbe988fa9ac39ddab6b9406ceb3edcb177687b9b9a0eaa5c1a7eabaaf5d7a8ff0b7ad0ac14cc565e5c9802fa3af198812f14526f403f116070c0b1d6c15607df38ef37cfa0765fea199b71455215d7f45940a4af595893cd476384f124a9ebe21ab621a829cfeac75048a9e950658d06a7a3ec9460d702325c3bd9db0d8301aa9210cb4d1bda54aaff1f7471c5f8b34be36c09c75ead99b0ccb5c213a6b9d644e3db2c7b1fdff088f881ae291de879dec8617fb44cdeb07138041a9c5abb1131c68e3477e7e4a667aea8565250180dd09085ef13cacd8a5581d15b9cc1dfed6a592dc87aa7972c37e3f397a264e50d30140a122a12c408c416895359ac1b446c24fa179665e9c644bcde4e8a08330bf6a93f8ad62996fc1255fbf69c0db0ac01b9e5a46b5d6256617b71f03fb20ba52e387ec381bfdc001af2258628b30c386cd895a666fa07bd11830d088985a465a4fc9413c3a477d35d3ed5def1929744f33fcfe24d72d8d579c7454b0e3f5ea90c3021e381e4028366e227a7af4b808000782995a54ebf0da3b21919bbbb79a1fd92f4da0c62a8c9957c7934352122a99806d5cf97f318f2128923f51dfde1d1ce302dd8cf7360fe2cb191ee78af2ece0aa60a431194560f60862aedf83cd1619c7b5057662494e106c08b7b874c793f98eaba0a7d1d35abf11925395f8dcc7c11be483994d7574c29009a790e1a3b692585eabffee2c92f0662b35ffdc2a9614826694a9009761349aa860738e5857c024d5d7d02478b3634bb623169ba0b047dc079b5d0135f2cd476b49550a06048694ce34064cd0cb0e644ac274ea45db3ae0790025bcd07f350f4baf0808aa7ee5cef88580deeb5fba53d627b47190df8eb6a00a704adfa2f81c1b2b6f6cd0200d0268067184058b457ec1c052c2252e34b6ca52d4a540ef7bd7b4c8dcf8b38af0a833f596db8ed038837c543dd7f8b48549dccd18b10d7ba8504425f30af600e6d362773d227dc72b7a020486cc774a7b6226b647476111105ecdfa86213ef2b9c0ff75fa9ca9e3d7be8baf6dd7bf60db529f05899f81ed2bd2a02a6e27a419f6ad00c5523007c2257304d3096c645f1439f43ad03fbce83f7ee8890ea491028ad052404af34630d6252ec9cce89baddabcf10a7ebd69e86ad4fd4cd5c8b2fc5b177585f798fe95bc71a3ef1cb4582540a6d87d33b594d88efd6bfc6b52fd47cba96298097d5769020e290ea341213d862325700e6b231b162e6eba0599634edebc486882d61b7ed83ef8ba389d916af54cf36000b80b988e83e7b055a8d1d78a9825703ce19102135dbd6c8b705b63aa3ff2482cce816c48f108b0e7cf887d6d24e9f3103ef6a2c79df20b03072bf1b99ae88f9616e95865f20dfc6bdb04a03dbf50b95b8c0e04ea101574ed289878ce4c9f9bf32fc3ba0f67e898e0ca69b030406bd1292e3920645a724eba622456655d038a8d54878772fe10a40c4b36e14f512d6e2f77c3b7edee08257c5b66ee38fdcd400cee19cdd58093643f16cd4909cca23cdcf19869b84979917bc8dd242c4369a8c8362eceb191a47a9682dc7db7a12dfd70910a2deb250bb37179a550ad3359d1ef90d3bda5aa383f392a438587c879ea45a687afeaa19d857b7bc77bda92f2a0f18858475685d29c619a33d63f7414991492eeb2f4a1d3f7a02c1c752e78c35acdd8ed8cddcd5d062599e7649f4d8cf3a2fd946a4dd520708a39e155370662bcdf46c114b2842954d0efa038dba569e7999646f51eab2736991f3d1ae5e14fda4cba500959769681d5d201952832010b07402ee0e71d06c435f304e2228db9f42fc253ddcdd8512127e7db270843a1032b1af5b92157bf5578ced1cd943b3a30d6c89baf5aa985321586750109dccdfed833f44990105e8232ec58cb6ce9d7a6e651215a2b54ec2c12a0ab6cac9090c88d82d7dd1a98c1d0113610ea42221e006e32f6b2e977311c98b8091a9fc8df30c97f94131d5febd8ee4cf1ba1984e5b07a07335766246eb8516f43cad67f08b28b04706b2309ab72100b1e8915eb72850a87115b53c42a604b51b5cd6f3e82e701d07a02e16091a6d2b1b0a68717f311fc73a9379a845ef8e90b7bc71c4dda139fc9f56bfbf2a51d1f1ed4b342b785452979c508cffdd88122de9c58f02358457b416ff453f0afad284a36acb5b7032bf396ce5bddc0072dfb6ce13b0bfa0bff881756efd6f79f61b3a96d7c10181ad40f9978c22f526547aadeec6a60a107bedb5067e6e766fb3f6c277cfebd39b980b795b6de9d37bcffaad1f9f77c70fd5b22b7eeabc181be94273eb6aabdbe7ecc14f823c4bd42b5af5585fb6b09676f3b317d47f17c10d30024f2342d005cf42dd8b7996b511b56a1a95185e1f888e77679d44496da90556bf65100944139f027fd7fb1b8c985994e015763893e64335a28165268fc54aa470eac7090949357482b8ae2724e086c8c42c6473d166da6d7308b045147c04500203c2b8b2b7e8078370a8e86bce30e6756f8d841b21227beb7090fd3bcd5fa7336df74cdf14bdb2797bf2195bcf003bccd0446f51dbce349eed6ba8664c0ff48740c14e55a86f4223ca46f77f43eb3a574d38e7671acf695554eabcfc61700292a512f178a18ebdc8a546fe0b123f4e1ec106b62509555d2a546aa16cfd931f664666da5d36cdff2c8bf49ff527385a861faef82b05bb218226e47c8644b6478e65dac1b765e56481224a77156fd9149f85bd89fba5b567400b0f3d4ccd1187ff0ce1ee423e8da258729181e283e4284b1409146a7aff50b69029ad1fae41320831d12bfeea54119d33f2529f201a88828e319d801d78415649a8ae07968fa228ea4ca3ad7794f787a8e10f61a621e86db0fd56f216b780b995f676e4e3f3745c1a8ac4db8257d58b164b9173d387dc6812116dd635e16031e47784818dd504d4ea14d30be51671e53c69bce9cf377996807120d99e3c9ca8f4cbadff7bd5e46fff4d465a91d7cd236b01fd2490e4dc12a3b5ef3297df7bb03921dad3a0021ff3b22f33e0c6b2fb923b0ecaa52aa22fbaebcc70119a4ba47b2ac7e7bbb98792450a6420dbffc066e69194a59002b97c7163f63b645e1270c02739fdf5ca066fffc254ceaf7f662a9fa6883024b6f6ab606f993e05b890c1fa11633ec5a18ab2ef8975edd278676cccfa2699e38e024e1d5c47e020121d6baa983b6cf8000a093a10443f55196b5dff09ca75576f1a244a474f6667ae69724aedc317be5094a25407eeebd31efd2d027ad81ce6b4aaeafc028229c1bad2f75909f7378e4e7e1dbc3d11e1b88c7f4edb4efbb19dfc83ac876529a3400bb3c19d5f7f52d68e13601b9b43e07620d2e26b0083aea6a53a38acfc60fe3546c70b35ea04770756a19d0fe3be16096185d4c246a407e9ad456c49b4d955c6c3e22c1a79b8eb03490fe096ee1649f6ebe8e154fa72a5edac2c4bee492841153c27a919f27ef370fa65ba30826e4a6e29823cf677da784a8cdafe54ffede91aa6f2bd33138edb4a0870924e5f887247ddcba027aed379118f8f610e306da91026f2c73149f391b14653cc13ccb9284678b7df1a5c356a21abb52e5a3d49f841f427ab19d366b38bd8ca920c360067e112db3c4e2f7a170f93588f49e32bc2043c056b8b0c40f76c101e0d9fd18e6d4a656fe2839fedb5fffe0a7a3deaae3627e346147e0e614254eabfe8ee61ce0240b4fa979538c982c768aa3614609a47328113c87bd4aee96b3703f41c11b44dad4af21b8e759b6f398284f525718a75cd7141f0d71b23dbee2557b2edfe724c0dca2ac1f71d70d564df0f54ee0e5239ada9e075637ffb98e3cd5420805d105bd8bf556fa1ae84507d2618dcbc7831c61dd1eb50d9539526eb3270f4233e6a1c4e0ff2e9edb006fddbdde945fd17e2ec568dd74c88562fa13c24832364cd5ccdf7760901c3b021160e93bfa3a0d7fea6e8738dd3476394fce8d769481a2c170d758abedbcbaca1169ba5b40daff3b468fb304064a7161e98938a2400a420371402d9973647fed370ebf2f3d5ddfe527d988c7c09b7c74285bde3ffb4934924b391eccccff2310ba7d661ac96e19e9dbdfa6fc12cc4bd93b81af6b7c553c02218bb1cb8b263199358cff7e89999974bdbed444ce98313934a3f5eaa324398b21981513bbb393607977a3147fb77f6d78f01da8b9ba7a69b67ed0bcc8631326ba34c28b3dd8dd9874f66a2dad72d0aec0ab9c38cbbd14296ae802a0481e17d5717d5de034d25f89043915774102ecfcb990d4e584748bffaf683033d349b9eff0f2d4a8e38efd8f1c8aded16fb349178ef4660b3946d8e95ae0794f58cf584ea2fd1bb6e276c068b6a60cd7ada71b92aacd59e952b1ccfc81e3be8ec39e3c08568f5348371bf82a9a331976bdddac486fde7a2aea3270a1b104b5e6a42d6b4cb0d3e2b677b98db46e8e5411a03f2067315037c97c06c44719ea379ea84170b9596250996714c0cd5ca3e4fb3ac9e92add2f218489dd0de70c62976cfb0467b158ddb4825507ae3dd59fbb9cbda2d7b3676f8768808cdb0af2910b7e9f4d553c84ffe8d06f0b3fe7252935cefccdfbaf6117257df1be1cfab80f4d89e68054a6a9d62bde3ec20774155b639c7bfa491d0deaa7307bd5b38404a4caf31f3f6bfdda6882a384f574ef51303f77d066e475cc93ed66e548b8e3cb9dde14ecb3da95ef28114c087a9dc46ca78822d21f9bceecb908ce1b1851cf11acc07329b5684c60ab2752b789282a81cf83329800e15dfa7c2da8e27e6202535601de23255ae5400ad7cfa368f78e84e6516e1edd64435e1737bd5ce81b4383f966a6a62108ddf3222dba0aa542212495e8b939d65c047936089653a24374f47e47b6a177de0817292fdcd665233cea44aa9703dd924bb1cb02532613c4cbca46e557810b07abc7233087f40c05cd6f2f15ae7af8cd38de489c5b0b5e1819c4926dd211389394d9f985b69be24af83dd4ab19854b21dbce93c8f2dba0b9d159e9f3f4882aec26ed5dcc1b705d1a898acc7ab7fe90b0ff11a7797a4ca82cfebd3bcc090203783ac9d087dad41209c5a08c1294b1ee908e2d31c4eab932ae29f2f06be0b75909564087f726fba9c167af01aacc93f4f8ecf9633891b133fe8586a40e2200dc06cc4b04ad81b7227bef8b8d885b83575cd01585ca48afa6bf8a3be8658c35c9d674a667918d1a769b0925d1c12d1f610268c02e6391845e18ce886db25bbf0b8035027d90a7b877fa91446e007b135bee9c9ae2b40e629ceb6ae7d275d0a44be12f69facc8c265da1e70de121221f77bf6b034a018774f59fac3b13c4979e54df0ad7f0ce2919aa090e87dcc1bc2cf0f570a674087956a03cd651e97270f44385c15d7c7c38ae02010542ad42730457a84e722867cccce4f1f0a4db0da9eec99c5be43e73640e2edbd471812fff60159d57e6277f290d428e6184fac2ac033f2356c757c9a29092af5603acbe173607b90a142b51bfd6a0f8b618df88a7d2c0684d5a47db75183e81e46569b106e5eaada042d57e7fc3ef0d699add228df0d82bfd28ef40fcae71a23d974401ac915f88b2a9258b1b49d8b023d7bfba77c5583e9462005c51036f95e7e3dbff9790d571888cc13270111c87ab0c29486ce897487bddbec6a8584f1155923ec38090e835ade73c99df1fde6a3a67ae034be59783aeaa3a7ae68b93ee89d8adb79bcc1b803c4f13db317fdab42ea40b028702ce7f7a7b92a40db3bdd06af95987353b516476e72952a2b56e83e1f407549572fe80f11f848fb42dbc2bb1bb930bc849960a537fe33226d82e783e15c12cf8ade6bc4072f284e02baba556ccd68c3ab1287e07867bad79b9945c8d6224f78e4979d80b7d5f99cf741ff0699f04f1025fb1cef8369f4defa2e2754a2b80dff0c2bb68f389d5999b0c8b856c68b517227911aa0588e6eb95a98692f399ec47e2aebb117d9de8baea934e599b7088638b013812f7ba5e894c06e163de38ba476f60d0f689816a7a1afb18b14934832faa4fea3d6c42cff1cd184f06215d3416c6b9a4ec5c4f9fc6d244212e1b22d6132b4822469e353e2a11f8f461da073e47c4b7a21b4532386b1e65845fc1c81379e4bc93da8fb56661ae48424c71ed23d22ad3f2d04657b1bed4d670c72fba5467642018ae75930d76b802e49d3a4d9419403c9d860e6366c49c7b915d386e03e401ccdb468781ecb5edfba216771a989091a510baac6ee5c3f5c489a34e5f41c497cabfd5ede8fc83c61213a510700e775de2bbd054ea2e9cdfc014a8aff1caca4d043a014067a454920534f253e1611d6f6c40031e78dbc5faa0151a1d22e371e2d70c8617d6ed6637717d436a3d4ffaadd44873002293b78c33acc64d0cfe863c90254f4591e6e5130ac5e3277125ec4ce4addc646226310239089d7c3057b8b46e94adb96556e729a41971b20bb90ff52b44ac561ab44f87ad7e6d5051cb2ad35da325dcf710720e208fc427d2bfd72608248e0e535f0494f7237e294d62c6232e07eeab07700ccb9116fa114501b2031a7290e688520eadacd4180b2f1439773456e3fcff83eb3d7d88653546d68412cd03a8a9ed4f6458fb20e83a758b90b3a8997f2f2d4c4fe2d225b74d121e3ef86963930bde26f668f76d3109c68a48e4016a38f2f71c6d5e08944aca923e50b047212c1d90bc711013c7b24e4fa753d9f2a5c9b40a2b17991f78f302c4fdcb82167030f7dbf222fd5dd7da6e2ba9add88aee70e3ed484324ccd4165b7d515fa9d1eb6604cfe5d14764e9f7d4cc53015d0d6300aaf48e96e216be0f986d39d11fe3f7ec3e1fa08dce307c6190989bc0f574d6d90428aaed8626fdb02ba96c6aeb0a3c7506b65cf187fdf99dac52ae1610749b9476505d455d7cae76b0223e52d774d0517d3028a5dbabd47caa5838597ef689e2ce5dd0e9755186302406476411d9cf2eefa48ef5c5de20f953449ad7f183056b8c145d6a152c643e67d282b9afe2242d6c39a16551a8cfc40b4cdf1f0fa125115f602b87ea7db37b94d7002aa22c2299bb461a37c19d61266f2d5bfd47bd8292fd6e6cea8049d117ce6469d357c7d5923e1e32630d79a8a6b55f788caeed32886627a9f7b630b3ed7c0e6d366105cf78c48e1e73b1fb76d78caefd7063b0fee6cf90a4b1a92db43ba584c3e35484a2c248302654852dbd6fe89c0b5519b3af551089c5ff10d8650a5fb248f9acb2ad4ac983625ce2725adea6044db31d4a0db37cc2aa31f1b0f621a91205968c1a6460ceef8865dc6a0a091b2c82db4427818d562bc9dab9cb158553b51c1d4a5707faad2c560c09b6a1d1bc8eda841730707a2cc150dbbde76659bd5ea3096fcf51a0dfddd9b408cf413e7f9335660901970fb1beadc83fa7e19cd23e37cb077ee32d9ea91378774f3522069f1fcae3772bd120719050d4713352cbfb2002de20992be2fd8cac5725593d61d3ef78c4bd0f2c067f9ae2269f87438f68409081e8e43ced5f5d174735ccc1f43ad0d58cc124b62cbada055bd61d7c403701c22049b2b76fcff1cf960e6a9a10bc8442336a7538adab84942e2e6aacbc4249daa4c79418e14f898ebfc6ffc49c948ba20d902c44e54decc2b4ec89d32a18d29c387380e1d27f17d0615f9c52809da838ebd84a8c73ff8554a65ae2489d9e2eb254c7fce8af6df64fb4ce80376c60724e4f5f08784bcb246c96f0299f5cb0300b90d4383a6a133c99348be3ee3eff99a5594a7e954c88b34f678f304f30cb6fab35b75826a83af275b3dadec1255503a11b202e1be9fbff719bc166cd5f1d6e12455943baf376da9468d92e293d9f396a4dd593ae152339e5a076769b2d0a926963e00e9d77fdf961d633f9c8e2206ff55fbab9fc0f0cfc9b40641e6e8804decb612b95b02aceb46121ff0f7ca41bffb941957fc0befc4cae58eb4d77bfd9029a291c38c5ccabe39fcc1d21329294741c891ac8afa6e80932a18fd41b83ae934482781b5377fa00d2ae4baecf7357dabf777fde9f08bf15812f95b6312aa0c94394fb07aea675cc109fb54e67e956c9d2bcda96973d389456e1301dec86dd034eeb4543ac70d4a08e9ac32277c76d23527d5ef2d1d9e055a0579489dbefd65685fc3cba530e5cfa533df233d70c4e9b6239b8144dd91c892d97866c12533a1f53f992a50b9a19c46e43414c6e7b2083dca14f19fabd82ef621d0d48bfa4040926e3758be9dfe2b20e2fd7b93d3f0aae85d2f2d590b0515887caad971d6fead891d757911419a637e1326b47fc4789f8210cce68e753723f63c97e02649cd33f9c54748ec0fa3d1144dda1b0ecd36a787d18debc6b968baf54d40cd6fa4bd0eedc45950383a1fad83ecb45653c6d494a366d19ffa907d01003690d65c239f9c0047a72e7738104708480d8d39f3596cf715729ae2172a6f3e58d9b11b15641c301b25f4fa136597da10373671d338fea1796ab95958ec666e018c975d548d9fc3e756a4c9a23159993a094d31eab5f8bef60b63d87a7b5199320af423ee31dc51e322c73f3ef461a24656ec9129cdf426215897ae877454255df84d4dbc8828d8b089294e4c62e3f50985381254ab38ba1106c7bee308342aed064f4398092a84367f4f417b8cb5e6eb9f1eb81de32d50e652a4756b10f86edde93138de1fd8067264134567818eb7fc1742149ce3d3521ebf114aab0ed92b2cebafad506e66baf0a3d4cc005df8b96fffc2797556c67fbc2ff63d3a85ab595579dd58ecac7a89e20be2ec70eb6f2d93f098dea5d64dbe61ab3732084fdb511a1b4e250b6cfb709294407d8b842d5a451e72ec725bf0ca4245bb90ffb892d538556b55635247bcd65707c255e9598987ba31a3c2a0f0a1fe01a844ea283fe380565fc70197520383cac0da36c548c2f1888998cc10fcf74a4fda3e26f5221339670bd175bc98ee889ae2d2d66cc49be6ce5de2a79e01294f496eeb74db36c03b5b944eb744715a70f18bee5630359757751ec7a8f9bdd33b553936570e1ddaa26aee9def805511cffaca53824002d072a511bc5a23a4d9cb8699216c77d1235ead6a3ec3823c211e8bf6d559d3d1140cf2ff03766526e662353afc541aee7678e5442c4e23f681b11b537d67db31660e22e316d1f47f52175d967069aeaeb7a3e4edc8dcba18a92d55516cbc2635112a0cf159044e9001661d44eda743c93648e87646cfb04aa0dad0ccc8a4baeebd50829f800f4bd6484cb85140f87a72faccbd111f6afe8cb2713a166c643cf8ac7875bc509a1f3e89a6b46338c9abc45a471ce8ef040873c6fa716ab129f259f8fa703be0b34bb8dce86fecdceb59ec8af0d3fbb289781e869e57ba4de5d0f505779015d8d32b44c33a75c23cdf6ba05a7687d4e0d54f13fee11e1d976637b5a93a39558d9ae1af90a7ac4d0fce08a9d31eadc01bdadb11c56e992a6b49b6d594c32a6fd1897922f318c32f7d40d88acea46f5dde231be2e5246dad3b1ea15d6de1d283f95ccc43dd1e0a65f30c79f7f15a098fc8038a204a5d6d5f4f643e2cc4d494b659459dd6e45e8275f2dd13105ab129500a5a9dadc2cce09ee471324c8250fa05628d6751e022d3aab2b93d1ebc86fb662b4a58ae8c7b4512d15a5fc84e9f515147b6bdebbcb147eca51c4dc83c5a57dddd001891939a286f7451770b7bebb9a7b28164458de7e980c2f55d6f3f48d7d729ef4c68b0a11992b17338c11196429c3d01fbcf8fcc6811dc59e5638aecbe395b72a268b53e357551c6d97590b9e87c81bf9c97867955f9d016f97bb215c942aa3dcc32aed34fa3570242c9096cf0dd98348305d840b15f419b4de5e9cbbc127d75cf6d3f2bac00274d6614693d165d2d33ce19c91e4167cb2b8c2fde9e75bfab0d5ad6158ddeb839367fe526c2e3082be40806301612e618ec05a1bc99dbc471f7d57d165ed7fdba99d4bfb07c87a991bc80fe972331b15918d4ab2a4020570e93bb3605aaae8e7fe8a56bb155ce1a0268e0f0eed3df4820d6464a62449ecd7da32bc7650a4d933ecb88b31e8d0aa3785e78c0382353b715e902e4a2f72013fbae7bd148c4d31989bf95e742ae8cb26bd691e31472c9939cd6d17eef5cafa6d5d983dbb6c8b36095688638d709efbf16547403a5609068792da3adab43f87fbe1eba9b791725a2035bdc6b153ef00384a83d5c2c1bcf0a851596317bf32f8fe644c3f2890a76cc8356dcc5e8cbf926767621db7fd9d8c9b8ef1af1d78e7f94292cb7eafb0fabf91980eba3729d21328a12706019338a1dc377ef80cdea774bd6207d06c968e646df1997cd28b87839d58df842f135ccdb5fe18b4212d0ab454d30a24a035b16f88eba556883fa4ce3fa57a80527e79b25067fde736d1384f4d2e0a3f65d601e1412874f843cb94aab1643fe97a8ccfc68959b8413fc853964d263adf992b507d3ff16cd96cd9ffd1eb930ff88734bcd73e8869f36823b17dae9b55fe0082dd044a1cb8974ea762c646cc6718b644553b0a59caa9ef87bc73e5ea6b2374788aa81fdfce462608791321f27d040d8f319106b5ca31f7e88abbc13b2791cc84789163d344f7290a225af138dac26074200acef142048b9ceb080752dd7b126fef4b206b68fba7d79789843c79e5b7294799f7f57b6d7c07127bc247bdced3338feac4767e1d8f242ad8ddc833cbbc9535aebbf029057ee360128056d4908b669f446e40b8b1a49a495610d1551d7c7244dde3fc8653bcdac25b3f9efa00b7942a47dd38957648c36787b074eb9516447a5db218247190c43333770237245067e0fd3221f64d8ce681dc73a5437129130aa2d409a6d4a89c6ad88753303e788cd2e6f5daabbfb25012c08ffcdb742e9ca8b885c59849f63398f6b8235602498967e2f317a083bb94e27a6a1be791882663fd314ab673311b1f17716836919beec356c08d0dc34ef9c995a255956a190a901bd62a520b08e49093d69a9efc65a3ec2a884b7049045c23de59135c37cded5e5d5157307bb3f29c63f0ca529f110181b508d734f8175d7a1c49e3eee1f9119adcfe71dcdbe638d72e8ad4d5f97017fc0642b438d01f1836123f4077e5fd01f83922ebd0863a06daeba71ab65daf1d21dc3644ae5780c68af7797c827b734c0814359f056dc66c3a279c04bfed0242c84f5f38b908cfed8dde5f7c9d7f59ff138e863e253d635687fbee47ac1ca0e1c59f5ac3ae4fac7840192c5b912a2f9feadbd30a3dedfc65cd9d5600d40a318eb384b33b35fe3121f7bbb060e1948ae0bdaea278ccc5495420abb2c2d914399fb1442ab91aceb1c344bdfbab207bed9afc3d7bcfd7a992fe5cb9f10fe61985c929b6d07f10aa692451729412ee5f831ec1f1ce7c912ea60d1084f82fc2374a4f921522ceb56cbf5a40b53684358c06f9837ba552cf2b516e301d3d0d9bf11b98476eb284c5839b86364b2a4b56024c69f361ad73db1c4713aa95ebf2f5aa8c1cf26842eae315ee98e8301b03fe76f3e52e4c1141b59a07c96d840010f9aba1ff91d40556653cbad044283ef0e45afffdae9914530a2276a7a42be76e6c9ada899b96975e2a92b0ff0d0d61f5cfe492fe8d8abea40831af9d52e7d72108fa4afeb1eb2b2da617d68301ffc76ee391a62d92f2b5fb5b3241c09846fd7086fe2ec2a0f29980d71c7036580462d2e14c7faab2dada3417f77e370ffbc7e7a385a3101f079299d3d4f1cbc5e6bd92bb2016b890e39a8fc23a78dade40c18bc14901309c109bc07801998544d81d341aa848511b3f59948cd6301833988358153ed55744fdb886f00367234f342a0e080a29f9e64409dec38fb7dd2d14c389831268f058fc0948c16c5837cdc1dd406c7386279d0877a07cc09a15c3475c9ec3ba8f71df2967d7484684deeb5079118e0d261e4b8ac8f9b67e3c2d48e47f5b5340286f0b5338d247b841837747b80f436add8174c8388dfb01b021861181be339fa9a957f02e6088a5cd06229fa049c1ba65477774473d7c07c8c8cbf6b95d569d8d14975521a016745b6587394f7368b3c3e81819221b5c59ca907902f0975299026855ea22613c98597c212cdb742ac08aabc8761e6540cae39218bb68279f0dfb351c1b6bc9118f1a5fdd96a2fc926e347e6fcfc3f64c9d03441cb1bb2d4a55756e54c1348b088056311804153c02bcd76cf99a0442b52a9920039fa640bf18a42bc2952b3e48fc95b5373cab2a35ddf341d23275050568cf323848955f032125f3985093f85ab3b7a0d597a990b1095e54c4d08fa53145e8c76bd5c2574fe3703ccdb2b35f584c15a0a53a79751771f3d24111769545bc63f75c3d252d358741bd76e4bc0773f1e7562bd33ebc63e1cedde51952c53ea66bd95648118fb69218d804a2a3f35a827fafe9a1fcfe26f2270f43186d2238d1614dadb005b637d305bdd8873cde8c819cb0946035238c120a2060c93669b55fed01e99a584c986856acb837ddb886a25f3d4674909aa5484fd5959fbfbb1d0bfb0fb3f3a6da3995e874580c0b364d26a0a584d9df6c414880715689f9771c5e2e4a691bdffa6123f9e570181ce6a0399bf54db77ba6d5ec256aad621fb4e5033dc9f64d63e5cf99b2ef3dd4a2e9b15088ad6cef0dd3659cfdc685922654f10106c6713274487ffcdca192334420b55adf9984b52d746fae8780e3631a99dedda81a753f863e7fc6caf1ca0fa07b6a00b402134c5bdc105cea523c107f7e5b0f36a416905cde048d359a577f16a45c4fa895d164b11340b7739fa87b04cc795237fa35d3fc49f2650245d0d8beae9bb95f07d214b4854fd7599e61a331180c7d5a7189bc4e0182c005e050b78b41f163baf6aa627d7fe655a8374bc4f165add631fced0b93e2d494031dc8614646f66ac2251cfa8f0221e77e0ab423364f511876eb21f0107fa29be6de7d3ee9d26e724040d477d3632564d1e03a9bb5d4c322e74c26d5cac078b72647d9054cccf5bf475f2def39a429c8d8459e1f3126eac7d57e8a75d43c588d28d8b2bf7d829921b19140465956a565144548e64d306c7969de07860813920a16981dcad3a69b4fa559121d4a73828977336338b8900f79bc7f02c9c344c24dad50483de801c37f2c6e22416f2408d65b3de02991b6d1cc9d52fc60991521e7657987efe0d48084c24e45afdcb0479b6c6b84f45aebd671661b0676606d7de7cb1c6a3adfed564035c974b5eda1a50b7bf5bafdc6298056d7454904603e5261ea3a7ee7a0f41cd12dc0903e52f650c69024c60b30d5e01a40e7c008b70289c7ef80c416c55aec76bd38fec072e4d6774f4d31594afea6a9888c82fa613c6b631df7eed0dad8c732f467d5b47abebe5df11475ed0ab4bb2471a46ef64d7b9514385c35d69602aecb273258be53d895f8120e4010f2a41f5764f07fee2511c869177a2fcef20b41b4156583c846bee5dce90abf34a0ac48618b40b30ec6b72d53d25eb69da85bbfa963a0e01d42a6366ac9549fd39a5b2e07e276a163f63e426d42d24fb3f2d573e4bdd85db4c0c6bdae64bdf8a87ff6db0527a72a4dd1e80995f0c4e0507de728a96c9476493ae39ac4f327584aa82050626eb481574a276579beedf03b10608ea218576e77fff9dca784123b78bb032408626e4526cc112384524110c4363de2bb6fbce42cc4e88eafd53cda9f1dbf8dbb44b4de482130532462315ea61060887b7f1cbe91199c3b939e8a5a6197ec3cadc18fb08b6f917ec7e5a70c2bc8f54cc4c21d927d08c562a1fe644d8109c239441d31cb8725353c6b21ce002dcba441cddfbd69db56a7291df27f427aef99b6a02d87cdcb0fc4cb37e4d846b2529a397a400561c3d9ec06de1d28b463645e5124f6f84922d697793c3cfd8624b8a61044c39801f532bd28e20c1a359f33867da9a634632cec38d7949007da3b6d3d3f0287848e105a4ea4491d688ea9096075d9827eab814dab0ed95037636c642f9e01a3559c85d8463e47d70445ef8129868c746c1b4a60e0b61c991339c43e68b0eba6061867a3579f0e56c3e154f30bdf727e987f5abbfff619eead6290bb4102e06610eba077c1f924f9d24ff3e3f902d4c4a175ac69d858a7f4b3d6fad30494fed3a3bcf90a76f5db5c94f0b86e8f1ae6aa249cdc695e2d5bbd1ad6c876b4bf000139392e9a9248a073745b2d17a54f48b591a64f3e312eecf6257a2d95c89f6deaf7b966b5585285bf10f24ab15190e4368bbce3439254eeedd3cb6389ca2a385e565884285c3cc1464600b9201a7bea781123c92a59412f8f4225d95bea8fa58d3e3e8a1d8a559eb22edab423b580415b87bfcc1a40cdb9313e12e0f058a54516f4eaf7c26dc462f0385e3eace0c3be08a147a2dac144802b739183060c54427fd4785630c09a5a2590ca4aa9d3fba85ea6833e7cdb165f64826a47a6ee35bf659bf2cd6d537c15e99dc062ded1060769550a0d6a842b09752a9f44511fc725e88f8ccf2cca47d0aacfaa766d7b2f8c475b9eea4248e8e842926348328cc031f1022145c063d48fcc0d25fcb9e5fce1cfd2f71975aef908c965231b095277289707323cd8530ebaa1ae1de3aaed0cf548a694e0870dc8ee3a4846fa05bbf6712f2fb5460754cb3350b2ca5b86f0ce8c7396ea5b3e842bea13aeb976cdd26217811c40535f693ac2faf2c93cd31ff57e96fb9db5c1ff7f58dbde512494167e4b49b85e3c7179376d86f12da7c12ab2ffdcd659cf3242ec00f3c96d7fb4e6951334ae51b1b0391b8003f251bdf9e11a75e06143467c7c962c29197ef8e24107c995c02b53fce31e3cb327ed44c090d2d8bda052981af3ffa0ba4019de4141aeb3759bb2c5578a772f05275dd8ebffd830865164c8041676f8a934f32d8e026b76cfc8abb22c7bf36d1b631ead7eb278af5062a59349c680a06681d830da6f5aa9ff5d49bbc8610cb6052acf1aed74aed08f30d8687bcab94403d8b7145676559d0117e299e0d722f384f0f1e330cd583da5425e954d9941a48a0454b62345be798117542a973aaa1a82a3eee3ff17888daae970024459bdc5a64fb161856932ebe8443dc80873e86686d39112aac9af39b853d394a95621f9fc4bb9306638957cbc47bfdf8d68c02407fcb70ccb636c5c328ffae916037487f3650d1f5713329b889abc29595a11d72b619b69464fdfba0569f5c0ac52fcee7264d3e760eccfff87be7fc17ac0985b537e17f25c6d0bd6658b8c0356cd17ba5154767a021ecc81f7cb8ead293579256a89872bde1aa89d0bb911de9da2d53e9a8e2fa44a84845f16716a675d88637b8b9d3b1e2caf848324a350fa8452ce6351ccb5f683abe765b442c45c7d619f2e26e81db517629923a143aace47b8e1ad01c016088f5a1e9304f431652e21833cfd1c5b6fc4d0aeeb6d048b82e71947cb488f46f4d9d0579dd799b5af88d3548495fe82339a0f4eea4b3b9a0da63df1ca4488983cc490276df999840b9b4e328c9e42e996990e6e529d06826dfc2e7925e66ff38babe00b38ded8aa094167429dfe66750d2e878eaef13f81dec1baed2474515f43e44514abf522054a8b693a63f09eead67773bf2a1c8e9b42fe3dc95909fbf360819748d5d1156a64abf225faa56239e1aee9ac2174b2fea8adb064e46d698e9db35688be08106c45154d87cd008af86b3dc29ba481ae2ad7cf39b7a4523082f5b2d459173a202ab62d4686894d1f5ba3fc44949f016b947ce530623644b82ce6f47d20218b0beeb7c14b56f4f464896efa4ea18b65ecd155c3f12ff45e69efd6c866bb80b2660995c2dab747e1e94c5549ebc8194d910615df8e0e617fe1f18bd15c98d3aac7c460d912f64de52eac3d7c69a6211f4feeb1485354de5435f5cb23892773e4900a93902b8a2d7ba4ef04cb766ed9e0d7fbeaa125ec1af77134b1aaabf256881904d87a4b5ecc0c9a67292e3e4e375c32a39218b84aa48910d9fdb8cebf3452f48ac83d891c973baf3d21278281770e249671976da55cb27b346c568064848aa0aad4a8822f4a35e45bb9558a264e5f42625c05e04366969f7fb1cb60dc33dba745ec0eee614d53800e3aabe1464da701d65b33479a9cb08b92d19973f6c2fd604d6e11ff784a91348993ad32c94fd8d6f58347b65ddcd752c31557ff9af7bc5a5e4110ad5b09f3d601526cf4031f18b2778c8f6793074d5c5478a0810d8c9b353d8b67aee1223adaefcff5887afeda2c240e2aa6bc91519a1321331332374a8764de693c04032501e52f572879ed4f6d5698ebeda400cb487f2a01a12e787de9f07bc31548743ef145481b1dfea2388698a2805bf786a47f0289aaabbf7612e546dd1149f1c187a9dfff4a0359a874291a3f704ae99337c5fe2d76199796e8248263fa67249a41644819fa717827c08996c23fe823ebe4a2b5c853da48d5c328a0ad117c9245c595e2d76f581f53ee842a187ba15e3b84c7fd44ae24e5402b965256bd460f42394643411da910f8739e9f67bbb0a800f184fcb5db79bacd8e1bc624823b1037989856fce7d71f9b2e6619f0cf51a149b7f8b54597b2d0d021af45974d364e68b98a693b551542c31c70a8a4e57a5be7517403a02589bf408619a7fe84f1d2d837335a901ba7a61c77bb419aa1bf67634f6c7c84bb2edc641085ba2197bae157a27f22319de4e9f6cd08bc81e87f1b2b88d70e62ccdcefc548528b345bfc8b0a04eecd76180777ab89928d1548c862573d26c0c3c66369103ea8177201b3a80451bd1b7e247a687ce3042cf5f0b2a7d208f6d8c57f0e611551115abede76af419641be5d2490575ae6ad161ae5a6315708ec75a91cef291dd8e69f5d8f2a67650735f1ac0a9e5fdd539f5b07513ca86dd7c82694aeb7fb49afb1f6fb23523b300ad836d7d316dbd6d9a944f48db143a4e8c708e474780bf7455a9a4a8a053d40206c554708d6a2d71f52923441ae320dfa32e2b542399d3b05f698a3d5887cdde618df46c1037524a5ab7c2e13c0f8eeb4e57eb77d9f93166e21d5f0831363aac6399423ef87432e28a524f291f279129e0cadb4e2f905828260cf2688748a0f16aa8927d433e5b1c404c918280a6b1db9754b1aa14ba473ea27a5fb5ad1fa0db22aeb9d5342398f359a06cfe1a1124cb7ecfb682f3f42513aba33f81bbbcccea8bdf0b0f316dd5a474c9279ef82ca884cbffbdf1930482d63e4135b66a4a8a1d398e205ced83e25019b3330a6b2577d71c95d47888fa2a3d9fbaaa415d1d00a20bd8dae0dc5344c3db222d482b1c5c986b2636537f38532922de797cf9dd3550c74456d9ae5153223a209f22c4df77dde8f27d8c3b46bc0b7b65f97471816c43b392d9969b476a8e77ace541520dd956dd34e44825f8894eafc234a12f97242f428244b876d9ceec46d42fd71dde5ea1972e3f39a8b1054a1783ce2072607c0c2eba2e45e2b241c7bfc0dbaaa960b1ec694998c0c02afc17c8fc7711995d41021d878c59835208173d62a6ca917c3cdc4b53d17c8e41892e089ce6ba23e16e6a78deaf6400f66073afa118507f92faa2de3f151dbb6d58b6fe12ec1fa6bcdf4b8dfe4ffa3acbf6e16071ebb449a4bde31d8ffd36a0339cc2dab9dad02bee61dda7a826221593120c7244f29dc12646aadc1adab1bd6ffb31edc28b128e5752272db8c615a12496dd0f0f0941da0d20a63c36f88f53890e5467f9306ad587e98a2bac8f2b722d7521494e4c61e448d87ad11e013de24a8fa7b02f03e5257a0b84250807534fc7228811dc0505f0a93806117ca13346f643f28aa99c34f85011ecc3b3d84b997066ea4aae081537222c55461a2f08ba8c690e27a5752d6b2d1e2f945ff75391abbc2a6f789ebf8fcf1623ac68d76fdc899d0b8c95d959abe7c639e64094507b828f108d62ef3f48fcde01bb26b6ad1f1cfbb268e4ed8def64812a6a87992cc93d48d90aa48fff29092c0e98348a19b0378388ba974f9506761ea43e722e4ba28c42b8e1ddab240d64629c7fdc3e891f3a9fca7e6f1713038e965f4daa0b7becfe9006dc023534fc020b393d9ab4bab42e472654f4f62a191d055feda138f0fc7272f2318276c9937af2e727a3dfa07e8a118ded20d55a3efd7f761bbc14e8ccad8947288c8c0733c2fa2467091a1fd8e6763154201c6c3be44c5a95e48c5bef4a931a106fa6864bec9ba3a19640f6bf4555ded388b78d75002869b25dc41e3ee5757b3e6766e85e4785474133646900e64ee9ef4a7eadc2ce3413e2f8dd5b36bf5db8082943c7a2bd40577e799452f693a0f9143c3a2caa612fb1c6ab581a59574906d171756f6c22e5b305f0324af7fdcd8ed581caaecf2210f166c535270a1e82c93fe977ac2b18e285b36603bb6b7e7ffa84f7f8e69ec4feb2089b5536fb308a6d3757650394b216f7e5cc752e4aa459fd8a0dc2bb85d71a2a8368b43a383de52e95bf08e63497671267afb330fc86cf284326d0a685c0ee7649ed23c8ddff58826b22b309f9612d4409519d9479d1b8f2f96237d732228c43455209ae69dbf1cd98ae497dc387232ab33763d70fa6e783e2a5d5e42933f401a72b5a0c055209a23769c17eb2f81dd24b6c068912501fa22ae84894c978b6cb7b27ffb0db9b78880744b0e925748d416cd39f0570b1ce522cdb09e8dbbafe6c78e2cc5758eef4628db21cb9fd3024c36029d677a6ddc5011b28f0b1c86bcd629c1e9e6736d42dc83cfce7b00f857854d23545db95e1830f382a267d54bb3f31796130496548ab1eac93d2734c175d579a6aced81320e5ae2c8b0b83ff5d530393342761b125cb0047806bb181f0be6c15bbab38c5b59e8164172f4818a5411eb4cfd8ec9e8697e111e17080afb13f247a0080653bdfee9f7037a3567399457b7b1218ed9253c65cf3104d49ddc04a00a833543f59c9a7c66a0cfbc96c840bd4174b216720b5dffe5210350fdcff3db1e60a2a269a76cb61bd25b2895d15b2e768532aad5b32d9812211068727f5256c778a0da27554ca7b67aa923441dde50d36b630ea545f3a28070bc55542086e8aeaf06894343b031968086faab61e2b29a5e913babadca4b4d2f27ed03eea288140de8d3978571112789f8359d44719f7734fa3e0ac6a38360f596cd5bbf6ca1cc06885bad8861f5b5e225fae0d388d1ab8b56defd791b3ecbef1fe26052fe42606b03cc51ea11738ba8ebad1064261f3d8bc8978e2e9624a3221a7dc61cc7240d3582481834c606a630dbb7a82e27ce7c1c5bfb51d675ec9ebc62df913cdaf7763158a8f6132710cb8cf5743da204741d11270fcf98db0278a0959b7134363436fcb7100be633f64e8617ab671fb584e69a1ec205917c28ce51db4f9a18de9907f173fa1c588c1a5695ec1e584229692a40cde670029967c77587e02d35826bd1543c48e461571d520350e3358be3f4e0f198b708d30967bb711281e754d343a391c9935bfc2df573671b712f948dff71442d9508273d16462c9b605b0863992add67ec6095bb9c0925be24c134c17aa1333eb1c097a0b7d42746eb2aca6c5e3eb91be2f514a85ee412f8ac76468387f6599a80fa94a8db19a1e0177b25b462f7ee6fdb95858467b133d9142a5a4799dcfd1d4f76f033c16018823825f1c970d9cd0082549245159b950d6b2c33caae0e7e6fecd846da1e9a55292a0e88445b252fcbf70460dea2f85d007b887e99c998f1019f1e684386d4b54696588c45aa6bb5b4dec7537d9d0fe84d9153995f773c9d03f388aefca16adb6ac852bba2c7822e7bb199960d0b87ce2e3c7be1a14a495f67727be19e9c5ecb838581a0884271e32127081c8dc51b4aeceded0cd91d25ff1e594ef370ede4de000af37349b84da73efd5eb9c5d1ff977ad0a72575987dd5aa13882b4f3b918856dd5a9e8fe9500e18877fa8a0106e62454acc81ba02f88273411c6d9d1b19313963ff14773916b4405b271b2e1f4b74741bf2bc06344007e08f97154bc0c326a5e67f6e71298abeb2af108bf11e6592d2da3e1d87c583c78cfd38101220324274d5acde7bcf75f18a41de419f488da8ed058df9d74853918ccc7166c88abc343ad81de62320a7261ed1856492916e1d81360f812c3d27caca99528527d46299d2cee2a657a8c1cd2310ed51daae6b7e8e8976e63d270d19055cf73b1a2b3b5d6a04bba43657f33e7c6642ae8434c0d117e9e5b926fd310b4d2d1c1cfe8db4c630f5976d7cdbf36f21624ec8d45f59b3f92f2347060afbf20cc00cbc4d829d2c9b9990125cfffa51c60205fe3e13828e3f4a4f2ca3fd1fbddd58f2c5497e95e0f78b492f6083a100e27c4d5fb4c695a65bc66fce9971fafd520cc696da7647b99689a66205930b1483474db1b96fa5814d64bdbd4f7666cd22386d432b6b664e901ab088cfd36a5769b5b8420e9c76803a68d27b562c2440b0abafd54ca5876ea0004bf3a6b7f06fb59e16f69c1fe7e99f98db2ca6c04c7820f5dabac2f8467c2b538af6af914ed5a41233d68eecb638eb5bdc6e278982aebd1dfaff22eebbc8ef4994582c5bb53d4623f7cceb6482e886c16ab867473e556c34fbd405eb7ed18b2511a8e2ea9c68e77a489d360758e52a9b50e6e8796e68160349676342dd7b54de6ae9d21af2fb963827cd965dad131986059b7cedd5c361b30e0ce6d26f680a64ab1df1148ba32420b1c22e0ce04d89a0028487fc56c90d00b4827caef6c5ba13586bf59c871d5a7da1968a4f41475d23e82f1484e78da7f59fa2cd681edc611c43b5eb1d65986ce972aa41a141c9913f27299fc476160039b746b8a7bd1658191e05f0e5c9de7fa6412dbbaa3fee2ab5f666df9d83cc39076d39ef70d96387d5ebcafe7a73f4369862cb04b4b1de84d33b6dec5c83c6887f9f0461c424076b7941138dbb0810f3948d358e14de3a0133c8a88f932ec463722a94d827f2c91f838de93efb9479c946b517172f84e6d35f26811a4e04c4fe6285a06cae231ef37dcb38d060c2cd2c70a6d24a6883dc3b67a34ad6b4a40e41e7ab0a4562d65f21d6a305a7433d3f15109e99352b009da1034a3eba7f65454685ade808fc63c0c0fd0712df524800eba582feefc4ae1e5525e01eb30e461b19e065dce898eeecf53723a0ccf6fe47ca565641a3239620ced79b7ef6a942021dad7214fb6df2913f9df8d20b6a44f60122e60f7fed1a125c911f8c21f0227015ffc599283872bba9e1ee466a278f3e843f30dbfa4616c926c1676b46eb146db44fa38af74ac215a293846a1c0cbd52f26d665c8fbe50426ef9f2f211beb8a6d010e33dbf30106bd8884c6af47005de35c4bc4cf43fe25ec2423e0cc4401528c2da0259dd85ad6b22c56cfb6685d9659859455f84a48a55cad6fc1245f2a2877f1f810e81c7df0263473a9e1a50adbc94f11e24dd58d1192817b56fea6648e6fddbcf1ac1cfc8cb8c4cbef52a4e091465f7ffc0a557c4642f671e4f4f5d5c4de702c1b4404adf4635db6dfcecc003f5f8b6a4200fac7d56e9499bde8a82303d73140a1f0ed520fb28006fe6af88bdfc5712f7193de1df427c89c936c105cf81993eb102aeccfc7ad279a036ed573932f342e509b53802e0738beb6e9199d9551f8069cc3c557b581f12b96ed73ffd2f040e702bccc489ee1b46d85fbe750b9498a291494a6a340cef23a743adf842c879b36f508c02466015e79c914b24b49b7f5439406adbdf2264c2269709374dfc5d6dfd8fc142b2bb499b9056fd52baad1e311ede86c400f966181ea82bc41374ba9554ae3773579f7aade0d3ac7d6cf2fb4a40bf337370c9ae90d21935bd8af585dfb6c05c22bd9d3cb52fbb8b85c7edb9bef74be7c7bcf02897122b7f490d1bd826c78a48c4e019564e03d2a26304d6101403d4b6d7bc0692d5135efbf04f5ab5e3d2473e1f16fa8c8bf01374e2732fe33043e00af9446236798a1bd6699c64512645552e5d1c152349def04810ab1cf67862742eb7e7745aeb9cfa26208bf2794fecd02502f96362fd6809ca6327227cd72cec9198eba3961e60a9843791203f5080f3dbb7187883dd53104a821c6601b97ecdc8664e9caed1cb0f25ce929af9f3af864944b5fe14cacb42308c21477a3f0903a5bbc7459807537be53383831ff3efc061bcba2d7d0e2060596e3556d970f375a599dd151786d63965b2dd4a2d697e6e50a2fd50131f1c2e6a2dcdea9050ce087b02fb39a0c133d2bb6ab95b01ac82aaf0812493863bfb6be422bb4eac513c749947a65b9f6d74f1c37bc6f495b6ee2b91e4e38fb2e81e92a4c06d5cb810caa86c4c15098b89943d33517fa42d6ababaaa01d0d33df3591a3964078979868614de9a32c27ad6b703e34dacda982547b79ad28840d4bbed64fcf68557b1225bfa6a33361013b4d07259090f4922c7a40216810f60361851b5b98ad27420e0a60d60cc2fc71a41b00feb32be623d33f2857c15ebf18188294e8ce11b4142f22a820c829b86dfb60eae2c79c0f78f223e72a4f60673b0eadd3f2b00f67b0b4154f3a93ddad0b213e48e03eeca1d89ea6748f961917c5c4ce5f198d5e3864e82df084687ae309d714d845e0d579abd2ec39823fbaae83820f42f441e545ba7d9ad22a95eb9121f0fc8ebfe2e77ac8e93552078ec29c03b6974bfbf573ab11e2f6a58380a34a2397a17b40299a2da3115deaf65f84608a6a89db94148cc6b84f43bc05c84d43b17aa2a7789e5172625672c91fbefae5e37fbbe8ee6a9c3a17de1971bc5b482c8b9ec2c26d9ea8924e09e7a1a9e8c0ca7e28d8aa1847a30dcc75e739c415fe7103821c42dae03f7f63ee94e129d57435873934643a6cb4f03c7cc653e27506044fd657eb60a2b56556b38f3d48b9116f53cd22d61a67e46003c5386e30dc79dbf9b8f82fc293ac6eb3046cd631dfdc5677755e5a60f20c75f47c1f2e67c46a3df0c661804b48909af4402d18db5b37bfc3c1a0debf18ef2aa69d3bfc218f8068b7632e1b352c22496fd5ef19cc8939d970bb020d2950d60bb29b467966a67c147e3cede73d786a381d778f5ca67c8768351d0d1cd286bd45b2ef7a3ccbb9a43d2113e357d1ddca668b73c5250e94d03cf74da268cf3db9bb581cf2166b5e173feb9b54a61a09151706e6120025bd84566fa0ddeccf6b4674926de50a980147403384ecd34002ec0e50aff7dd9d9f648887588232187f9f4a95f84f161495222b6c13f3bec93d7f315a3c80dc06c2f65f47bff0cacc832c3bd1e5b8c207ee90471456b5e11dbee9ec77e5ee5a23f9980eb3f609ccd675d5307c23cc0469c3a9eb9d58e55f249a5d74acfa78f23ba6d44dc0b4cf2ad5dacf3bb9200e375106707d1421b8592e7e967660a012479b955247e8d2ce0471346ada811bbcf9439f737dc6df9dca9e51b9d31d6c0e43ca340c0ac57416e6c4f014548cfb8f909b40fe0b2dbaff50a8d87e564d58fceab6950cca2a72aef7c63356b27a606c2cac1108cc358d102621b593887e22a3ec8993bdaa59ec781f49ea47935d4ae8758a0aad1a351b85eed6df844a325898a87b8d695d60077fa902553c210e5a4996f95195d4226073ba6fe7224308fa2291d39214090e382e150405ac35fc3c197ebcc66da356a3db6a6b87a924f94d5959bc3ceca76ff1b714b9732500a733b75e2012ba41e9510c733534ee60cacf72d9c95e782946159de811ff093ff5db297a2bb2d0973285558e93959651f40b46a7a1e14d91133978cfee58041615004c62b797fc3d8472586e1111b92d7bb06cbc7f48384aaf30f21b08462c2fa2347b3e2ebda335a4745d368c44ed3b9cf4357723607286af881bdf4ebfd6e3c32b216b36bf1cf429c398d76a1aa88eb6ea987d3f99e09a95b683975730ce82bb1bc6b62b5f4d5487ba21ad1e3a8b27faf2d7807dc283fe7e21da061ed553b0163b6cbbb665ffd2e2c1e1f6405bbda7904bf601fcedf02ac5246038a6aaab18a3a1737c2a369c89c4a4d851b88da0cebfcd92c1949afcac328c0ee231e1ca049901d981dfce20e5634c0fde9db1dc3529753e7bab86f98b9f808c036a2f106cdfaed9154b0b4b3a29a5add2757772e72fa95c47701d84791d0ca1ea268722325eff12011bf154ef3dee1502471b52d817233f0d90d59c47143c122137cc50e315f602f4c672e665d88e4587425fd764525746806f219c7a9aa607fc1a1c05b5240948509335fef819723505c3eac3eefd99f855d80dab048f15156ed12b09980ac9c22f01c289f4d005d349bf60724a8226a96df4f2238adc05fccf732a7d5bb9f5795be1b13c4da4108515788ecb4ee49c9838d3301a89a0ae648a65183b885856a1876ead26a00db7edbe4d2127b130a07ea835deef79471e1dad7595019e12bb1f191497c72a59e0b95bccf5e0a66f81825fb7cc6166928ff3a3be60e2bb912220ff8bf8376385ffa466814299d279f047aec4667daa3873dc6f7363e73824fd87dcf0261857a12ea5116ffac65d96f0071e9cde6fff60a78639c97053cae42be2b93e0be0458b4d77ff63a78531b083aec003f086ae8bfa6ef3df11a85e4d5651687c15f91c659a73b2a2e8cc9ade5aad80eb3ddec9b67b22a1e1070fdbd12ac09a5a7ad7ecaa89552188a974434cfad0d193bd8b74ca5fc30a033e55e46211bbbd7b8aa5643566694432829fb5d338d110223abc3dd30b52bd17d36b5aefd2a5b4802960501a10c2437d36c6f63cdc239709cc293e702509b288fe5acecae4de0e062237c5a3e2d4da65e77cb4d0aa2a938d7d1ca26aee5eec1e90e9ffbbb14c3bccb60b5f0672fbae7b652f810f293b26d8e63c9504ad9d28160c840a66cec246504cf801417df3c3f9202176cd138a7a59628e166b36821d19304333398a6b982bc2c9481f6a107e42b23ea679434354ae9dd9b981e2c9b05ca774ed722fc61cd6b9036f1c604efa27d232ffaac425083ecb9650cb6e7d4c66ab8478a4afe5f346b700e8ac119fcdc1cb297dcb5a22083e6321acd674946adac45bb8ddd42c70e002aab1893ff9c83965fa4ef9da0972e6c7b1d0aa6c760faad50e484252fc38391a79e8f9d6928b360a8be200d558b0f0050849c882f39ea4397dc8fa96de715222c37d33ca79cbb7d36ad0bc6c376fdbb833fdafeef778a23b8be844348dd4f62b8eb4c9528b9a34fd0676b81dbcf467f20b6fc73957c4126784e900a6bdc26c05fe4c29937a97e1bcdae77223eeed2fefb1e7cb7e739b63249297b04affa34849131aea178a4472d462d505012c1a50203492dd0094394ee935832c71ddd596f584a5d6e4f77a30707731a8eb934dfdc5827ad401c36484cf69b1ef48c3eaf06ecaa9ae0863dbaf141a506c1492c73aca8adeec9c7640e11e474d05405b45e2a20a8e05d4a40d8c1b00c0aecb6c31b23515ce482ef92c76584251153a08a87c38140485823cea56608fe916361e756dbb5ffd545eb8f17237081c585d114cc6412566253d051787a64f3b96f4429a94e19d9efc9a8c9f23ff517fca78c8fefc51df1512f82dec6e463a6e787cd959405125a223a187e44b891d8d7f8157356cc85a8c26b453f170e987fc22dab7ead3d582b34cec1ba48cf76cda8d22b8ce0c2598ec3cf1a1c850a204fd3587ba4be4f4a2d3bcae8888ca4e5c950ac79c0ce19c84c7a149015f6a850887b2a76cb2e931d399066bf650e706a74051de38591f51bde8ff340dc02fca320d789cabe2b7483c31ccd8f5d8cfa77f4065a45b0e42d63207a55afb38063c38cdf48bb83ca7bfe4bbb91f23f0a49547a604b468ee199cca95269ff884752f40095437c696f3a681e8ebc4b834d08cd9e4165a7ca9dc8e4a138cd449192f62d7e726b73deb3202ce05c24eade788a187d2b7829c57cd0eea08e94d918d9bd46504ea60f4c921ea483406780943220020fce60f01782f8386ac4c32fc03f72b2eaa0a5544dcac8c8c7f303eaa5ae1f3058fdbaff296356915285197515fe3496c84f5c5cc17b4f20395b9115a71fdc2651507f6086f0684a4ddc798e479495a90aaf69c302d6830edcacbfe2a19e1bb0e747fd494a7f09a2c1f9c18ee7b580b9f6f32f5f0e878157a1270b32a8c9e16d60c173f71d0427581e221b5381cca4aa23c6e413267c41fc00bd5c3e508b5aa1a3c9c29acb61107396dafa25ea4987230663a431f8b95c06a739f444bbef62f148d1a5201cc6c762ce6c7cdd892ec6c6cf8da99eb255cba6aa0c75a595b71262257cf5bf7ebbc46d3cf6430800286e2b6b3593527314821a5cca39fd546e141545965fe313d905b60f4583594b9eea17769715f749033066887db3c50929d0514f3802ac34d7b0435838d3429f6a170dcdba2818b1603054e5a451792ee0d5f85d56271851e7f837436106d5e27e1e3df99d3096ee72a99edb610d3e95fe1b5a553734291b4ff89743b463aa771e66bee3ebae6d0e53436d31104115e90b5c9c7efd6f83f132600c05b52be5e15a7095d78ee3f837a27411be22c340e49d757012d55fea0060114e0a90ecde6046c9a671500f9f30d2554b62776225b49d0462212c774219bc9fa1a9f5482f31eb885cb57cadc40bf454c694493f2d42c440d7c48bfbff227b3746afee1648638ec42536e3d58ceadfbe57bb31492a42e10c02ebdaf142f4fb72992f7df611a19b3e8b3ad8b74b8726e23cb40e887f26369bc388c31770fcb3ec057a67b6efac000c6ac7f38781187bc95e967cda1ffc1f7e49104575287b04adf01ca8e905f87cee28227cb2882f27a345f6a8f4fdfb1ac9574c3b17160f98fcbc1db34fba088fd81533bc3bec3f3a6c39ff7481565e183b0de347de91b18bf76e51e4df6b91fafd46d0b5a1bc36b9a6839fba0f73327f8d46aa79b67b02efdd7aa568757af461dcd7cf8c1f7405a01dcfba58acf39f91d75702e221eb9b949c63ac2e292765ce3eeecbfe3dd68024b5dd6a44dc09194f1ab69f6fa14ec34eab1aed7b0b1bc8d2ed69a96bc42b2be47a01a87863fe5c4c3f58ffc3b42330da2b139b9fd3a0f677ce45ec108d1c1198079332a8638252b5e6537a675f1e28703df6146677404dd5e95e5acc3c481ff3a6bbcdfe6fa8d4b560e78f822a6bf938a554fb3c8791dbcf634ec0b69c27ebd3c8a5e25488d152eaa628672ac190bb19564033b6e470c91b10299dd3da0d8360e0177b6ccfbac84b734ddcd85e50f536885e6bdb69251d7aafec46d10ece2375bbfba8f078f2c94ecc625db758b4681f24a9923e37ef9e294fed48de81484efafef680167cde10759bb35645e2b8112e6a487e299cba874ba23231dc30bcd5490e29b6f86fa77ba1a6ef38c4c5edcdb6b86b77967320bd9df20b5e584c428dcd21272067103624187fc2564eae7440791d4984af291e0b8a84e745708bf25f93ff7ed0ffc8de8aaffdb65de76a920a05cd8cb1bd3fc9c628e9a63ef7d869a617aeb5ac24c1d28abd4bbab32ff9a9c0c4d6d2f6c398e7f3f168fa2206b374d6ab9592090fd28e3f1a451ddb6c074a66feac6563955edb96e3ff3db900951849f36cf02b0798f319e15835a3dc454104f4ed4ecd0bfeadb76024307ee344887e06519424ce9b0f41bd2b7e84005ab5812ba37e03b12e7e10c4c05dadf0cba9d308fd8105b2097875e9e42fbfd3f835e37966152b1041d9a96151d28a26059d123e1d2167f25bf42ee0cbffae5de5e799b95424ca2e4e7ca779264f72735a780689a308fcb97d91c4d906077c9ccefc7c129b0523f05bc8fbc20556673525de0cbd23f628e3b542add11ea32cf4a589ed0af1ac597870b6e28c636fea718de4e16cae5d8e0df6794272615eb929d5641e3c02e76fbdf8591583165c15f13b2e4cade8a68456809c94db4cdd51853348a30c41dc17b741e4a27527a0924cc45cdd24ab1bbed80cf9ab5be6bb5b2ccd453ac049c769efdbb3660cf6076e8ee26551cb08957ddfb8b24bff52aa06651306720cc041480d6ad55c1869c1eeeaa3722e2f629ef2613b5f34ea3df76f63a32301def241576b3a56a97d03960fe77cbf855e7329c9aebb2528fae405552bfd3a99ea336649e9b1c24dd0ccaf72e70774eb80f9181908e886447c4df708aa1bf79cd7c2102d9b311d5cd97c79040c48adb47958a6759dd33d7e9101cd9e79e3eae1251480f4182280a6ed3f6c758961d95824b9538c453c6e69170b4974012c448072e441d728c2016926bf3b8da59403793117e59bde7e7a0c4ac4d3b4d729ae8e483ef5865dfe463e05e1703731b1e1306b038835c9c7b9449f0f62f4e0d73b9ba17e53f72b26f31e2e20891981229bc7cbe97299e27bb0573566aeafeedc56eaf5297de846e0cd3f0f25de8e908a9ae05046c15a214f0e782bd9a80ab10f21473bae90072eb2a83bc7a5bf8f295b92dc69c3a4e13bbd3a346ee7d84bf20871d805307a938b25c196fb6b21146b4d2118db930dc3e5477c41f64aa23926297b45f8df8957a2de9b8736db34954767230db5fad781ca886f8a6a37a1e3ea069c223158649682683dfb21bc53540205d8b651c626a0a8f0f2ee0753e941a496e7fe8c9e134462b555563186e37e1ab805336a3d58887efd51fee635c26b96a05432e7223591e25742f37890b65cad632c451319a90784d0e82220aff47af772ffe824cb20edd10227a8e328a5d68c64387d6f9c22412e74f06f746e9002cdc342a38678fb5709e1e5d38dcc74be8314944e3c48d75744cf48abdd50e5a49599556c056fe76b56b6e21efb9836cb56a860f39f07862eacfb3563e71547ddf220787b0b19a45431927f0c1602614d70918ebd507912e9a94d00385b8b4686e6392cd38e2809e586855626834efd91db5856afeefbea363f1d3780d32fe23c935b6184ba4015e81c45f025308ea333d6d9bed23578d82067c23bab7b7ce7d8e004652db151146d8a964b16bb2ecfaa860035046e899fd8c91a30b6e9a0ee27df2491baf9f98c085cbcedb1a5ff759cd7834a6a480ccddef0887826c5b1fe5cda9320a4c62472175e8df1a510f593427704cb33dff6b603b9ca549c9a3138f3729a04bc32eb8ecef3293409f6003647c352c7455253bfe7c582b6f96b24dacbdddc5fd56243fcc9418bb5b21632f2fba6608c3554ab676d6dcbc6b2acdf6d6a31a21be83adfb72ee240c03d530adb5e04c48a90505bcab188753619d6cb3a3648ffcb0094093e9651d7f873f6093806da2dbbc7c581ccc6fa429259fcadaa9c8118b6f764994cde2cfdda736729b1bf4e7d63356c7482da87a8e873a387990a7ad6e420423b52ff010e9ca1a88008c4a95f420675a6badb7172d6e31d2a04857485235731829db4dce676a18a18a84a445240c8ad72bb9faed97b73121e558055bd317b6127a45a5378de544251607ca14007df339f3dd43ffc22d4312d9158849771fca506276148561a2e7b1c3407853bb1be80459abf4527845d7adb2cce53daaff7c0a906df60bb4b1458a1a3ddb1b7144c88ceaffe95bd1e219dd4aaa529e1797ffc319b60b3cf6d8ab86e8c2f28ae67ff451dcd93295f5be6f8074b6d6f9cfa409b35feb67f90b62e2d112b763e4188a628255004be2015730449b260d974a1254d0def428e9e63454da9a1f86e09ec3bc0b3fc9c432f3c73c18d2173ad8952e0ee07ad8b246b43867fd3aa56e5bf94a5e16331e8456183efd26671f38160ea32b2b6cf56ed7c7e2c3b08f018b9b7ef86ad9e7e489237488a4229e66f507965fdda5f46a4f6750658916257f9453b35f60cfa1e920aeb709c12e9b168607467c96fa97fc481bfc79665d9176402531307d5f4e122a2ba6ddf45464b3857fee32b8ca3123e04a63c475f590729af481800565bf17e5974b91bbe577f66917f3a85234c163e2efa6e0d1079d8da03e0872916be8a7ccab93b12bcdecc8937e156c91d2875cbc8d512b329781438598baff6d0ff99733941af75fadb616305022dcbd58be41c504ea87def07f71e2f9eb806b3e35e95f4ecbc187c54659244850f962e71193f29ff72f1461852b007370ae06b8369d24d27887b592e4a526cba6b54c534a7fb74e795d3c435f45c46345c78d6f83546e90ffbdcccb74a50b640678c0ecffc4b60e55ea4a5263a619a0ea297fb61c144ee491fe08e6a146707e4735985fa6467ca5aa428013787bd3477f6796751735bf5273fd3fee22bdeb2221e64c0df7fc2f4be4c6b15c28e34eee8d3070831afeadddb838096817038679321cede8bf1fcc13edb7ff22b5da40378c7c25fecb93dfdf3d0b6498508677b1ecc1e03680b020c33b9564fcf9a4dec86af0457601c9603b701b3aee22d223006b5826c8b0470110515e78f652b11d360773fb658dd56599d877ff50c8724e29a5739c13b5a985f16a026fd3239404327e99b0fbd7ad6e3649d68a8e5ae04766fbc70b4831e7721588365adc4b95103ff03cc96e2094dabbea9ccd2b83f9dccc8714cb0c100ad7fa3d995c3005e8ef70d25a0e23e78117a94b812d788818bddf105dddcf1877122c0b88026efd0f277b399ced2bd6adfc0084038040ca6e156c8365f640b78155d848b35111cee79c73ee5779444c768e88f0bd26d258f6696b3aafacc45c6503ffe289aa40663d56fad7f5189949d4e7356fa9d3db77b92f8c2c6721fb3a67c9455dec902e13e3c86f94719dbe527197fc1f5ca7166d5628da024e950d7215935c40af05ac277c5d3947af1813942fce5ce98a84586447d9a9c20fc9103eae9d29d13135da7a23b29003d2d7b9c825d48340ad5fcc00620d0e1d329da87dd839e66ab5c87f11159ed9c62cc07d2e1de51160df99ff183d2559288bf35bd826f1f89c092a1bc5c19700a96bf51b03ea1454f98bc5d503c2b59745006d6ad8f4c24aef772eb814566bc523edbbd9ca488d54e4520e600e5f1469b835049297ce590b753de99d8cef675a4b66e1ce136a92396e950627f6aebcf1f3a35aa6a8a5f8a8bb91fe991538aacb650846ee7390a31e6cb4adafb4bd611e6d007d32f6fad857949c7713a7f05040a7373c703b3a1f74cefe68853d3303560d52dd7a4307206134b22a1993274948d3185dec2711be5c60c8b371440ac1f9f39013365d59acb0bf377f23f662271a2cff86c070abb916006d5f7207d540bbdba843e6e056286d7382faa61fb09653c7ab1055c0921692e9bab9720b55b4131f908bd7821156e0cd92eb989f139d0d928665628bacdc7f2ddb5f65143a3df12aad1c1280fb0de6752b97f8f20b56ed9083fee924894c214a811882804c3dbdaa0ccd4853a25ab23db96271eee529744174d958dcaf25a478d519988f05978afe610cb309debd6b40b2cbfe08718a68c98c8247daa7f845fd5d63c1c754164515f7c952fda238dd7bcccf8bb0f7fa0601d6a6af3a0b3095568545cc05ea680068ef925dcf5bd356e8349af5a1537b69f621602ce6e3a354aa94908dfa0eb7ee0cf9be41c9f4840372728e9425eb8dcd63fa18611456bad6474335c977ed7aaee97f3e1f99ef22f1b5a1071d3e4b529ca7a8a2e05e5c50e6409495b92028583b0c887b37a7bb35fb746af7cdbd100f2f798eb899431f62e85904bdbbda0c9014c09e3094f13f3cbf42c015401068d208bd13da34fc98d04b7cf6a98bb1bdbf08726dadb23f7ff09a13a9b91134bfbcdf32095f1a09fbeff9b092fa9bab53bab960f7a6a65a71327f40a09555709f923ec98202e3a600d0d8642b42359c6e322249f53221cafd3b61ca210153f4081cdbce521d257c11cca9c7036865f6b7360f4bc781c613af988adfe700d1e0c7e9a2f0a1a0d8961884c95c877efbe737d1c169c7785df8ceda182313b61e0b0755fab126f95bfacceaac1b69bc041b86039fd030ad93b1c2b5bbc9750613ac490ceadbc359166f03ba870bc473d8a89c75406c3547ca638dca5d04e365ac512e855defc7e073276a7fd606b5b1e9e500dccd6d27bdf57fb3fd8baf751c634f112e42259bba98f6e09796d6bea5ebb7e8c14a66f6ee883e06394de7ca42023c1f8543c78b051efbd8de0c1b88ad3be0c666ac23469b14c93ca2f9a0eca1f2b75f41a1a3db0b954f861705db8928ddd7f1fcf7c50fc0ac14fd3a842892b0cb7a35d75d6d77b706efff967c737738918eac27d343cfec57a98f609bd06450657197bd403a934295db0e5edfc0670c94c52f5ad172fed667a2bee10c841cdc86fdfede46da743efe2040fb23c940fdeb9b0bf17a22462fa23296738ce18dae5a3ee6a5ca43b8ebf50dd6334ce1b0b1fbf2cd394c8823847010bb1b5da08e0c363fdb45c3c572197d70c0c3d422a2102914c46dc1f8ef625a400befc6acf2fe153eb081092c5085648ae9447fb5c95235879f2d4b72d119658ab50faee463d26274a3005c753dd8839da418e8dc1077bf85654dd104502d9f5888cc250d440f08d0129a5831aaea34c824d27f26033c4e79fded9447ed7caf27a925ba70dff6928cc4b667f53ccac59c0f72bbd251e302a62fdc216c2cac084125830323ffae140f4ad00f51e7327efdeb34b44ab960976f9a552bebac5cda78ee033ee86a7bfdd76e9cfda4b940ff4c96dfa3b3ae912c4752f483f56cf32829d82ef578d387d5bd8a445c70d218bc0eeb66e591b8f1d73a50faf69e70c0aafe5315d7185e95f3703b607a608ac50497899408727c7c6fb7c8549ebe3d07b99ae01f0f808c2a2eb3c1719f7255cdab17eaf8c3f6a9345ad5597d5c53a4ed085947acd8ed7315b4b73de85cc4c796dfc61577cd649699350258cb1c70d90469ed3e7911604714ba22d25d68af915cf1d1d08ca96890ed75d70aec691ee39d74b7984aeb010105cec134685e657e2d37ee7f3db7e2c93f37ee00ee2de84914bc5c6f105941b948dbd30600fc4728c14c7ccbf51c6b464bc1eb68270e1a4e23ea0e2afed72da80e31776218fd8d989c8a30cd5c962f27431c628c909821a08e06dd3c39609d43171f15d1d44e2429144f1d8a1d74b0ea3a4b18810c0397492ae0ce79be31de51f6413f0000cc71bf0387eb233eb4c3389321a792cae8ce1a17ddca4e27a3d4b7292a0fe96e04d87299e2f59d4da9557beae4ede4cd5a834b3c4a6d696541793abf3814dcb148939ccea0b93a0f354e891175eb8a89293fca193413f2d246ab60c92ff34121c842bde89bc0f68dd22a315c096f227fc74d9c4def1a78f8a7f59e2cc46bb9b0ec2a5d90fc7e1f687feae429b4876c49280f588bc7bcddc1c0c56f3e055063d9d64cb7e5e42e089e59b6740e8846343e100d056a5965e029b2d78387371aba82ff58a466e110d54655cd00c952fc3e6276131c842d7ead3fd19525b6ec3258cb463103cbae5af55ace8269d44aaadb1a9d8a11f996a60bbdc7c560ae136fd529a6d0b296b3418f8665aaa7e0eb2608f6672c2bcffc82e99d7deb452d31a965856d1aa08027e62b55e005a3667d02a12f956d7312ac8da06d4cc8a0f5bcbd6f911de297fb19823cdec25f5f6fd17ace52b8765fa85d5485cd25c3aa5d3ae4ab693789794c4de92f74e2aa9ee4f6e35ec485d2ce1fb7920d0e7c88f33f5784defc13bde4fbf30c861cd644f506b8443d4b9a8eaebbb0168c353f7b6e8953062fa2310a3fc9f2b261293c5d90a7461d5e35c18c3fa9fdffa35d74c969192949f9ff3520a1783a875a361580da0144d5d3a608c40e8fe90de2f6db4def88e0ca958135825fc435c847ad98d62e44006c1f3436bbba730ebcef902770028b0aaf77f6970c14f34fd77e13eb1fb953c1be47d26d85a686142222943cbda605291e9f64e7195f2786012b05335e71e4bcdf027a2bffc193bf01950134ff58a3daba58a7eab1b1ed599f26902f60fbc7cbca368eb0eb37c3d69d3b20b932038aa628c945949a98c350b8c366224967a9a2af352e9dc9d67694f2c5e99ff6052047709cadd2fc289410320818092eeea0eef5ffd6cd75a7152c1628a9270521977c5d176457b4de8e20414b1379d666ed50863e8c30a60cf8640f7afca06a4a87cf8365792fce8909740eb368f152bc5e5fb1eb4415637a99774e0410a9d101dd4d941bfac075977b35e13e0c075bc3aab62083faa9a3cc0b75f31109517722e38bea90f7141679b4882d011817b2570c2ca439bbd5d00e25c217608f066ad8db892cdd69c5c2b2e6c3708dc37a48139b73235ce45382e47be5e4bec1458e82f5f0923599361971d68073e74c03e9840bab9652a0224fabb773932de68cc3de074c278a9701769477dd1e50e9e4a4e7673b4d199846831bb44b19fbe310e9703384bdaa2935d1245f059ab7f9dc396d6c7002830b7f295358705fbf41881def6ed00620b6929c314647ec37bb646db91e7fd23202ce0111b8281e1b65bc9d68b53f129060e4571df00c3090c100a4b3fbdd0294bc22cc534ef3b41c4ddd18676be46ca15a152125f255d3cdecaa2fcbd0c4551ed697ad698184d2c1f44b82d097d8d6130f8ef60a290a2693eee242b317ea8884cd7827d50111a97f49dc45cd6a2ebd0c8ba533e604204bba2cd7509d846549f9d9f62f995b6c67ef74f5347fbda94dca357f631a081f2100b18bfea450eab0b33412870402593d6564c445af5c1501bb5829e529495ac4c35b74528a4b4d01bd77098d4efb9ddd8ffd0b25cdf93de5abcac0988baede8471d7b79af4e2739b504ec6246993d9976f65a108c60d6c6a4ed772263529b9f8df6fd7b05f004a7be27d5635f90bf615bf05965e2ff07da647f57467d7c19cc5d13e58e826e0889755e8978859382f7be79a8dbcdfe2ca35312c8b904c9d6316810b5ce05d48af27552e7ac44c5d73651c5cac976cfc8f4f2ec9f4d9c419a27d2a3204cb89f062a33510b66806379eaf53b10cfea4e851fe1358bff8bf7f3ee59684c296190cb8b49c64a6ff7d699819051027b0c1e47c43a761ae533404d8dcd1cb1e8e87889cc23a4099ccd491ca5902710bc77facc80134ff23aed8571d2e9e92a1aabadab842b5a653ccba7736d898becc85f2a36d8f2bb6f970aa02725a54885ba56da9ff7d6eead5529e0da3e33443e633f49b33726e117c0d1e767a891386a4fceae0efeab2b90725da9990c609eb8f6d83228aaaee52e42a0e7b417eb6252ef7979d779c3e91e4e1569a3a1c8252c2d115aaa68ad2a9d33aaf980b59bb05e6182704ef0c8cee07c5ffc1cbec481ff698bdffb746593c322674009fd47340d30bb7fd0e2de8718adb178fb9e0567a3297dcb8a2c59215b42dcfd651f4a380c3a7842e85e23055732c9c7335698c99159e5357c651efa80dbaaea206b82ed0e023ea185e5b858aa8dec7840e619813c9e945cd9e300bbf5988a99e0d5efbb5f8b9edbf1b3428d0a270ac54ecebbff33584774f9e320d67a0c8921c49f0eef151ab1ffeda5d439ede707129795f7b8e133cb82073a2bf1513a311c6c9ea88c15dba8b172c645e1d18c1e5a7c47e96f53d4443a6994b5f81c6eba383f02433c2bd7673658798149cd32e77b77757e4bc92189d7503674af93d35d7cf40676a398145954096be91e79bf541b7c203fb33e127b85815e27fed956513e4ee5a2fa6071766e912a033c34a301cd281afc2154249e818e3b222cb79686558fb7003e94daf81360a5b2b9f5b1da66b626804906f52de049096fb76038a532c38a3a430a59a22ee5e26ec10ff1054319462572eb84cc7a810aa09e73d187f9a764ffe9caeaaa425522617380f9e833420fd619fd0a05cbf74913d24b03f43c78c4d1b5229e91fc35a468e7b94a9cdef6f5300ae30dba442c6fd2e2b4d4fce811f10431634fd7a4b196c10969db0bc2f362224001aa6727e2b9df756278cf195106c505255be3728e30c6ad39b0a44a42bdad08fd598eaa2cb7c267a4f10beb35b433a85c6cfa45837cb9764870d61f9a264c09044ba3d307772443c3dc30aea7f2c70ce5adf7eec0d17e6eb71c904e100f057c8a2fdf7c8a0881b036c575fc19a8323c382b605b9e71d337df49dea3208107a1c6ff805ffa410328c2547ae54df3fc9d3bba625e4f45b6d7162f79628b0f038fae33e50d086d175ac1f40ae39bbf63f198641d1c7349bc1f8abddca0f43e9be212af86bdfa8f797d0673c5f3b72e82a267e1f6b54fd65f1a27c5d6287efb832419a480b7b065d519b102b6632980a0638bd7c78819dd17d43d3854a6a7c59d994eff0ca514563906657e3e4c217e3be58a320c81a76fca505b9468d1bccca02325d873b853b0fb0a970a364b011dbb605c385b341883521993cc1112eac4b1f97134c281f3782c08e26f72005b1041bc3dad6c173f5b849fee527a9ae68fe0b97dc7453e2de7aca79622e2ee1603105bea1c9fb2158c1e4853eee03711f0cbf6a0c390829b06ef67937cba60514cdca81ba2074d10defac391418ef0e4bca1f1eaaacd9405c01373021d01e79245014f3d198e8bdab6e421d9db926cb4a77ca4018cece6624d21d72184fe41f3348ebdbbf0e6d5b4eeb0db34d4290a63d726f99da77a8b641f65a0c9981513a2b274c138fff5ac8610ecab108c6140c49e1a35a8cfd763abc6d6edba1eced957c7227d15d392dcf8553fe344c60182ae96c396cff71d348cf66f21d849582e673200f7cd8d6e437d427bf43f17ea15b353fb089600d0ad4d417037d8fdc5ff70dda6904f6ab01a0691128526d3bce5495ccb270ee6e69a2dcccb2bf48395e340b6b85510ea0077acb2ad19dd3ae246ffe3df844c019911d3ae35e87a71db3aa04125e717036db0e8529bc3720af07af9e52340c4c2a5aa6d3f2ddfc07130fe45ee5eb99544f36b775279a64764a621bc128fac9b25820778758d3d1c7c5b1516e83b63d72b7139afad0d27b2c1ebbd9f4fd4da6c8e066334cfd458bbbff59b0e914f8fd5626f0feb44ce5819e5f7e353695ead720914ff6e598e1d6794ea3b9daaf46188e38aebe9ad13466f7dfb8ea10248152e07fef1b1edce3e164d611c2064c1a3e5172880bae718870e74e1fd10008453c01087f741c6fccc65dd207bb85b045aa7f8a4970941be773339b98d5615bfd770f9e8c4a79312e0204e55f23530f878b79e2559834c312bf5b7ba35043ef2fa1407d2c1597ba03917b2de13733f33d9094f16336ac5273a053e7fa59eadda4ea391a0db6c96f22cc3c2b87c2233d7d50593fa95ec91e872a88e0de98fd1c017f6b7b0f72bba404a82b4dc912315dfd633b2ba94ae24a42ae8766f9d1c6d9fb847cbdafe178c3757887a8bdf6c566734ee874fb3544629003b9d2411d1ccaca67c0df9e498505579594bb802c0fdba29a5b00425f95e885b6994d5eadb4ce0e6b569d52b650777e329a371a6d8de4278362aa268a6d33baa83d1d8e63e701d6b96a50c847cbd832a6ecc282a57e3a82659914fb7f5d217c6f6ea7f2604980aaa7b6a7bedbed9c67d2e89d19f4fe02477a62a30daea2e9f59bfa4fd5ce3f97b4b6c766c0e88953b01386949fbdb75c0e9e4bc0c6b511a9508b05b8365b445901aea00fe75b3cf92bf38aab57b218b64363833564c5f04305407291e5712abdda884bb876a6d15d67b47e9098aabbd17f90a208464c85145f32b3f4349249efd9bd152763dccae049d5cf1c087012cf76835ea51e7752ea03dccf5da5ced1b91e74946c4c0c993f671b5ff609c995dec37f42a032cba0b1678acb4591e1b01951ca6c8b95b27237a566e56d5784a4c0d869432000ce408b744dfe83ed42ec7c1d1587e7d7a1c471297a42b50d6046535bce8661de8fa8ff09e81d0c786227b0fb10b49bd263471f67e0cd8e72cc63271b37c03ade8dd528b97d56d14795ab5f399fad0a234dd48af530d7fbb802c6249c9963446eb93fe1f50a5c01184247a13c835ca94ae7e1b6680c36d1acc2cb57e0b221163d7897543f50c69690b6237efa4dbb9903756ee19075012d37abc31bb853a044632ee19c862f3b9b191b152d5ad548e70c047db963f87514d24c4533b3960a74152cb114d2af14f5b6c01ab31ec3f2f48080830a6be9aefe2399293eda3e626fc33f87da587a01762becb23e68511050875eab9e194c58d743ee8d8f29649fac29fd9add95b48b340601df1efe9eb53e8ad42c9aaead05e60228d5926561eb4b91f06182b3eeedbdd4f038e615eb352c08b65192b926565fceed80987e91f23e3d6ea1c072b4619b2def23296579459b7b879935ba7a72bd42232d15a21a7e12f2f657bb2e72e5a9e18f73ded3b939c3a04ea4a29f9064cedd88d3ff173aa59bf8085f344bd89ca86891a480c53647bb2f6db23e319950e8ee61a9118c625838b84fd25c3c9d8e9c8a7aabd7e7ad91985f1361c8e01de0eac55f19240b695ebd20458609a0941e6975aa11e5fbf27ec86141aac6b7e35c2bddc8af5f04450e1638c74fedb18c957d0f7455cc7336e99b717eabbe182ae7a52376dfed91dfc6eb90d84f9eebe79f0a8a8bf1aec7a445dfe1f78a85aca94e719d14237d4fccf5746a5652d9f844526606755ad28f1da1840fb965cba99f3c4e15fcaa6bf0c5df0c651df6e6110b0bfc785c5cc7f7462bb5b8ffeddea37eb2c012b69f29b0ae9407a93482a3c43959a36cc5d618d0f1b8785cf70e9cc90aad327fe2ca1677671803e8f8cb1aa3d523cceb70fea86b40dc1b9c700d118e48032038b655ae3bfb1ebd08237de1e175991ecf5aba9bf4ac069e586c4e81319c2fb3a97e27542061934387e3c8a53e4f5bfc83bf7edd5d53aaaca81005932245ba309af13e15a23872b7f7c78549a4ccf18bb569ce86f359c1b43bbda1c781270a1ed0f7fb85ade5a4972d8b7c7fe2c9e7fd30174c4cc70d09e800cc7efef0ab844fc13169d0fb0f00acf73b7e4463e3f390af9e6e7b41d43fad0a171df55d54a5119ac91e8a11faff5931f3571a0c85a21b0e74405674fe9690b24e78c2e2d2d43c2f196ca800d78f1c2e287a752700df4a7442b7ddf76c1f3d406af21a086ed787ad8c9fbadacefc6ec3bac85ff2d679fae5d8d056bd193f09cc9b2c6344b37efce470805e086c20c3f547cbf9a0e18b2b6e60e7d27ad0d76e34c172950708f22f621cd9f15320336df4ad5549de82ebe85f0745294641d4adaca2ebaf0488bbf1b8d74130a11289041d777d8291605334613443cbeccd64fc29e43c753304ddd88ffb4036d4a32a70e8342c95389a10f0015c1e37044cfdb46932b4ed34a7cf6ae8cc780a761bb962a1749b5908852b32ced67defd597b555538e7c2d128556cf7fe70ad87016a47d88640435fbecf4bd2d69c67573c2d253fddfd8c86acbd1471d32932fa2585e5a5999298cb3613cd9f634f0022f393ab6b89a1309109dafd358689ec19a98b094fad669ce36398e287255cdb023b74174418abd029a82cd9d46eb0c7ffded5d9d28923527b1e4c81d50f1dede8875e2240fa5d82d73e91d06bbceb25efef8663ffede048d9e078317a3f5aaa2e67ed8daf69ebba59846185d130cf9eeddedeb0ed475414abe42616eacb2e149d2e2f8c94c2c908d0afd22dba302d8d07099588738e24b3ffb45b679bce6153b7befb9d22d689d5afbf70b3beb2016b3f58cffc89befa6fb99801e90ae51b8cafbd55640395ce43706854e54a0f3ca945d0c363f90c59a04bf587377257da6c526b00a7ed9712e2f544946a6f12173ec5f82ccad034062e24db8bbf37338647f42a462e4faeb036cb3f5953bf35646d4546e5db3d62bac8bbe0e28336df7bb8438d5f1a2f489b0f60a36951f56141489c9cc50f681bb1714323d8c63a8d6face81b4df829e7ebc299c6b11cf0bc4d6de47595a96980f72c3292983d0f0358ab85372ff376477860d1c493e9e183a45c62e39e77515f6f08c54c1f8d2222656061bfae67bc391f344dd7d31e29154477862bc9fceaee3b9ecd4ac5b4e61020059a78e6a81ba134305559511212e68d1e82c99f2312eb7e4f374775b357d88a165429b712e67cd6a7ba220de42c7cbc1eed5530348347d34c5415b34a77abde1d2f1406b5416d5d2bc5a1fa6e59ac7bbd32071943719675923a3a502072d911a248b93d9b9a56644514c01d167eac65f494c9dd1b5bc70f45e2ecfc1adc51f573a9bd6973c0b14e14c13de1724f94039e085030442c4d5fbcd0ee6655fa6f8438f326841b81aca2e4cc70c4c9695c924a2dae315670e613a4c01df522dc50934a057f80b142a04ca5c3b12e7fc511c032b1ad99eb2ff8a3bac011170a3614bbfdc451277fe3e3a26c120f746ff0274070f44d9dc8016351a5cf7bc2bcd825fe70402ecc6127f58ca900cd7225f64281854a178f52e42e0b58ffa71ca765a7a1e25ecc7c5d750b4c45d6ebef4cc3495563106e5602b548ff798b46682dd750e1f72f4a8fc745045c76bf5b4bd05e1a8f5593cd702e855763c0fa70377926fc14a90f2da1a0b169e189ed339e24c326253d2a00e8ca51cd8bc79767d577cd080d6d341573f020304538b52eeb826e0c89c782d2d23fa45e53375e703c767135ca9a4666bfe57591e5fa6b9cf69e6efb6ecbf8cf6e4d20ddd4abbe424bdd91ff070164bca0ade9705f3f759ba79502f26ad388a00b0da891565b97fed2f0b552e7ca753eb0172accf279bfd711554c6b57a5ffc6b04280300895e50659777ddb991f4a0df5953f27c0c2c49b19a1a06e03935b580d396b9f2ce7631b1102af0f6e7973a936fc4770525f9acca7c47bd106dd0877b51a1356dfb930176aeff119d7990f1e849507675d8b99c5800582bfa385b0cbf8c8a8e85c76fe90660f4187745050d3c21fecc9a68822e1501b74e7620310b1eca5724716b6975d25bdab9d7ff0c1f0c41df4ee8f577e70d1e19f00a552889df5ae51564a8271995ebb7b388be171d9162040d4bf2ce31b1c9d2dd989ecf5157a993720b7f037c81b2f0beb5e884bc0a2ef3e2da5bb9c0271ad216c45fc2d31239afd66c6c094c7dc6f116036a22e9ba757a1459cab8960b82cfdd44d463c7a9d3254e563bef39ad08b7acfa49611163530309562c280692d78d746544cf94ef05c5c028e3da7c4f4ff73310a310bb86ad54fcbd3c33d58a9e03c9bd364d234cd8eab5c721decee544e96734941f2df1b14b56f2132ee64eb6ba34e8b642c96567682f0fd1f90e4d6b5739eabb916b19cf9237beee8a0ac8c1a0b1efe68cbc0afaab1ebf3d2c847766e39e5492f8829722c7d2014486da3bfcd7ca63bf92299f95ea133a0ade3e32aa38a05f6dd2eda6e50c043be7289a4ecec878eda099182523426f1254120f0b9bc145c68cef1c0485600c2fbb6b2f0fdf1a416d5b7a030f21d37bbbfdec5a86fb505a6e93997d492c35eed4cdce859401bb8cad82a14a278c4bbde70f90f1566e4a068865a91feb5fe6dc242ad5b178523b62867845dcc4573dcfc376173fd011f5697fc1f7083671809bd19cb298d572899e36197902a9d6ba845596ff45625df53ae529e58c0777818953c829b0fbbbb859679763321d97d6fc8120869afba3ae12e019a28a74eaf7ed2b4d9440090769caa913f648816c0692f959c151caa873835db15760af93954c07c9ff60bae49ac6abc24d8a453e72881bde54a4980ce30fc64b28ab2ddbbe329c6aaf874ba04c3bdb0a142da69bc53c22a2b50095ac29e99cf1c8592ceff513842cd843701891a5926eae62a13c6eca65547f436c67a0a68da897f3ad06aac69b3995ce2f713d5ee70fb62862bf83f45cea8ed2704ca148679b595121a25433a168810e783e2b8c9a83741a03cd1d90338773d65cddbe9866267414a4a324a5dd1afcf070b7ead41f780c06e4330a339b5b4339ea2f8181b936a7f9251df2c748e0dbbc751a43c2d6203c667e062c4215b053f106628fa238be19179aa2d44fb5d461ca281ef9862d0288df5f4d91bb1f5157f5c7ccd9f095cb08076ad0502df439d7804de3b243b9577091ec883a0d95f7c282f313c30cd6316bb46b596b9fbc9de879e0af074fa5bda23ce291c98a365efc9ccab04e16ae2dd42201b00ebe40e3f9e83731dcbae6fad09d7d6f62178a3b09ead9dc9195b7bbb1fb8d8f2fd7c38c4f0e4f62b7fb8a35f623011c4abf599650c019df4ee40cd8187f7da4002182bdd18ba1b42533d991e11895647efb026aa557cfedf03f4080fd9e6e0bf0f0e0cb6b3ac480f341cd310ccbc69b6b059e376cce121e39b64ac6dd3c60991572d67f8a802c3b793537ea8e6639205fd58c6a14f9232dfbb2d8285d0b4b557232be84ef3b22188bc92a917e7498cb10d2b069213b3b2eb9460ac206aa79fd9febab5f86e4fac9e7d7271f283e2b7b958dc4af02738262afa74c9e424ea28db68a83a66428e27acfc1dfb5ecc6e1bf89c0be7946453624f6fa0920ec3b561a1639b89b3b5d589b61ad7001d6725cd3f3b1c08a70077d08c5d88b3a0fdd400588b2f6679e3a19578a85408d74e2061ca107305d2731d9b034a77fa9e7d7e07ae5c7e97c440f41606b0f99480ad4653296713cb0a3e9461d67c59b52391231a3d4970b416e4a8a4f4f3ea1f3c20bbaa21c3e6e345b54a9d5da9749c64aa139be162270ec734862f465bf051c38dcdc11d9f643f3e7d289b7536d3d79f35defd1e48f9894c7e2b6173284cceebc585611fcdb2835f5ddc1a62b50bd638607da36069d3d9f7a0bb08a91cd84556e6d1b526a4b6c7300d063c579d6a801d5ba7fd1deec69a81e2694b965c7ee506274a8c76ec03a1532573f2573c041819c5a8ed2a667f315522383886b42e04a105b22e8f1d7c65512ba44aec91d7a6ee59ffe56fc595eb988a9a14969f6d42d78be9c134d6faf317cce95acfd8a01f79ac1917f57df8dffff8d1004da385d88f71045ae553475503e0d18dc782ad37d5648eb3679a54c928bf0856bb27dca1f1abbe915394a820dc1460b363d46e5b989c4f8ce1604f8c8abd465be3d74bfe354cde5efef30e62e87cfc99cac6c621f64e84d1ad1cb61a8a1d991ade2370047001feb84e0a5eeac84e1c1092d697adb7232bdce85bd4133dd1dc095fe4819e27a136e2990e75ccaa8defe95101b816a06d5fea79686da75f953e511f8af9d41e80932f481ac1aa4b6ea515eb7f1be2d64056f4a1543681b3ffac5379514396f3c8941aa2273e54ba7d1f0e0d714d2b64ca4ee21f653df389f582749ed475bce8a8f70f11e6de59dbf160e06767cafb97caf23c2b4bf00a172c6c111af09779d30f98a1be2f716256e54b5751d37ca6b0b36510bf4d8ddbba4dc20ec4f9d95e00b7ef3ee5b98142425090a52a1e5fca0aa4fe8adebc035c18e8fa4a512390d6fc05dbdec841947528d4b909467f7f3cfdfefbee80ca14e72001255188c8e68537f751bb25c4e8e7ad67bb9a1ec4215d7bdd84615a39381a75f76f6982778e858a70da177d65b523cc77dd6ea6f76b9150d6a47baf4232e8a620fdc492bb97e1e7b8a9ac47751b1719c2f82cd5223c7bff563fbbf55095456528d9028bea249b3dba7a86f598b022db2492bb2317585d5de13a7f2836476f07ec8e37ebe905d3eba4a944019fb1af7495c03e26bc9860b420cfb9c9608f2ec523e1a2bb063a0ae80acd245e500392d5ff99127af021a853197011c87f30f3fbc719c8aabd119838cd8e109bc54fd1707d59bca023d95ee5116c639dc08baa569a30f6818a66256412532fbcca018d38aa29b310d69f9c163472dba80ac36d2d5dd207bf200cc936263b2387df242d9a10df3eed5978a86d3f0c644da2f8395a31a228241d38055b124e372be833e7e6c934ee37da8e3fe463c9915274ef22616ed269331f1dad09ae14eb772ea32ca1f2111b0061bde6aff97fea0bef673d01e2431e5361d5e74badcbe32703ce0f6f8b00fbcc1b0da5c8329380be2b8e9e659916b7427349a13e2292327208f67b54eabab1f6e9b1355ac90936f76531c89ad479b046458972b0f89d671159cd8788f0f2a4af8261223394c630b1fd69cf7d997fcebbcac9d3b56e2608b65979d00c0c3391dd415300cc3faa84137077a09b0d7ccbbaa10f016098b48afe2396f5e42c12b1af36824fc4bd2bec5589b930f6ce7afe0c291a618506f55933635a15125d75eda59c4f43ac8cd78c7cc327cf0bf34978a9f6f56b5fd9cbc6013f7996cf81431571b74411e0836a48f603b9e2cdad74f7e48dc37cf37c92db8bdbc3e51d2d2b896ff4f547183f89c26bff822869659c336bdf8346e2de685377b4b767f47adf190e726446546efc50ace1e9a0afff3d272c5211589d4d5a094d1d664299163b824ed19d6f485c6284d112197ab168a9f51681fe0deaec9635f11d65d9058e6170bbe721826003b520cae020afa317812d7178916b2fa6883893a169e53c0b3683e1f9f32228fb7fdeaf6317c0cdb125cfd0fd7d03a031acb37a18cd030e65f353530b69345d2090f1a2c279fc07684fada39e3ba86cf11f7a5031b6f9675c4426d215eb02b42f258e3ba4c624f091fb748516c4de1dc626b71e3c33444b142acb1d2125d92c182c8c8fd5b0ff6d7108cb5735cc273896540a1a1b420ef3b4962657415b936febcaf4a1379e39c8a1d75ee07fa32bea4e4b137416ce7d8d514984e577aff6a181c39e547d8cb0d43b7e86d74c10c3e51c81088a4005aff889ab134e22996a1ba55fb091ea2c9a98e58a032b1d91f939e0fb7fc7cd7d407b26ae47d54c07c9a66fa6965aa0c66c86e9d4d15a48525f5cebdb031cd6112da4cf1aeaff214594f5c654b647e95036b7816c78d05132310badc75914e5ef589e0d3fe57ce1122f65701d8c4d2799a742ed717fc0abba98440523cbd55a26e4d3511bf2d755500a79172eaf7a7bbc44ad9a81a7ebf411259022fc98d2fa20975a2ec9db013591a9029380f0996c2caf6c24706850fcc6672feb3db7c25324e89ff1ed5066c69bd009e684ebe5f6b1251db17884372ee12d4c79e84b0d18a052e649f1482ec829b5ec0baf13ccc9c4f33d7a7b7add9a9757f012a5073dfdb8527ba68bf170592d3bd737050484f825f24b8b9aab92f7102e9e841076292aeca1e408467d360a3ac9f96e357add07a844fc17c9ee4694adaa9c65c3b7bd89b54889c50988fe97d04d88f20ab09699feeb39c01fb8c83a82854ec7983c701f5a2f08d27fa02cca3273225cd764bee92da67d4fc0a149500aa1f83277aa34d374ae8ad01a3586feee3e6a2711111342b5fa6f95e4bf656211e63a0513e7fa7d72b70fed1d42373b4f5064ebf1e67e479f461ab3a216715560a0485f0ba4ce83e4de9ee3260d6e02fc4403ed0a6c78b99ac4f603b067d8b91402b845c87a25f3b13bf39dcc5ca64fffffc568471b8f43edbf10bf37eab8a6da8d1c333108c01559663f70b920b9903591ec57b9b534a52646353e658fd1f1e687a31d769e0cd439b66e7150817d491c61793efa6fc96aab43fabee3308d032efe90f5414ec5f0b65edd02d692259ea07c9776258050e6ad93cc7c2e28081832f356c23481eda03eb7cbb46c9d9ba33c6d3ed83f8df6e745d95420d7c6361da7a41bdb2a218afd6c5c0aa07829d2966c62073182e605d5160e49a6f7ee9f715261c20d9993ab835c40ef2d489fbf26e733b4ddaefde39f41562c2a5ebada35b2459a2a24a2fa12ef37d5f889d11e3356707ae3eff1c8b527db722e93a3c97c1855968f6062213c7b7fadfb73c8e6cbb6f3382c6a3a35700fbb201fc70f89edbac299097672db8897394e8eda394fb91f1c5d26ca668a0f32dde545377cde35ed651bb04b133ba42bff29a08591478004f55aa83a42df2be5975b547f53f5837bb8f69d11381d94ade4a18d6136b6751503cfc8bcfc59e0ac0568952c1e060293e75d07101343a4506cb702b0f6dbb9144cfcf3d71a8a49b45a2c9f0d718a07ecd9bd83dcd139d570840a6c6b9bbf4f49cab5cc64099dbc86f25224c702675572f6af7bc8fd2a5e1c960e1774149a115908b4b300a9f32cb61c907be5d80e399b1584f07ac6c4517761c6490289cddb3b543bd3b4280a7f8f7caac864f310feca5480cc8eda4a6cfc24557477ff9a99811dfdfcb7069ed167e2aa87fa468a99f028dff84d52a67f8fb6d539aa5eb76667774e5ebc47bf5683f5f64f1734c4ae10120fe838f1cff20d8ef0c17b19b2e59b32cfb249dbeef9ac7a07fa1b553cbe73d5f28eeb52d1146b009516046e6b31da872579885ff3aab38e5c6e94d1d656361e1c2603d92f7471cafd71773da636f9ef7913f6fefcc64aa088089dae91982dad47049ce1147a995a1582b5505de7a5e16dbeb60a9722319e7c44fd92ba3a75cb06e0193aa99006c94805295177c1dc81058d2568da606bfefd7d31f335a1282c444951ef2317c48361d384abe5f3c7e11f8df1882f3dd98780511bff830ae5a71b4e06c9ac19d95988638fefa72d966f28d9830c43aeeb5333c81b3ffa14a78f0bf46ef4a55e8b658d12d44aff8577cd9654c7203d5372ea07dab7f998af4c3876b6a807c91bc50ef01e137d2a532c57460ebe5ef32471e0fdf12cc38594d28053ac071f2406183c2923f6bdd8ca656664b40fe1eaee047413227508483b269a2d94b67ce4fdd53a7fe8b26bd508d4f13e303fc77b0e67ec75bc6e89a306868b3c863803bfc9c5762aa45934fc0efcb6f7b25ceeb79fece0cc9908cab571c9323c31350ee28b8df3420940017b8061b9f902dd5b8ba2c7c6b18ca3c18f5eee480337abd3069eeb9e21eefbf03b271da77986f7896e16a82c0bbe206ae86b5a34725b7e93be65c36c1465ca30a20e1a63b930086721129e33c6bd0c2e2c640b0a8fa0e12ded73e3e08d5739b11a76f1d9744b9c0391ed62ddf6e3cfa96b30d009c83e5f75de40af90bce04bc18389aca059133102860ccd717be602706593eb750a131a0561858003382d0d97eda82573c196324c16bc0bbd89821412d49f6251e9757a9d06bc3a3fe34f4d689ed3dc5f9812bbc10b255ee9ae35edafed07d978d72417daac66af1375c5d3982b8d0aba13e8ed974d2f52f70009d71186318461bd03e24d997f40f669230bf6c6a77440e76f5e495433b19e83619ca90373df624e40c2838104209719e47648db96836e3bbd155658eb0582ade18a69de9fa1f0b42af15b5d082f2a6e9f8df17d437ec8b257bccb73c183721bcc52602afc063bde58612f1e94d9bad6b0488fecc911ffcf6f995820e0d843970a0c46590423c1c9d6b8a22000f87a0f31eeb3502b85f2de30e5be3e782848a64d0c77ab6c281a8d42dbc1ee9ae1e1e370990923acfee4b2789ec6e1af8982f4df182ea9ecaa30b07d1995a62ad9a3e5e440ea2767f03907131bd2945cfeb2ae0ba2f2444ca054c7b8ddfab6336d27047c67244975be3915f19acfd3d25bcf29ba8f085f34974cc374932c9d28efbb61322559cbd7dbe4c832ce06fd254de502d087445a2b642465a1f408623b84c1c70247e99d587c2fd0d84d6d79621edc3c3b597eaa3aeec9b16363ce77fcfc11edd8edec5e1345e4153417700e530d354c096739a062901afb28754a6a5ad94ba82c244300d2dceb3a6462a791d295f374bff1067feecbbe6d7d30082c2c63d50d7407fb23580a71a838927c9c0cf1fc9b08d3e8d25c95788b129a5bdb27635bc22a62bcb13fbfb2fec7ef5763079200e024cd3d70f4e6c6e668ddd2f79be46d70e2aadfdb11eb75868a18816a4468625b94f2b6c320092a0599e20b0494dfa5190f854040da5c7fcfd11dcedee3a1d92e86f5a54b0d092bea80f72db4e3927cb60aa6f069e8dd18612558a6b84df90adcd57f13c183f50bd566a0821ebf0933a652555de573df979b702fbd9e595062924f59e3ff6edf7f6cc90d16a7cc19e1dbdb965d09871b909cf6068302796e8017c2ade91e78d4176f2679ddd4f6ac09bae309b7aa4d32dea281386e64f76fe4fa98a7e60b107826a6f568828a9ffefbd75d6718cb38a3ab09c00353b012d194edbc187d033f32e348f619167cb4ccfc5336f6aed9d966dcec93bd68587a20bfe7ed1f19785d37bc691f1818226ca9c294b2ee9c63c537d2e431eb133ad6e8f6ae2521a7131e5e65b3a72ad2528cb949162e19ef040d76f2463fe543e7e81f166d1fa1e3ac7f86d55bc3f10c718d6a6ba8dd404fb9c64f46c5c58630f77d0e52d888df6e3e95b7a9d32bc21611de8bfe3a36907ea3deaea6a68cc8b170fa1eaec17d7275fcfe21f590a5cded083d3d24274b2b4937ee86851a934b7838a67f357f0990eae1b9647e3641e44797c5cca38a7d2deba2865b8513c0b0e81d6ff7f49bf436aba2a2dd8cea68ceccf426ae978666b810157b0b8e48ba1f60c2adca9bad0518d7cec5af7e8a76ced12632208c2d801ea7f2e1a16f4e295c161b823cdd2d18f172bc5855bdad93ccdcf3fb1d18cdacaec458797ff9cf0f895d368e6da8c03615aa395342044f1dcfb8dd6a4a588bf3beb92c0c70969fa1b43f4113d31e3f51972072eac808da50f4a89e6333060819721e0b61a04e103ae9bafabb6f64b4e0a76be62e636bd591a03076567463ae9f6c47ac2622fa56917116d12c1d83d4732eec253273ca2cfcd5f1ff8fe521a78bc081b5ea34f4c58a37ad71a89fd58a62ddf6349f5244fd5d9f8c5f0cb0cc8b7dd25b81ee0d0243403f43a5990b45477f44ea10dfe6d3860fbc7e6b06eb7e8c856e0ae970953b338800047344643b5345bd428e482478149d4b72f3bfff78d20ca6262cdffd5b1c95bb0baa6032cf41306bd1a620f323d2b202efc14d5913b4813f98e1825bbde1bbab81a836d101f11f3a7c2f6adf77a6bbb1724d4ea54e0bf6b41f50149be276144766b76174b6bc2a1138bf1da1e5e3de14cb32c0744c11e880881dcfca8a985672cacb92a914cc05145953223a47948dc48ff692029170619a7080cb2b0e359726f72bf7875614b80a90c394a684b993a353109369564bc6eb2410c818128a464b3e50c706ab961f0eb90cae19c3981f669b234630529dfea5bb2ff73fa3952d8e37c039a11e9e1ee4bfd32ecabd694e6390859d7a536b4a51eb78b8710426037c0f4c53a03c37d4c4e76495782507329c747412a704e72f64aa885ee06ae241479940420c893199070f43ee6323e7bd854efc5194f3ecb3d1f85187aadbde2ef60747a6d2264d2b877b54c2a3632295b8c728c9aabec54f80591e4bbb9128e6e6429497444fcf61db8566c4ca199726cfdd489f724be6fe8db889fea9305ee35a4b6e5e011e149a09c7dfb7981a5d27f6eef6f3c37a819ccb2c3684e0980713244a1ab00a3adaa5413d42bcfe4689bc307a016a11d6841574c1af56e0fa744403f8ea7d155806c16b1a72575498c353683629c8e69853a428efe593db53c45bf109065699a9ba43dadc4949291f578adcd6d41c85a521693fa8762f8cf9dd48ca748a4b0b1c7893839faafc3adc4308dc53081b4085d9838af6b8a5b8b13f60e57c6e7044025e20889e6993800e1d402df4f83ca505559dc9ab64992fd4f17a81a9ef22456afac08940f31a2f0f65eee49bb9882ef5f671fa1e7366a997297490ba65c993add9cf499c382086213b80bd01ad7690057fd6f289e5bfca11fdf76da4db5d2af12324b32abf02bd9ad9aa396414394e88e30e528f0945e39930f0e29664e61967735dd14930b85d2652b07f76774ea5f2f8205e0457bb3954b1520000cb4a7014a33ccafe090fef6d609b599c039619bee61f6a67150fba4e841fba66b2b650cac95de3b39a72f7fae69a65749ec7bd6d7cb4b4de2c0ebdc40d290f440b8d6b560461578106ed2ab6804c930aaa8e019ee704b1fff71898939837092f1b412862e516035c0df910da9a078379096c7bb571f7af6b3a10543442b5ba482a7eff76c9900e53499b36ed7ed638875e5e5a8e0e2ad773c46bc474a7903bb7584ccd6c9d48ccb61422efdde500f61273f18d2ab853a4efd7862043cb98c198e5d51853cdc4fb62b499fc4d68cb4efacac894e7508b5771090e60c43c2d59c54fbf4f974f472994628b4e5827e7af503503cb399791b210229a5dde3e5442bfeceaeacd5386be2253bcbdf4ddc2ba34184712331ab68357d86b9f91c3fd2cb1d18654ce46e8718a6c82e283f73af9c54225f1b2f59369e9fe6b4900259253bc8dadee13e81b9613e99c51ec559e2ea2f8281fd8d0cb6b05bd6b5796e9e3aabd21850ceffa373e21de96928e36fae26a817a38cda8fecbd1b888ea2fca68a23383241dc2b0977cc3c60db30a13a875c7a372c1cf3be6bd1efba4dfbb17a4ba5dce311ee00017383b431d33a0b43d763f37c5696303f751d2878d15bd795a74fac5e5cf10353007e66d0e35e8b2d16fa6e9d5ac82ad670f6e5aa48eac7cca85295fa5608ab8f695258e75206eddd0c872d3eed729a66ca826dd433aeed9fa23a664824c875b2e38a0a78edd64acdd39a1862a8d095a8814cd68533bc0df5c695b6bd4a07d503ccc312b2eb69dd95f85079cb3d206aa4972b79f6d05d05fb073591205085067993cba24aedb79ecea6ab2a95bd680ee116a7b15a4da3edbd5ce608578de06cfcd0ff641a05a374469ed525a410f2cd28a04774b414b71bd46cb1dfd78a10f8108f492ddebfe015880aa3664354b505dff472d7a064ab947d46431424b0a08025c0bdf20bfe48239759b100c07fc6da182110013b7f348d4e91405b2f1e1b7a08b7feb24ced88668b89221426c6d3f9ea2485d5b98a2221a907299c7f992323a94f6ccf37d6a6b98c4564d5d4bc1fd1bffe2d63947b5a36938cc1b9060527efa370d85ac5737aac31c3af145f4b1dea979d3c13f55f92cbb468f779af8120ad45a3e9aa2893a0f7fb94865b3adcff9027ec0f7e64d996bb7aea9cab32119a662d5659d669d45151e75d4b7ba638cf840bb5a8bc11a903890beb6f0dda123c5c922692472d05fbc92f840c44eb4260ecd5c33a2c7e2518994a9f86036f943a4df22dece348fdb7631d4fc7ff45360c701af38e927600d430f6c5dc38602869a65319a5995e2d4ec7967b2eba70356053d0e0e7655ad376404f9250ad31f1d4ab75b0144b8c629b3be2048dc817616f362b1ae30f42f7afb1ed1b1532a5180a633894c99b9bb303f1c74ded76759f0223730ff882f15c60babbba38965028787d67cab45425d05e52fcbd8cd48b749816203e6267409df447aa82c20b8f0ad7a6781e74ba4dda06b9412c97ddf26139fc8f93d12b4e2f2535e4451db75211619b13e8b77ac3571bae328aa05d6fc247711fd88a8ef717ab06d7629ee8569206d5eb54488613b4c64f42ddc2d44caa1884244bfbc0090bd28cf93c7badb5c35959be4119a1878465fda9a78162f655b00199554a53a88cf7ef97cb57662da1c3ad29b5ac0c306f0456e65ae4adb8c89b1a93bf7ea8da7923351582f1068bd4d1b3e4582321ff0d846841241f22402eebd6f475d743c858e3fec9cc0e3166b7608e6d7eb4f20be2c55d35b29c217f16104b3e3878e891f04239f3ae93fbd1a45ade8b2aee533500146fc7ce087dec0b272101618a5924718d27f7b771291971d589e6142fc70ad618b343df222065d8320929652f9509eccc41ad584e8fb3e10550dab2600b7581feb9fc86dd6b3587eed17b89870d7d4626cfe11c7e7f57afeaa9e9d7efb6786f9eef8cac5a6acca84262d7e7443285a944cf3e038d4cb0dc633b6c8ec21b946848ff9562cb6f0deb48d852b72a904d4128ba10a4b2133ded6435c2129f926ec69cf79b08d7f2a0b5795798efda26687f800fa1db0745c1f5b29307d544cc45b753233a09ce7f5d5f93e3a9458f76ea16f0171709b46e7026c9ee6d7efdc2f8eb0f4147fdcd9db895caa377bd4e08202bd47bb9935aaabb587f75850556ebf4692dfe1b039d67d9135b395696eccfa58386ae9de883e50e4fd7b0b2a6d161ce7b68506c664fb353c87bb9948f80d2320eab2dbaec57b9b2c40ace9a342b5e53de83b7edb1963a2ab1b692f45191a4d1672a4d12a3727589c4d9fcbf69b80e39d6f0d55d5fbd9f316b3ed95d96f54798e3b090e1a5143b3802e53e9715ae17336275d5516b2cea7da5edc13a4c2484b59585663180ef168b1b85f68971e11f46ecf5bb5a41c3e23603784f32c223d766afd94cd1208ca8c00c510495e752c1c90cda492eee2f7bd0665d2ac0855a3e13bd507ba21dad12f8e49c12a3444e66e03d0b435ac14a57f02cbd9096251a20619cbea590f26e09181778d0c999af73a1f6f2c510edfbd68bab7031852ffbae094025afe5b16a38c0dc0fdad3098c60724282a157b992951280f070965b80b13d9147cfcf86eaceb93322262722ac1178c509a1d7ce952f54413f41d9d2ea4f78091e0d7ccbb665d46876415892297011671840462bda664028068dec8f5f55f87f87408f936af9b73efe9906f8b7e715dbe80c32f1755f43236dd33974fe53feab3f4a25ae8f9bc6b282c1108c6f13f2420d9b734677917e7aa53bc08f4cba39737f4c8c955f8ccd64ebfb28e6258b49d73f401650e8129fdd8be62c7f5f6f9e7a66d26d461634137cda3c46da00da9e235267bca2c5544dd448640e187c8e3d7d4fced7d41dbd39f557f90d3388d0782f2603a77103d400df9ff24eb9e9921adcf9329355a3eda74c08726c7e15ebc2a062cb6f9669d0c156f4efe5e238160e638be50d01e1716c7a1bbf9268c57d9d327126c69cca7ee3ba16b2146bedb2a6d28d0375001d69c5c5dcc8a73a531fc8e8e2af50c711016dfb3d05b1a43065b0a7f07f8a77dc972712890d9287437c6fbfe3cc73979b410860d85d47b628e1666b39ada4727c5adc2727ab274b7069501d65749d0c81930f1950d334a0b1c7d1ce93aa22b7c6f7a8cc6c15c1f5ca556ab99e2c9645be2029da5c3c7a8f37d2e552a8935f110fb13664b4ef9c585bcc4f44083545db199aa4741c955c856e3e22a623020b4e83d502410fe2943c547c36f48491e08b90aceab1b0ab86767f8a7e1cc8f2fefc767febe20878e16e7cd4e49439684e74209f658a3cf824b0cc35d95d8fefd9f90aa21c6ff54a4ab65bfa8b3a19340970d16561e5f1c6130b2cb8ff0b6ba23c5a227d77a12fbf3e60011d7533a9f8d2fbe9033e41889c9c0dfa7d84b2af35b67a2bdbc1e264938efe83d25e26157ec93aea5de819e7228617e339142ab2f97d4c353e7a6faa499cdd85bf17eb25a9f8a1f482739b284abd20dd70a4fe8f334e1afd36c534cfad36562d15fedb919c650792063740ebf3d420b9d99028b3378ef277a45b501a350e24055df5488055d4881f4c42f09c21c5845aac88a22a6b2d0ca5556973d920a6b97c37cb9cad9a2b3b8793d318dc1889ea6d940f40c15c4aba26b7d312e388621585abf93ae89beceedc3ca28e01ac36096fc6dc0a41512726c643704a8d257fab0877ee61ba5f37d7323b6d72aadc891f2b5cbe87da10661c78380692aba40bbb7cdb76fcb60fa2696ca290dd9444dd4ad1e5e6f2b436c28c5251281db2b28cc580e9d2922a0fd07469fb20f211bfe26e5d41e83bf44f673c364e40dfbd8856306e5d1e1435d611b5aabb488230cf78b9b114709977edaff08c6edb6d6129d5b0c7c7e4808813b3ca34a3a8b3f334fc1bf2c7630b03958b0921b79ed66231a4239248fcd2f5cd65e6456efcb973fc8dd904e2a847073ace0aef95fb63b29b0c7a020397bfca1680dad99d7e08e5ae278092905a6ba02f1d309e9f3e717fe13e15804273f47f4ad1146b4990037a4fed45265b0a3b04f55e2256b8f5f67f062e2b2249fae1599a27855b57934fed38a56f9a1134a16249ace40ee20d66adb37b98be8163a472e52289362012698c933e54f61717261bc26f6c412df5bbb302fb5700194935f72a4fd0f33fb8cfd0c8002cbbf55e0d00880173097bbd7cc3e456a18dff0dc234ad9261c98cd56fe3225d4895638befe72613a17bea118ade5e9156cd03376c88b07fec0df28179c799b19e0de648d2507bd9cf53d147270e8dbcf20a16dc0f47cb588486000dd1c7bcfd20083d345636b458c4f9c55e0b283035819874bb45c6001a22dd36ded710d226108297994963054d375465421a2f9fde38ddab9070b3ca2fea5e87fedec7d5981f08e66821d62546bbf85784ac7e3546ebe7df6e41f8af05f391c9c57b41299e40a728c94435ee906c1c93af29a020d505df9a9306446322a55e82b397cfe2eb81ca7c34829b76509176c73869778b96c1e390b47e87dddb6f74a3a94bf02fde7c4b32cdac65d548e1047d5cc098d7396a615f85a02dd59872178706c74b4b5f26e823a85dd61ed2cc6c34532499df47d40fc62ceef9a3435b7b6ece299d615184b7be049da66ea356a7f7f23b4b5ee82c43e09bead0d0e4ee0179b972666d98817e96eeba33000b6597f6f358d178faabdf19f4c065dfa30bf19f1503649ae1034d4773aaf2f1bd0016675542b3b41bb130cdb42438c8ee647a1f1344fa64476319551ae5dfb3840c70c62b5899463f11fd563fffd029eb54dd845af5d4f86278bf9a299ea0554331cf87cad778b230d079be5711336fb5f1444ad32c759121a5368ca36ed2b1fb2e1ba2613565b2b5543d54fa3e7509dcb157a712fdae12ade1c27faa54990efb3d77726fb947b316e0866f34e2b0eb763f80af6b37ce2ffa8d78ec417aa47fb49388f4ab61cf49490bb8a2a2904ed1e155dfb2aea0ba8953d379f4a87dfeeda5868a5d65b825a17111dc50d5e3fb9f4180463be247b37db941c3c8b853a401be7f11af6a701b685ef1cb6534768ade77215f3aa1bf95b5912cbff31ddd171df7011d18bf14b99361b4f7abbf086f6d44b2cfa399eb1b58c6601f680de0b04a5ff5b0572587570f814fbc30c14d96e925cc10cd9820fdb6a552b3d7bcbcbcfddfbe64cb6e42a10dbd88dd3b160427356f247dba8a28c149e20211c018d0c58fff3f90984496ad06b7f55d83db452f123f01b863cc341981618a792728375adc73e0b880b138d77884c5202fef7e1959bea9f6c4ed8342a96ee57c86341909459f8e4e2adcd27ca34f77c15bf603cab1370d091a02ba8677da302cff56f0888a5f9cf9e6416577558c12730965621eb421c6320fbd0782cb10b4fe51b648f9c8540f1f1574213ae77da21d3da747ded513f5b49c95c09fb9345f3e6120d9af3990301049439bf7663e3a857f9837ddb2bbe5ef10c13c7012d5d21407073ee4ee9f72d2a6a2eaa51e74d3c57a9d84f405eb15a3fa2c01fe292b2d088d3750b16e0fcd28b43078a583a4286c35de8fc3c20c834f985cbf0d1b537527a5438e3e86002a6e8e8a119ecc8bb312c224c07dd7d09891ba7b4b9f4d9e5ba6802daa079a9ec411c70f97b22fff43dd09b2e8eeddddf16efb3ea1b34d9f95ba1f467b099061f620aab883fd8f9dc570da501093636d8f62fed078bd440018bbc8aa686fbe137e259c422317c5afc2899e69f3970c9c57b987ac974c0321325a2e24e8cd0f2564adfd51a9d8a6093ee8a736c4057877ca6f2fdf718f636297d9ecc3397d63cd79f5ac8cd4166f2aa948bd7706612011a6be792bd5a3013b51ef356ab1ad245a7a8aa1a3f699baa84abbaf06f58de36a9acae15bf52e4ef19874c13f57eaaee56c818c24c7d9c19fb5c82bcc2e9129d764e4b2b108724fc0457ecc6c5f1aa93498c6ad84dab985d5ab100588d06b6b18974fc902320c100139b7a78905cb7a4c17e5d38133fa5702e17c7b8ccff65e56405300a550d9ee63cb34669dfba3625c9b066788dfc5705d7b9092bac422f1da485b8ebfd5ab17d7b750acaf46f92d79a31460b91978e09e27bc3e6ba22505a117c01585c111048ec9abe69ff67ff2cfe917fd31c0bff7154ae4b73278ce9243edd0bc73ee4a9150691f89ccc5b16c91db27bbf7a4462a170974a9a81b94cc9e2ba9afaff9a3c78bb4bacf592280b6534cd98c4311cf3ef06e3fd26c7271cba6a0981cf93c85a0b5640aaac16200287b81b6043bdbd781582c0023160c4510c7db5483a90416add024380e25fb6de03714803aece7a2fd12e886bd0dad0209d751e84b90c80331c1c3d2ab7b85d721b866d8b44921e66434e48057e5d5e9328408003e68a33832735447a1296ae12668237214badb043bd7163ae7af5ac2e921a3625b421531fb9f0577118e8ad7ff868ae6ab6098e9d9215703f02eb5f084536c0e95390a09762fb3716e11009c200545e507fcb6484698338e718a5cc71c45bc48c7f54c29befc7a39ea7a97ebe8034fb2bfe6e451f3abf9edf7916b883b9cc4e6c913ad12491575e36f2a6479c0065c2a31e0f71b18a09b738c70bc1ed32b0ad028c84fbe2aded877518c0a5668664ee09ff8852aa0bd478e25e56075dec164f3f391a1065aa18425735fbe117b34a717192c5b386c90def5c620df1b7918674443e97c9e82e9b28581e464e2688bbd47738d70ab63deffb3535307636ac0f9b04c7439077d892313f47f836ec665219b6a261e1659723d2c943798f936c228aa93420ed70d54d4a2cb85c0907f900d43d805e54ef199b9fded180ab55e2f6935d02c662388a648c94bae82996958eb64cfa378b9421dd010d620fd7d35fbf88de6069cbfb8ae6775765251a180a260ddf319efa5edb2b720eed338eafd94210c33eef3d6c19ddc87c01ebf232a708092534c271133e02898c81d345edfad673331527b577abe24e6291d8c68262ac313d8fcdd6eeebb0b9bd384b82c3839cfad63471360a44b7e0f70e143b1371e34995ac742bd5a25beab4709bebe15fe776a3d4e0bb085e847ac157ee2db42deee594ab69e7da7687e006ec01cda7cf45baa707c0762912b0d3d8425210d7ec263168ed1cb39f721b04e4feba28e0e5a4ba97c16a7f69f93999fc7af2419af7988ce84e9a196680ff4621226f4f495c88f2422216671eed2152559aec4cab05a4939b8f73169ba5df793174b67e289ece0c57a5a400d92951f567ea974a6783dc22ae6bda395da16f87b0732608daf7a1f6ef7b9c754c014cf9aba309ece8f52627d0f051f3c34f46da3445ce3b0bff12dc9a1f38f775d181bd7722516a9471e8306e57afe1928324ce1e12de352b93b946076d760c66456e121282b097781fdc981c4763b764c3f19ce97091dca27ce9690690a816f7ee6d4c2f8dc768161e23a57c6390ae950080e27b1c3a6e4bf1f1c367fd74b0c29edde36c6980613b30a211d6ceeafa49811a66653c5c68673795eab05203b42669ee9f4bbdc004517b914e66f987545c8bcf9efd854b72a63c2304bafe1d960f323da9aa81c0f248b9d77fd4b46faa7b7fe86351c3105674bcfbe71eb3b1557768b10547525396a9a185e2b14a13180b491973fd3c70f8bea64fffb4013c2b93b80866b3a2252119c4fc86a038007b24cca18ea84e921868f20da03ccb754efff8679a3891fdb98e8d2b4b76870418e8fd4ed8b4790357d29bc3f9668132c901a98eba6061dab04b1134c55a7b2bd8965177897b227721cfa3cce4a4853fc23866c125887e90963d46de00be6a683bcd9ef2b825200a13815db4e56d51fb9d3e1064177b066d5e80d28666666c83431109ded8630036b786ade0ae94fa16463a702f844b127757f362619d8b4e29c25013e3db2413660db6f0547b687ec08a17fd0d3375ef4822b6cdfc7e7fdac577a007d749b42d8655a001b2a3d985bb0f29add89d7b8954f1e91360bc9714ed57f9483e59c934e570ffd9ffccfdc21ca251ece26ddc1dd03bf9cdffd058a9785b30b2412a40d729eefc1ac21b523fa4927d30906683008d1569b03138b010488bd1ff59804ab910ef8b5e59bb620a580d6e6e1070bec69116326852efee4f5c95e34e29b4c9c0bfc1b247c6dfe19cb86f919583e4b7433bf208d2fb338091a6afd6a9a01e690cc02639e96a07d8b17ea01e26811cb45f3dbfe0027240840310281cf4e9a0e71af4496e8d038017456fe12a6018450eef89ec522bc7be4d8d08aa6c7e8d8ee6747ee3237c50a2a971ed26d1e3de7618c4e8a2cc82048197128adbd95f26f2cedf32e23e9178a37a189b563690a92cb59b5301a5556f5ad8d4bb0d9f760d3608156b865fa3dfb512b4b27c6629b1dedf2b2d97e3f3c6fc6a215fcfbd03353448497bd84deb6295fb9495bf63b29714cd919f7b6595615a633113d7a98f425cfaa1d081bcb810b2ef785771ace1bc5e462a8af677d3976f285c1fd13ed6f15d6914a00ddf9540c8ffd283b4bf285ea7c0eb45ae16d01548f61c61dad993564b46b1b719fd75c64a25ee28f892b42281ee89be80f005735e335556dffeff67b6b43ac4eda0f0c1c68d8ad820aa5f3e2de0c8bce1e37405d491b2da2237543002418aa0b016ea350a89ef85ed9eedf517adaac1410c9fc6d7074ed966741979a9b15418651302aaa703cdcd383a564815450724be1f083db409284505a559be8b1ca24f8fae00edd2253e235de37e1b6de91facd1123eedd543e6f1ae9df869a87a7bfa54ac716bcd24b3332472f051aab8dbb4d1d2e9c0e8df24911d0696e0cbac829a8e767485b1b5628d5dbaf8a483abaaad0d5bf5bc2bfd50d079ba4e0810e76a1b481e1ecd07a61994dd0d8170718ba2ea75e0c8e3efaeb1c3c7377258cd3d0681d87d24b2904801e6258d6a7f42721928cb7e128101330fc5574a7688f66f9f4a798e7b2de23aae45084595b39cdb6e4fb76cf3bf227e5715220dabc6784859cf50aa7d611d4cf4c55b5aa3a447ed6f587df7d4baddfe3f83bcbff876950a3edecfc77de9add5d66a7e55fe507a7b1f722918adfdd73730c7f77a235e015b80fe22db431410ad798ef266ad48810a43d5801527b74ed4e8cf96812bce2f3c19e87c032f05af04e5cc73dd062bc5ab1e2912b771c259875747a2e8fcdfc01e81902267841dab2f4429ab39e559304e9b9ecaba9b15bb9698fb436967a8c6e434dae3bee6df0a1781585adc2cac6f53ab7a2e8d2884e36fb2e23aefcd2f02fd2b1634e16f39c1d21235a1f77fc2b753604a88681ea243352f77007f8b8a36d56548bf85f5fe35c350f8c8ba82af7ae8fdbea8716dd534d61fb9e6cac6d35f7d15fd441ff8e9f52fa0c5f8ae3d11604f3d0c62430ea72ffad773fe0cbd8b0555bfaaca7612b3faba49917f3787ebe846934e3a9dff5959026a01872d04d8b397bf5d914e42e381f0a6787d3be7831392def3f5640432447575b75848110b427182c17cd7bf76b9aa885e0ff2fedaae4c88ec2aa4ef91cc777490fcd925cc73d10be7c7a2fcea8694e950e10180f6031b87e5bb43ec26146fb5f4daaeeda1555330f834de8d73ce88cbcfa9a61279bfc16c3ad1a8711f3f9ff912fb0c32fe08f08ad7822542db1ff67a4ee7c1dae7eff3c5c7efb433adc97a672cbf6d224a5de842b687325c20a652468635ab4948f676a221afd550a1b6f3864e3863344d5febfa9ada19adf077481c316c151bc8278e7c83a5e1f62d16482b1599d36b1c2583a45842a38a60ef3c944f906e02290ec4d894740955eaca2f336d71ef2f91bf48b12e4d94f919996135236b90da432ea62a337243b83ee7c074e83c8ce98490a6f3249fd41688ab0e83d5e502b70979e49a4146b443819ed3c844eb0be2ad815ecc295e30f9d4ce18a4080c95feb1d262a346e468a4b2322910bf660b0c11aa466111a5ccf1ac211428439ad25301c98b7b68e94b2e720766214e3b07b7a3320b00b3b54b98df6934186009f6636aa3a1cf3222da0414bc2a806c6526431278614744f61351536336fc5fcc366def0973864f5c2cb2b510dee0014977e6b2b5d4fe4b5b1a4891e32ae683b4a616edad93e999a7c6b631baa4ddcd3ecd8295726b98c4e5f43ae3ec02cb5cfa76bacc7a5f891ddabd55c5e91af12698177adcd1363266b879c37a69a27072812d51d06038fe1ade419b429796533d50ee833b8ff6540d48ea6705b7289d69372512e051fb0e1a3c1c68c50b4d7f1cc00c2958090fb8af304da31e4a1945cef9b315d9968fd1ba6dee2a9e66961f2b6a2e8ab2a4cf97ded16ea72f375434bf2238feea7178d1b211bb281e2d8b50c58dd4e94fc21ee7673bcdedaa8d3a3bb669d2ccce45392769a8fc5ff2b1be3d25f61e8b7034643f2c3b0ca8f793452398eacceae1310893e1fd4c61b0b0294d961064b23b5377e10165c253f66c62173b096a977f675d796e2e68a25f31b540a2cf1863e736d6cdba15b18902c796abaf7409b47370c3d2ae90e6b7082cbe291ed2691de46fc4e04a44c2b1fabd9dc3e663bdf2cb39ac335106be8fc93ce80cb8d52e0267584301b6ecb0ad94e5b50a8c7570dde95fa33d73d2b328b7dd3313cdd64d8bd6c712de28a005dbd9b0af28ed32ffe62764600c7d48cead596fbd62b70d8118aca48754c0bdaf8da6814b67e5397101178ee26e5f6a41ad4ca05e46499fb088d34c6f67e495a86d8d7cc46911d2a0213514ac9495e365c992234ff6e890e32a97ff2fd255410a69908d19fa40f42c5d52b849987f57510672e18f03ba46d5870b19555f0ddaedac4b478e2393ae9e0f6195a88600ef6217d47f1b1af535248c99ae3b3b5ffea83bbe5cc4218a7ad5567ff4c40ffe6e56b569f069bbbf114a829296cffe60e68b4c8f3580eb4c235d8d296992c7783637d7b901a8c9603da196ad2bbffe6e714b7b460140344a6228cbb4b6a311ad3ce1d2f6b537c5fea21964ffdc3026478ae491080f701eacb6f831838f81e52884f4a2e29b2f10335515803659cd66d409e900c5015b550d20e3f6abc8051f3f32897a8d1eaf643d8c0967578f797fd17ec69d4785cf162511626a47b6a8514109717902d89f0a1c6fe14551ed7cd4ffc9907061fa2de67f1eb9175cf0f2d96e67d40a73b73b23af15e13e0662d0f7d4c08e7b1bbdd45695f4edd6167d2868b05f2c3b84e50bc759b116b06ec754eb9b45258a986515a92ec94b7ee3e074070ed87599a61dfcb25d12cf807072e1a2f83d901271e0acc26d4a82d09bedac2d355a2b0fd6da41d79b820028ebba58b6f6111e0637157af641ca7a4f705b8f840db291220af2519835950c5ad415de877bc797caa18c8a556115f2b803d4edea407a5958e260717943d110471476b36c9082187fa08156f33ab697ae217cb95d6039022cb87dee4b38d4ffad854b0daa6665de7fd21c7ffa94c78436c5108f5dc4d83afb75a55cc63dfff5fd9bd150627480d5f198ef3b992fa0c4ec513624a83628476ff004f0a1565f4d600035bc369bc5eccf2fc7b466649d4259a2201c0ae98ea70c8da6f8bfdeb52bc0669d037ffb2f791963b6f8b3df727594ea78b03ade5ab6eefceec96781718de56537d1efe9dd2f8c3fbe88828d022bc21bc19cec47ba266cffe9a022999b16fbc2a56005f4be526f785e0097b20c764c684ee6a5d7824f1124cb159bdfc89e95cb9b08d46d0998ae2f10431f4fe8284b8e89825e489d558180212ba995d2949adc4e2473cc26f88546be5b4b44eb0a3b2d33cf0427ee4c7e8afb48d48d0ede06e73fc4bf79825e5b577bff90fe093f17b23c2207675dd13268eb519b1b4bdb95d8c64741a62264e4e66020edf9fcbf0f8804e65306217d94cbca8eb246e4c32b253aaf6dd4d608ca29e29127ab21a95b1fb34e18e9a7d26c30ce1cb72db442291535f54f4cc9ef974f8753419a0771edc2261a5cd958a0aabb861bc99d0666dbf8b67fc9d9c7b644be8f0e28686399c0fd9230c4b6139a7bd5e5ebbf940e78e7f8eb7664ef94aa7051ea10b8199d990bd44c431a2af5db6761bcc9680d255fdfa0f7aa9853e11dba3db05bdfad33ba61cf857073b3a00aa0d57bb000cc65535e2fffac4e8d46bb365d56f1288d18f94df636a3b9134f0d6972c7b2267c0783a5eaf6083bcfc5b44d22fc0d1868c8786d2188139d22dccb221614d52e79965cad04a6f3b1a8994a73460df878e3848314985464f84faffa2a4e9dd5ffc421e47519768996b3b6a4b4ef03f950a2431ad0052804b52af853d25a65f9fa318c4bc39177b27e5f5da521e371286e15f5fe4eacada7153ccc2b3083205ef901e1b5cddf1fd853664deb7f1ddf8b966d282fcdd6b3ed30d097c5b060a5c2241961cd48d5c0c211806500c5168c8f6d68c827bb5af63aaf069f469442f788c450f3dc3b724a92903d78d18d954e4543abde2abb4865ba871c84a56eace15f9ed6c6a4bebbcba9246b4deb264557b6288177c520cbf0dc939da94ba3c2c21935745c424531863e6743f36bea90c0ab5c17de9e98f6f6215292fbded76af2e5a9da7cba8c7e4be1ccf3b863f1805a863d33f93965512378ebe513802e75363a229c00c3f93467cf3d14987e8d84ed786161c3f4897c1b2031e610b5c7aedb7defe19009d58d471ae9f6efe9998c02669ae948616baf2ba3a7e7cc158ffe441709847917dbd6044942e6dc187056ed0bcd6384c229cd3926ae0d6b55e35a4f19820baff64f2ee4de88ff914db930ee2612528a9b521231913a018eb351a478e4519cd96c64cefd76c989b1648d6bf07d244830340e22807b7cef53069c2a95f1073700ca1fde077a956353954b8e8d79d818993ffb266f9d7e5be4287c3200bb5a2442918514a5fb9d9d49dce57ecb005d0caca9d6cb9efdfc4b5c8390cb2d92b643a7d013446857417ab9c093efe964c50e69554bc38e8e2f2ffae4f3afa8b71412ed4af5ee15e8adb6abe88a0a3a7287a9484bc32dbfc2232e1a404657b5682e30da457e41c3d6fe35b869b3fcbd87462536606b5f4b3ba16d1834d37216ce86ddc92978405989985230647029600572613c38f2ea64b7fde7606624e3ff3c53b6cc9508b3c089f6e865a3e6e3b02d927478f3ac452676fa474a4d95abfafebdc36615fafc0e286645e0d4262086569748f094947186bcc590b0a86e17c5e1f072b420a344803ca48c80013d34bc6a8e4ad038d8c2c7b26e8e6d4d648c6aba2db9eba320a22952cb82cf96e46bffa9906fffe91fe6ab664024e7d4091b12f29073d3ac6411f0efa8e99889322d8647ff9306fc0d4407d7370a58fea7df904a356a1a4578cd1c693b6f047f43defa2a813c90c10638a780ccfeb5df585e5b2b25796d81598543374daa42d67b57b7097aca38aa5f467a79c1d9a6620b8793788ae8fd4ab7cf1fe83a2cd94907fac49df5b986ce5eac200448f1c75b7bede8fb0b22dc7bea8cc2c06e0409604e1e374229391e38058b22f5f2a04cc3c40a254d3ceb99f5ec1e7daa204971d7735e5315a9e4359bd46b40e9f655a54dcf80533f2497d5bb9d14324b2530aa4a8a509eb9e8f3b8e1410bb45c8b7f95f7aee7d6081946c236d7124df0b4a7483bfcad8370bf02e06604aea415bf36831e4869e6c3dd5dc1838e5a96dda429794afd0373151c2372b3c48d77b1acb51303794303c3a350a17a883e9fcd254bbeb587410b8f0286359c8814b7445a7b1c3e8df4996e084caeb52199331cc2fc72e289b8a0df81964106e7d15d307d91a42a40b90a8c7dbebb04404963ba52321cc1fa265009c3ce9be3880a24d84d6c93c6aab777d0046445a63ba83f6cf07536f480bef35624aa591e2ca1781d02ff51afc48344de49436cd75ecef7ab40335f107b1b35c20c7337487c4ecbc618a4cd79fd020bf07de9edf459f6fa64f4f5573c711b81b7e272c1aae16a193e64a94912bc3eb28eb71daa7447ce8392bdd0fa3f753d391e2652afefb1ed6809b3e49a8f78e548cc717a2f20ebd1f4f98fc45396db29f3f85e69d0dbcfada2f12bbeecf3b387b7bf94a256a9ed3786fb706442bd0b172453d3a160cbd89cf204b1a5f55fc615f1189cf8340720d203ab752904dc4ab39c9d1072701af73c75557ef5b523d98972f07fc8db0a92239c588a60c74d943a75f982fb7da6a89c94353930380bf800b7911c5c761a684ca6023970ddb978cccb85dcd9b076f16981db50e984403d7436a93c9ad51af82aef911f674d45909f55ff23bc2e8d9b7a1251f35ff128539a15460f4e94be19a756b38441dcb9fe6b090cffe8b50def73dd5f5b754eb04e1fc8d9779ad12bd8a0b01d2a18daf3b02be23220d0fb4aad048ccb775085c5c133e730f6f936d2dd8238e6e89daca302bbc83c3e67590a1165f3afd762e03e9f2e95a22f7fdf2e14035a6e46945ed8cd3a107a0baef342c28f41e34dd96206494c445bc6af1678b7f7a0048e494eb7b2397a772d5de5b67e590cf2dedcc345a80fd7abbf6920f220166ac236ea43d143920ad8784575c2081c5bffdde9f572869c1113a9a3ca5f8fa4fc62656fab910702a16f216dec2fcb6e93d47f2ed78a8a4aed6835514c181337c54e8cfe2bb0591ffa1c7d31ccc1c14dea6e74b5106084b29edaba57f8aaa2e7a82b396645d01562dde478eb6941ee126db54a1a24c33ee8b9ed2fe9ac092f1cfe989fb091010c38ed95ca83da0a350da6d45329979d92dd8c66e80894cdddd9e895b2167b29195907bc7121979ddf6f3fd03f29393c430c196263570e0016705882c5a5fbaf88056dacf24587e879bef963f6e14d847de434969f4c2596db4e71e63f454e5d3e918e0b74f7fa0bab147d8d7dce438ce5d73b1bd8f189c3e964253ca95967b32c2c87101bf21d33ad4a90db07efeb318242020287ef85b8f6fa22abf27aa53f8a1eedf0b7eadf523959be8d76d0744d4ca8a55b9ae1d8153057493ef154fec7e5104390663eb19f6031a15bbf931e343b8a1a59c6ca93813cf6523f88c8ae85a3933e97631065a853083f6f4a7c8d804923458b82d3fb6295e4fa987062ad35217356dcd5bfe7efeb152b621c71da48f11379792e28d1bf8439db3278bb0d96851e7cf0cf41c4b92352d69b86899f5f0ac9ef511f358794c3d2434ba53c7b34e54aec8f8cb46d18415e62698c85020ce65816a2e684a864a237ff8ea315ec87412410e51fd28835af64b74ef3a66507b5269bf7ac976a00cbc42aca194c6022582dedcf9639be1fbc0006fd1d8306e353378505e2e12fa0c8dc153e0e3189a4e3211db1c065b08d4feec2e1862d6af303db7ccfe1ffec9f1e2f6330c7565f19bea94862102ccd6d9a6d0c334592ae2726525847641010d0bb86bfa086f24973fcbfc20f9ca7977fe17923581c165a769018383f398a5678dd750309bf2b2a3d9cbc80c7d7a46826edec631c0a3cdfac92926f9571560a4475c879c4b8b07b846111a45aec6b244b8c2b18cce9c598513b1e6d58ee041e9f56cc0ed588d4d56948312f4e92c6366ecc14556436273acbdfc27beb0d8df911081190e8ed4ec97bbba0389b12a918431805c43fa3523134657213c8795b65fd84b139993518faf93f9a864cc7cd6ddee5ca58a0547003eef5acd78609695ae6efa9cbcc43635bb589dd7b46c23ea08e382f45c8eadb817ecbb393ca73c37468b36ea1eeef84545513c9077b5bb68db8466427f15aab70a68f7e71ea84499fd291aff562f36137f6b68a1cb9564e9e85356ac0d9fd41f3961ceec805ff087e9ad657945b59f7fbb0909d9f588f6a43623a4169257123dd24db73cf0060ca440e5a4b0f6c1bac65a91b4b36ad6a32b1091ddfda806cd830dd9875622fa4947b572a5bc574eca1f21514d6158476a4dca0f5193ff3755ad69a402f7d9507e9c074c8cab5e48209f6378493c59334e278033edcf83a7b5e58d4d101ed2a03f3a82d82e81b0d7694fc7ee6d55b560a3d9741ad60988721da90a147764d9e630d9b9af46ba8aa105dcb37e5ceb89e87dd42ac91fcc2371d3b36d8dfe19880dbfbc025628a2243b82cfde448ddbad97d24335dc44c40d71b2780a4022f083c728697f3033691c6987d08a92dfcf12a26d20614ab56aae61d48fbbba2e9908da3bdd9ef8ba613a6f6d24c3e2ac977bb48fe58a03f00315bae451e63cc88a7dafc3308a5ff0d370537ccfa19a63230c3b54f406475cb83672fb99bc7152d646162dfbc6522c8ca4b7f1d5c140d72702716718c83936738b7291c161e029dcda8af68f239f1345eb0308161cdc6703034bb8bcf8104013df3b2a604d0f297b70c60479983e0213364a66dcac4394f849b3596214fb479daa9ef6ea37b39475ab4990676153d03319a7ab2c110afa9967085549d55c7d3e5445bb082a43d96671fd4a898996b117e56c3ca864142e79fca62d4bb9df3cf03fb6235d6a9af61cf1dcf73bd6d0bf7ea0b006fd9e4d344571165265ecda57fa51f486a5aeb87f261f70fa8921bbc78c4aa4f63cb55e2fa7b69f080b8df274a1c18e09f8904ca06d12a5d517aba40a76609b95caeac5830fc9eec178fd66b6be171b773768813b54f1f630481f2557e0181e61d80a5932f3604633b424ffc8e2e69eb0a2bfa057add7ba4e0a05700c37681b262579c9e42c91f04c911bb8bbab9f62c47d5fd8d77d4650872577353b67f881fc3c092250be6868dde3deba02f794bc20dff944c6b9f69a0a1b6e71e4dc0c429df2fdca38f4b44945257a794c7798e81b7ce2aa8823d04c4ae15e0e791b00a01b4804021a873c7dbdae6510fb37fa6dbeaef421f9661a780f146a537f6a4134d8f79e466074dcfa266e119e5d37c9e2daac4ae38dccca014b9518a2d1ddfad7b01f2b6cb7465aa1f8f572b68d1d2c9cafe99a7b0d3ea49996c212218b6eee83ce49aba0562cedcc113192299d5412ddb79ec9014371d17e831b974211ddada1081d6122686bebbcf0c724a72e95a730aadb0fe31893ab3b25da7d39d66f4e038e47e004e8f1d69c7e8c7b27230fed71b4e0c2a6c4b8b8e00280ce129dbdfc775e9126b93e3b762090318cb13b0eafadd72438a064c6b45dd43541f32f76e3925a88c4e5554ad0677cf31f39ce70954fe2f79592a8c28093ba683679746784eb6b17ff873a60203ba8997fa25b9d6095578eaf6b342c26d187c415acca1fbbe48e19cac93e91af33bb1c3dfa0991b36ff2e3054705634b6c32fbc844a52a7dd3815eaf1baf19cd39a9ef7f342de758925ba28d25828466d7fe8d1531a1293154bc6cb9e8ba1bfdd30e01c262d13c1b1a6fa806c8b7a87bcedbf1f7f5cba65d5c719a3b8720cb67943098b5d78d9a09480cc8dfee234f3d869693918639bd3c794f16260807b21fc29d5b785693a1baa037257daf41829f0a0195bfc5a06fca35250991163808026a6122ca9229cc3b1d46afb9586ab986355da09882a7a6125afaf1cf1b06560dee16f06f842cdb648abea4ae22473fcbb9960627645100f0a8389c19f1640d1f453cebfe632d4a87bab3f36adb92f908937e00d30224ab323cb9a7d444eec462a4c4f6417bf8bf4f248ba0ec11878a56159952263795cf13aa20caf73f789ff529864742d2677644c5f354b7a3592eaf920afdf72f498317eed64f93b0166d161cd06d6ff81d4f13a6c83bb2ffbd9bb9e1076f48792f377bd1dfade443cc66681d7b48d14394da525cbb03b2394c4573319cb11866beb364875e51d4172ab253d6f1ae9c210f055958509044417e3b019e2f1c342c3610404d456040a9e6ceeddef9001a4ee2cc73190f022c0b562f55ad18e9fa8cf532bf06f10ef52c60b053dccc43363ece284d539bedc4a393459eccc7cb201058e0d21781d642fdeda846cbba2b239b6f8af9de4b461828073273d573d9aaae99ad0c54da8a55a2cd93dbd77dae9f93c9577745d4c4e88b8b21fd2ce04ffb1c6266edbc63b38d197fdbb308353bd2561ca91ec3b54062b50971ecca159bf4c1f7c852ad1d8a0d6ce1ab0f4866847be4d59dfaecda7a2163571b27ddcac83d45721d7bdba718a6f6730511432e68cf3b606f1a5f4dc97009328bc1d510be8928d64f6393be0bec5963a7a19feec51857a6fb359475ab65d86870b804b857ec14dc9787631687e133b1b72f8e9559a10fd6fee2078b89e3aaaf3f4da2ff506f5a0d6d87351b22f33421b88286e83b34340ab97bb3d9bc0f420380ae74cc6bc9cc77f0f732042d6da2235785f880954f372e8df5aac2948149a842457ce217f00cc3f3c0eb2340d72347eb1e238ae7dfe73a4cd143456192ad980c0d8c3619820855579285d6aa520fca4f6f22f9aa2b6a7533bcef7993bfb069949c508e15b55d6b9d9352f5e95cbfda3d6e36e35c7300e3b2824544c287a7c7fa2c5a0cc1920f2987f856c13f875a65a135db6b2bb451c0ebe663e752e8a1088a0bef6f8825df1461ae5934ad9089b4986f795e743e6e2001263e729740f5cfbe39c66d813c54a18f5bdefff1129db6fe22cbba9498aa05d2cba452ea3dbb65acf33d21478e5143e2aaa17c7210dd4745da89ed3644c139eedc66fbe7b01fd37f0795002c888ce43c658115f800baffd0d1b0df24dc5beef7c434b62255011a82e3b1407e8979c87c8f5541d0483d356902b2580d6a73b56db527397e4efe5b806955d45aa9b970e5bfc9fafb94b3a5c0ee654dedb76877e5e8623b9502f1f5124f94c7a36187b3e6c58c19c88a1b735e5b0761b7a757216121a5a1e581303806a9f2b9231589023eaa331e2d82b9421a7a06843a2b997dc55fb35281626d3ec5d15e97b08cedfbc415239a938e83e54aecaa252c8b6b1f22d0ba0aad68bb5af0f6d1f670ef2a145b743eb816bd4afddfeb27b1d6e678383622ca9379ac7885c18b01e191ea753e0929bc1d6f01472f6b4435b51cbdec2863abc21d072518e7b4ea9446ea169e516b976184dbd4baabb90e99f93b5da1941facbfc7eff3c67239c350aaa6eb5808d227a8d6126101debc5041606cf4bc4c30baabe6634bf67aa93612a3d888fcb4b84d98ea6eb59cbd02aa55319220644864152a5d60c1296d8018fb26b9143645901675e0795ab37481fad58d3ed68ad4db0aac2d1e100fcb3190c487543bad347081e944011548bcf1869f12a31a28c1180da48210c59650f4eb44b757dccd49b410cdee75fc8f1a507c24e8a3bb8b55bd38865f498a433ed0cbe4ff9a3619aee2a64b234ad8a5dd6eaba7227579384faac5a3649075b0daa654375d86d35bea79580016fabe3076c72b5efc14f6cb99e4c57210cc204310412cf0d79a1e59cba2b6a12f13a72b7704769e42f734326af6edd54d4fc0ac9e086786535f538d4e2ef0d6b29eee1d368019bab3c3e28af0bd7c0e10ccad60420cd86e19634216251ad091a27890493f1eb7a6bb2aa646c232105ed991a46fd5353013d109ba3c5cb9200b23efe866aec1003c9eb2bc7706fd6fcb3397b4785c51dcd929e5e9932b03fd449f3a35e0d0785d40fa4df6647207f523394bc29139c1c454f907a558578c22bd8dc4d3a6e9262ef55022ae8bf43a0c4cb96e0ed8d3f4ef2718a79be1d24b8684d3f7e1b1d229f8c0478bceab4e50329e60ff5ae7dac8be6b0d5c7fcaffd069045acb8c4e1cb93ea66f33fe77cc5a7a44354a239fd4184b2a5ca901d9e1e1843d2dbed114ec8b5255d52d16db11bdf827a85936bec8ee43fb1f751fc1973e6f3097e956969011747c40634751c96f13d436b2aca684a5cc93a4257678ad29e0944686dcfd331f68819620fd155c2f2b33bbf4c1478ed08aa5e013d63aae7b3bb73ab75aebc9f338209d82f957627eb86b8379e4ee98ee1fad51e502c651a3554cc04622b77130daf58b60b26ef3abe15175fd06fe55d7c4e88e49dbb0f71346c558a10a0a388b6a60e42cadd61452820a81e62b4726202d08afd1cac0e50b4ae929f5edcf0c6d95b9fdeb1584864c4b37f27e99ebae2c8a8ebc0e4fdd0d470e73fedded94c054b3922e9f180d01e0f1915454e45a8d27b4618966745dd01cefcae3a0610dc129de150324cf4abebcbbe5ddd8f0ff18d9ff3638e081fb844d919208c4d41c352ad825472d67442cf18bb442384e24f8936e2dd6c80433671a63a43b3be7cce36e9c090678fb61ca96bad166447d602b8474afb07674e4debee7b96548f0796fb8e67a0bf474e8d1c5acb3f868b017456113ffae99085b8b153f3191f99053d9e54c9cb424f1d26a9dbbd02567201212549380ed329bd19f9d05f64b1e0555ec4d7311562782b2ef90c3a865dfdb32a0ec6e059b8c0e0083fa34fd443700431c8e59cfdb0263485fb6e8840d00aed1f4ed6fe56e0cbd4684e0c3bfa4df69d35642a9bb9ef3d62f58d353d79cff45050b5f98e01636db6a39051158d9beb474f0b9b2572adc644aab0e861c61e3c9261be8efa0525da4ada869895d688a80d7b2a081c47612ff75928c8c97a5531ce0fcf56b809ca6248a429f9de30aa81c8631a5eecfdd1516bcf1036cbfb91a1359db706beb133f98dc4b3ed1bb9312d22c231e98e10eea91c04a549579e988bac1cec21860db9a4bde2a9be968b88b2dba7b7ef7e17094183f77c67ff3e82e350825aa9fe2c670fb97c7b274c5668c6e294247d633778f41e6695ba47f7fa5c8668b848176185b80fcf6ecfabcfc0b11b3deaffd706e6b93ae147fa280a344efbeb2d6f7d067821fbd8e14201ac1041526150d718545034060a6d524fb99217411ae0c1b5985256082803d11b763dccbb61182f89195e42ffa4d6be11167276c3e7df787cce0e3d3d0159398aa9946969eefafbdcd0e33165b53a2d700b0e8f3a48d932e663f980bef22ba1db1bb07497d4d39a428b5afbdd8cf6175d5b766e79c81fa2bdb6384df0597de4e517b77c7cdf93ca379b4467a6057a82aff9216950076ada822d69734df5bc0c528e0dcb36752b3f018032e483a655e56ef4b533250571c4d69049187ba67c84b972a02c11484563ce54a04eea666d7d0061ca09c05a8e4c30f37e95828f40541351cd2b0675227b9959e7b4d0f93232cf0d32788dcfb7c0db3820c3899914b5edaae77f948fd756323c2e4b829b62562826a4aae9e5aad2ef453170507f39f76f905fe9de0292c8bd4db49fe03bd1c862c56a619ae4df5a99765010ce90cdb43ca375b8fd1e8ef81d764318453e3c48ee1c41987db50b714b230e5652ccf3f1eac25f44e7800dbb15916bdd9c461aa8be91ad525b1a24b83934e3de3d04ba15dc08fad8b7fabaf6cbbf48b3f76e927da34488aecc7e04e555a7e0daf198c6cee2f1a63d46aa9bb77333d2e73bac628d8b57407564d9e2ce7ce1cb8250624e6c7d1ef731f9392c6191caf6c77d4696f75b32a73f7aa8d54bf9fc813ce619081864255bc5f29eb501e759111c53504af7ce1a78e57d70a4ae69163ce84986e7f470fe7558550e4281e642bfef5c2231a6a6331f2dd4f84c15b3df0d2090e96d13771f62a04c2f7aa0baff1d34cd35a264bd0b6d9e1735dae66a40b5749244824274496c70a119d3597668db563c1ca3ea940c42edf0e4846a79e638fb17a816e5be69e0a6bd6c5120c42fc402d6140429083e4f8caed7065573407ebe915b91f1e76283f78b34ac55428a0ba336def61f9fe011791dd441cd77b4b02aa017da28655690bcb54e9f6f1dad9026527e1e1528301621416963eff79c35347c00da46c5ad95e11cb391ce287410d482a34304b639c5f1c71c23f4f22db992fdabe13d9e91f270c2a3665fad679dd32dfeb819764acea06dcc3069fde10adedb82560bb26a014a3bf67499e0f6789fe6f922861546d2d0a61b531f664351f26a988a7cb260c1a2c6d6fd00883bee82db37597b208394e8800d67dacac1dd33f37a15c9fdc3749cab283ba064619171b9289fe744a40ae11a2c36cb2b1a75c8d856b9402d81c2d6faa5bcea4c366a6a1b3154af76f71ce128c5f950bfed0b8b4e0c25959d63e8d0fe9af0caf19021cd6ad2c7cdb7a1176ac359277899adb1f61d039d6317a100cd91e82aa36c55d4a2d3bd8af473e29736385362a4c6ab4ae47ab8e16e2cb46e4b98222ddc3552cd46e2717ea5535211226b63dcab3e77e4d0f5d02d3d3c23cb5de655b00d71381b3f2d92bf56911da0add2d4b4ecba90a4710bc5da815219da32163228e6806b3f7c4b414c1e8e2dd563cb8e39cb6469f70eb83548a139a0c7a5258a65e440dc61fd3ce7ec96f6b326a943b74f6629dacba5214b88a351d5b426291e13a2437b6cf6c8bce8e6f661b97a28feea65d2564384ef2866848c261aa098e3f3546435d3abed9222ff7dfe8db7ab000a156d85cec468ba63f1bbc0cb92b20c1015843691b0c95b4b59b7b99c39be0104aadd6bff6cbad1f61d369f54edf8b02fc418ee9da2fdc3d968ebe7de0d446b317ee52a437c0a83dfb671b4db4250223dbf11cfee0ddd8cf1f927d33e4c46491723e817e049dd63af058e4f9ce622e9214858c8b3d684ca5fb9b9d19d7518136d7c9103b574f40703d4689646ad315f96bb6ca79c0ec0a406ff9ba1098d2982bcd34c90a49bfda65a4d806e8a479266d288d0047bbdb13d82aa2c7261254558dd0c82e440a6505882f4c760f0cfbf6a935d9c0dcddc02429825f25fd954a5a242753d2f4110f474631f8ad34c25dba1da4f57b9aa9686bf921c4ece35c850f005fde22a1a3f8d3df5efcb49c546aec446cdc1be48bdba0fb2198739772adc2a51c50b95e551468f2ad5effb829a73d257bfc950c9e4c6f5181ea2546c9bc6344a034ec7edea23e19558adbd1356e98296ff1602a53cab5215a2ac907f35ea8b4a2a4d3f39300c72fddfa6b78db19578a9e70c80641afbb90f2bdb5296e455d8f6429b2c5cff26d7b1c957a19a3250d8459748822f21290ffbc1c059c86d2cae32dc76c558fd798c47559663d1d52da364eab24fa082ad3fbcc626fff5bf6d3b436cc154335a5b3698c8dc4f2856899ff56f9b13e766ab99a86d4e9b627ec19082c0ca273677f71f9e520537e296896af281803158120a7db5d1e4e036798a15df56ec499702a73967a865e95dd9febfe08735de0cb292abde4ad170cc1df1f58770fb660acfd0c891b3adec21a643d1417c97ca917e6e8348365ff9dadeec7d3fb5bf1ef208b919a38d078a5bb69bd73d064a64070d32999f654d362b16662cd5c0395afdb0df2ca8bbaf2664c089ea6c623ebb244c7060a045a824a92d4ad29eda26b05413b62d46a4ebc527c43455c1d212d077a4e1ea0641aa098b4dfb07739e23fbe20249bffc877cb8831fcc010cc7f389ede61f6b7c988e0ae61a2d2a6d5aa6c2aab375b1f386028f9a91d9ca9f28a2cf37e3bfc9c3d6280536f54e7c0b21c14b5c426a648f12985e0e833ca291936ad1de6fe4526533778cf9793249116f038f10b41930901c492ed29e10892c54853692dad1de087c7a11da984e67007e4d5f908e3fa94af7edbf730a4e7f568af9970ba560033e691663c8598f4c32b2620e71f1a5447beaea28ec7971c77a9653eb5fbc4f77ce63c880a1c52c23badc02a57b22cecbb44a69f6dc170a6372bb83867e5641543c1e249f642e4dc998efd94ac895b92633e87168c03b27c875b5649a2100eded64dcc3cf07ca2bf645032f32e0de8ead57c49560bf5430dfad5ae82cc5e5cecb4fe5c2283dfd87bd851a2b3a9ac74d5693ced1b886e59ea25b59e17228d0ce0830ca88413de38b6c06f95d5761e5f9193ac4f1731be20cf4124c43406a54b0939cdccf333985e57a4378cade57f8914409c47e8518e8a092871a9c531d9d604221f7331842964c07705e63c89a79a269e2791d7d42e215714bde741d382a4efdbbb5196926d6dc08f8076ea692624ceb558acab868afb422ed85646979b2b31f5a5bad8db4bf38cd5413aabcf7af39226dbbf3c5881b3d4d0dccbbb2ff74f3d5c2adae62e55719c778f69ff59b40c2691d7626df9722451840a1763740fe1b92cfaf90d5ef7f56022ed3c28546f6520cd74770a4b0171e8cef96fd64bcbc51f955ede1e19237ad505588984246013e007381f96aed4707a4c32ed135d9f78abe76a6929ae11eeb37315612af3d592934df851d9c360aaec5db69696474457959d7380ee79910eb9780dc085ec44c6dfc086748115664b76b8a5cceacf135d0d4e3f3ec14cc40fd9f6c90ec1f6f437462708d75acd6015187e19d43e56ae750c5622b213879a92f6aa38d2c9fe6ce6eea576136b3ea573656f9e8eb8854878e8d4fd3847e85a0e12a1c5d86f695e5397e4eff603fb09705d8f6389c9937745adff209a6e838791a03c4ce9155e8ffa766c5521903924c18a137a92cb39c3d72250cda54689dd98c06e5a2160102d5aedbc8923c2105ce2fc853f9ef56249de6c7e612816fc54249b30b90df4e2ea4eeb9dec7b8a84f42e660562121ab6baad87032ed6e0d94cce5d4fdb61537950c2c91c20355f65aad9d47713c5e2509dcf7c8abd6b22afc70da4c759f06c28c4474c92f684a538496a0abc3ee5482b815259d3384ce6f74f76815e00ec78cdf9355ac6b0cd76045d25dfb8c1cd052e588090a99ea0180a3a41522ad6da7f0035ee618a5050dcb5a1e738ba1041b9e702d0b70e338888dd91c32204db0d62a3ed6a305ff37436911bec5ee0a7af911e5a212dbdf0b2430b79d8f1a346fd2988fd4bceec0778996717bcbf460ec80455aa549a9ad20e720f999bde48d0b4156c6b1e41d0d50a0839c2cccdf521400c5876e1175a2794a27fa0407a023c731ceffc9ee16753c0fe1967ccbd07e329b7cc11b9f05b652ce523a7b5593673df5eff9e43b9196454b01283cd6bc89d905b49035dcedeb708a4c184be56f2ac7d23b81838992b0d7dcc261316406bec40e383e00ecfef50514dd42a5aa90b5c5924633b0931325cbfe0c245909248069f5dfec6d03e45318a6acaed0575303ce2cc495b6ca8be0495d98ea973316c2742c2ae3622496a4534d48a6c0a79226baa6897e3567d6aba7ab39514e32b0b84d45dccc910756b74f5c32ddbc6dd62d325e0315ef530d234ca9b9c9d56b1611bc4166f51623da44f6f8e71bdaf90d382128f5a5841798c2ee79cd8c77c0267beb241a8fb7041edada7f1daa2b72f521606a6db4e0c480dc4c17a8f4c009eaa9c0397414120d06c9cc13f76e36303d9ee3abd6aa083382ce325c33f3e6aff13cd1086c91230159b84b7b78427c76339cf0c2c45a8d93187c699b75cd784791361d87562b2be049c9f46f8fbb7345d8e0b09c05d29726214212836a45cb7317e369f877aca6a55fc8274f367d57457e77e5b2380a96107fb9d7a83f183a321177defba4f9c62e2fa74349749fd4f61182730423c1e4943f5e18dec43e6fb816155d4bcd72ec56148194c48df61b9d07c117105b53379bf0e91adc6c1a312a96e227ef73f7c192e243255dd840d8624ae1a6af7dc1b9d7eba4f6e5eb7d70f0bec256e74dbe23268110819d3b7e4247e86e47afef11a6a9886210e3ef47627849095362246306cae7ca4be584d7e2470fb5354c25ff4c2b0b67e708c46be4bffbf4c0e08c3abf69733593f2009c3aa2da8af58c8d2f4628203e4275eed605a9fd976249008727cc05ae1f114a875fc82088987487c1a822c890cb52ae73e35eb83bbb70c15d102c3880283ce38173e813d3b92fdc71c0b35e9ab59c9b2fb659a5d5222aa0a404f5ca50652def27f48a0ad4adbf08785e921fee68b1c8c9cc41f575ba5525194097c16119004e4f326e9e017ae50e0c6e3f53a81f423fc9ca9e5f39af7063c08ae331962998e926833207487bc61640f602a93577dc1bc1db0347af7dc044c4fe0275a4b33b1aa4f44b7a569d55bbad32fdc2c160240ffe535d9df35c09fc1c630dc39984b8b462e54a71ce6af15f0fd11040fc9093d74a60f38a3dc93d02478fdd81e3b4ae7dec6d550fba5ba60067d8f7a269e1fbc2655e5bd1ee0ec5b8527c672f8661e5fb086742f66a1ec87c27a381a23ef87916ad03c1fe7a963aa826ffe1cd64c6e77f42169f7b693824a7f55afaf847519078f9647a97952e4f3dd465fce58d83fb5d864b3dc80350b464782209fd8d4f8aa5c6a30d725e6b2f7e653665c1f073b3cc280c4ac574605b3b4b885ef3632d015c8af9c25aaac2002bd2d1dbd1c25177314a56d759a42df3a64e43f12e5f98cde01deff5c3e131e69a41cb6165a12eb2438f76819db5521a003ad421ab0c00f8322cc0cd0867770e36c45490c4da10149aebf2ba2a9857997c5e5bcd2d3bf266bbaeee6bdafecae6e7c1113a88e7f884e97d8371ec2bcec6144724db9173ba1ae2823dfa1804ba543389468d0016974784d9572b67b985714a97b5af9366b8fc199027a942dea6b8b8beb6e7f5f74e6cc996e7e8cc8f8b1b974eb1449c451a4fa5d072a990a586fb0402c8e3b5c40f48d7b2bd59c33a594e541b2e6ac2ffd1554a2628371b3178d3708c0622befbbeb8826ad3ce5b1ad1aa858edc1b9283b14104d84b2890da4d1fc0c94e868bfd2b01d509a04c459e9f96941699abb48d62f00f8eb1ca4f0281f16acca9679906518def201d7778ec03e193b0a5bb535568443be11d514e8bc5d82ec41b5ac325318ec16596a31925bd9c96d246140e63bcd13e9596e144f914788f77f722d5a5ce0e47c880d8713a9cbeb260d9ae725ee07360917826c22cca0ac8d8ebedb816df248832f9fdacf3c265851ff3c170457eeec56b4aa976c2fde03ed42cbe1e3e4db569d8d549538e73f282b0dfcb0845d322d84f536dce42e913a9d4acc16fa9f808a83478b986fe8088703ea0c29d27a5d9919373551c161980e5ccb33d8e5b5dd9eae531400467cecd3d2a6dc212cfc834bd20a24710074f4edca60702912c7050fd6f73af153b557875bc5f7ed1b76c18b1bddb8f378b5a7d19bd827bb396a23b3835fc61cbfd7f4bfae304be48b421b9c3984ad5ee2bd24c87ce6f260f7a83a88e1845d2654f11fccbef4b8dea5f52a82ba09cc1fb6e898e1d431a69e8e0516587088c924206771a80e2bc29399ce7513e2bd83a367c5d5b3a9f72dfc6165d087bf722bfc509d59bf6ec2b72cf233ef5203f72ce9d9747b5e93319447922501bdd4dd24cb884a6415d3056c1d0073835f46f730c25a30aec3df271a59ac20db09190321262070ec21be543281f875223786fbddb3ee6509bb729694b0f0e48dbd642358a9334df90edff8339773f256809a58188eedac83e3c3eb67a605b6427166ce859ceb87e389bce1a678abdfe8e4bc033a8081219ca680ba68412d73f72206e541e506c4b7e8b174de83cf4f570b2034c19555216d0fc46a4e38ac08902b60011e854ea6fbfee3e31404d31cacb8cc2ab1cca2c851fedbbb1005dcc57251d86c5f8d3bbbeb7d9501655b1f307cbe1bca3fec7d136a57890f3dcc3b80da01e4aacde587b0bdf94fcec290b94ee068f7bb3be227720007a49b2fe5fa6f4fbf9ef6722aa769ed82f617002eafce1a61898c82697be1e588b7d12b62c40ada9c017633a4bf9c49b69e72f6b217c2d8c27fea73c61cf8a73c45802e061e8d8735bc436ef80a5a00d8fa061a1c6e943216e91529ab1a8992d4614108a6c9b9196bb41dca637f964866646c5a215f8fbe11e4735be845560dfd369a25f3c787703066a3612095c27a07243bf868e1f47a4acfa371d01ebcb49fa3ee23e9bbf089e563fb88f0891b7aeba5c37341085208a1826fad307187ea55b1475816850915ce62642c20805fdfdef5ce8886d3aed2d74fccc87651c46d73b6161256155efc4f5cb52141dda9071f10543427f5b51472238fd0885fec08157dc26b8be572ba65f307af72233dde578ced4f536fa3cb1dbfc25d73829837aeefeca009a0c6eba1c496fc3fa9f36acebae0ca88506055a3c53faface436ce02e1b57196bc961ee5a93450aaf978c647ee1df30c248fe76a651ed1d361aaea60f3de221c19fd5750df74c344f1dece9903e693d87cbd91b3034519a608e794e558c25a9100a421e756582a63b2e44d24707ae03170eb2614694ec80ddf9356e1ba3754c7b425232e6ba557dd426aa9d1c9551aa069af0f78c23599af01419769d983cbf86fcefb49a9ee348c1550b93f5ad35bdfc724b9f6c016a7f6824718bee34a74070fca8e5cdec864705f72f24356a92d1c7a17ce2ece947203d7180dab9107b853b4230a878abc10ae51031c65a658f08ee95f7ac6a3aaea5beb4d6e9c690a3428bb3bade02b3d5621b796e5465762976844ba83d1fefaed8ead5bb2ef3dafc969093538461d52541ff25396169fd2c35bb8cd444f288d13e4cc88a88b8d577ae1859f1dcbf6f2455872713e1d1cea184b4001f744bb8329c203b421c16e9a10c086ea952bdf66740b4f3035d11e20f2f38b537a4e744ba9b20235355e7a6314e26ed4ed5f7e5317a467b34abe04206d3e24936ed79e9ed26ae2f7bca84dc60d3dd66f94ccd2ac73cd60af2a3c812ece163680fc6ccacd11a1a24d7b3b0ce8969f85b8eca3fdfbea2bf5bad9ff61c594f787dbae8bc85c8eb0e7fe3b0f26bf441e98142ba46c5e3c6ca20502f95b89317feeeb4d331980bc37eabbc197492a92f1a4ee8309bc52e84fdf69481ea9a18fe606aa11ad40f7e2e0f7f312f747a36995a20f7c4649199635577ca785a432595cb77b365831ba1bcfd255dc613405f05c57a2dc94371804d9321580284b4f4e9b5ed859802c910ed5df0d101ee90e86657fe698f4bf7a9ea72ed0709963182e07acbc4e5344ec8dd04b91593f08286b2598ded5600f6b27e39c9384d704591ba843978f5aed77a6f5e3c8699717a28d33d4e93034371712b18d7b4ab0a223ed4b88b86ef5cd0f89f6344094a9ce15ce9301f663acafcee7211cd37d50a0f2d763aca11d823c33749c4f4ce95121013f93e893bdb0ae79d9e24afd7c3d09f1740c946472b2053b1e81ac3063cf1ad4336951e58f13249c57f751e6c5003871fabc7368fbd38a10a1bb2c71a286fcdd2f7eb23d57e2390179e9a3dcdaac03e4e7a262be041e6d270fa297626045c04fe7a79e4e4f2da8544be7f1da07fb22d22e0d7c0163399331042c81a58710b954a041c58740a9952aeba9c80f8e41f22b0bee066d017ad3207a6be0aeae46f444169fe59fb0b8b6bb3761f2b3776c0808d135460a6ed2cc18265d5f1c19c1aa76152105911ca08a98f78c6214ccded88b6ed0487e40e2be775333986ac8e1b6c72792aacdd99c69977750c733ea51bd52a0e791944516244cb15f35a06e2b4f003e1d0164ecc03590e730d3cb4db18296c22856f56bd12b10e2f260de5e858a4b951f6f45c7def8b14e8518a9de86a531041638dd5d033704c5a4d322b434044463041aa8510da11ac7b2befb72f9b9fe79b1a75d49962a28e4925891f8aa607942134f2f6a2ad4c39da0afb3ad103cc5c4ed319fb4dc607c7cbc072390d5f88955099ed144b1bc22c75c039116678d8a0ad7e20404e5a16864842435f79e4c8813117f06418b5f7b9fda28e54e33c70fc7741000ae0e0c874b1ce1d926f51941466a532dfedbd6dd079d0ab988150eea261f371eba400ecde43215042fcd112b7c8b4c6cc170c3c9714d336ccdb7a53e5fbf8b0278eab966dccbde384f837adf1acbe58674d4a0700508f14537c07affb519917526d426d3aa33303263d6fa7a74293701a337961691f9f3acfb9a78688f4b2e6080e5f01a92cc6cd182c13132804a931ec28909b7475e2091ef3f767b9c5dc4b7e67d89472e058918bd106299e03be0aed43cc8b79a369f602ba9a2d5fd96f4cc3409f69690785fd2b271aca0d26ac57e8ab32f4b81a4e3e29096bf060beef4f02ed82e3d9d526e0ffea7555be5474f106c2e58112f60cc40f5f6cd2f25476385161c6835c36da5be7b352cfef3d8084b7f58e6ff26ccc32ca3ca99969636e5d95d07e167ec72fe959d738659eb26b2176c40732e99a3768ef42e664f068a2c00976530787587a6b6727dfd53c235ac6e15bd41bd58bae129d93d68399481d2381bd82e82459d7ed4084648b8490b9a8afc52dc27c9edc04bc2a9924c9f5540eeb728a0a3d11c653a6eeaac6b609305d8e6e10b03c81a1e43d29390028c532a4b209e595af3437c1bb34e87c2b45eef2e641eb70eb87af95a7d3ee690a37aef233a0ef2dcd6456b048193d8744a8c5215d0a4a4b7cfc6f234ef54d0d6f681bbc14abc0b126aa836897af968bbca08a0a0e8c7fb7224bc42823b3372fd0eb5b785819c3fd9cb069ec9b1ed4ec1eee0d37b22938833a8d68e80944cef624f1344f99e6bb9f993ae2284bf64f72abc6811b08316d787065f5d1f19d33d3a07905bdecfd790cdc1146dc569dc9a87d89b3e87e35f33e1b1a57f73e53f57a5c06b772cacf806469c71d75923f073b12ce5ecd3c2c674bc08b6e6b1234a3f4d653eccbee0c54101995edc9541e0bd97b2901b35c7741817648990dae09b0ec4de6c205e5c9de2eaa7dbdbf481f758605c0c7e76ef003d8cf60bdafac11961e892ed6b371f4c5654747b9118fc8fcf35e025d4cb95e57a877f9d2867fd55caacd9852e919e4509158fcdcf3b1ae409083c5ab509544768465e4ea527e44f7f5890a366d4a77869087745b9b5201d8967dd4146d8aeab137bf699a636883f084f6f3c2e2c9a9c3c60407a8578e1f38c3b2002db176baaf4b1054532dd33a9bfcecfd3897a1342640db38b21cd9886b658faf0c896749cd275747d49481fe528a47e85f13dfe9f0a4441c8b2acf0d82d0d76fe5167f0e4a460d9107aed80990124b4504fdf8e49377541ba7b290537e2605f46ad695053b25a0634b3e4ca80d90723cea063700c0eea854f5bc2139c9f7d50034e95e91e7fa57d745385bd16dd6de31f10f3cd8ea759efbf3a03ef601049dbb9e579c1744b2e9173d0a51a7f6633de33a4553d3a78aa50dced99599f4f91d4836aa4ab8bd8d34f3f51bfcb442dfe0642cb3f6b0cdc15f9948bed2ed6f24fa0d9bf047eb995a536772e5f7c988682730d9adda4664bead2f0c6f7ba31a58af4ec0ed1b2562c573d8b1a1fbbef8e5a4570112e8c36262051e6d28d8e531662a7011f92534b441edebe82fa100b4dfd232a3e4e9ebdebc3bca749c2261a742feefd701e92713364d20b1831a6430e2d1841ac1b6d6aec48a5b5f174f2eebec202e18056d16b915fa78005198813a2cf851803dbe1067ef43a0861c8a087138a420dfb9174252cb867f3c239bd7800c209f95cacca11dce2267a494a37204f32f552f3d3022a5e9e9c7c33c5b1c962bc968d4d55fd15c36dd5264ec92b8b1c7a9f5bdbec61c86911c09c1cd48e3de82f8e6bee394332eb08add015b5e7145f7f28ce0d2b632ba2f5eadc5efbbbe6e2b322780053d6492cbfe82cd8ddcaa894d961012fb47969f0aa0793efa226e7e9c2e63dcf0623a2f90651a3796de73d9e8814d1ec70108f6a836f17532d98689f5a527f2c67e6fba6aa70cbb8accb9a2caefffc4f788539dd73fadf17b50c191084d61b09ffe39726666aa392802e2e4d92898fc34b718be0e9b969e8af888e8d61b939c183c14409ad46660f4e8336da155929ff931fe761b39440d38120cde8d9b7f5bc96cd1f20f26ab0e21aca3019cf938554a90aa6e0d67690774f2448f9dd7aae23e759945b189ed0764f943271a6d2cf7930d9eb39a10341c074ef722558b7eed3dab94d2a1efd7630b1f88e85cf19073e51f72322d3895961860d876ea649a6809135f2a37833c1d20dd3959bd887412de2f8750e18dd18d02d07373004eeb50b13f5242219960b933640900ab024809cd065200712bdd039a110c10370a5efe72f5cd027795e57cd33e4ecdc07d87e69401efbd6b5e3ef88906a556a37c1a34bdd41a6824ca0b8b445c23a3b253c7b0a6976c2c1447d3ef5029ed2aa048488681332ddb1e5f32cb451f3f14ebd1ffdcf9f4dc4c53f0ffb1cb3b98396ccbabd45f28d4f3c8db1b54593269cb43081a1559f020f0aa0d1cd7f0904f4523433dc40651505e235d4cacd9e19f5c80e70299020386969933bf7487b6c0c768de1fffea4b23b615ae39c525389fc5629137de2b1a78c2b9de1dfcaa70b9197d20c675364725560a23630d2659d2f14faa2a7620d08f52735f27b17e9a2058c6862f535d295cb0aa58db1b950a0398060673cf755faecd82e6536467f1d5de98eccec2088706f48a4ef8a106ae7225c16f4e0c72abd4a3b6918fc4c6d18b4aa611447c1db17b1cff023096d757a4c4dffab6b6c1bd7c9c5cbb5658fa71fd8a49342d421ec7e158dfd25d0efadd1a60efbf6a85bd4fa7db0079c3208cc72261195e89fa2cf76c679a4ddfb3d779bc7578971921bbaf0d6d7f783ef1854d4442d73411808bc95ee9391d88bd865f180bf3f20385a4b62408fd35d5af75d35fdbfef09b81a3159bc0e5b89edc42d94eaa4548c186feac75e641818690756e2b7ae67086ba34db0dfed68cba4f58c1eafe658464753aa1fc66e59958cc3f4f12bf55627a4e62aadb9941a40671a5e531069b5c2c0e279378c1e31cea1519302aa1bb913213c2b2fa3cef2499973fa3a8afca67457b31cd13b892e134d103a655b3f69fe504ee450064fff5a5bb6aab6ff3ca777789d08b3abf434dc453e58f6cbbbdcb60a2122f08edc76705b2af87500964f905497cfa18e76e669debbdb5279d5bc9474b9536d1b49ed3827abfcd0ac406f94a96bbef9aaaa04d669f0ef2bda5c664b7774948ec431f923a3585e676e7a4f5dae22ec0888e589adaf8e677a707d51b5743df0362069bb99735b5cdb32c2043ecaf73fb352234b3fa684a2a87f81eacd74558b0397ce861c8a62df7a85c9fbc532071cf4f74edf766d243081e42d0f44d175b21f2f41a670d248f26e7f201c247ebc3081f272dbd69c73f4b9c9ba1e78757caa187c0fa0ba9636b147c73ca9d0f666908aa616de2d76d51c35af490174e86f3842b2e08b8c1ac017d1916f642718b059184e936da505f83eb2664124a99fa37240c3903ae67cfbb47904d07e82d5d1e1086a8ab364d07e679468e6299cbff8527ddc2099d67ed1cc4586b7e99d2288116e978cc8c2b6512404e04db02cd2240db39641b176a732716a3f902464e5e36c2fa726a92736cb08cf5a85a98115c3e6e400de3f1626e5ec9c966faa664b72b1ae9d9c6aef6d52da149293557fc5094f0a4cb26fff84605119b5f26eb5201b1ea2109f706e749bfc8be2a8f8ec237891414575d21aab78218dc6bf204e82c910fb80e3ee42a0b64d0240bd7a0aa6fca2b58ba7d7b211894db3fe8f214c8b28d2518065acdc637f58b2ee72b8143e944205080f5d2bf4d02f0189184701721b75ad14d8fb3431ea2a3df8c1572d22d3c360904c57b0b29b2f80d11a47608c170a16770c165eb74131b3e6bef5b370f2a9fb57d0b5e481463711bfdab478cdc548e064edc4756c435ddce77536e3918e1620adea846852cecbfe01cd90c87ff2f0cf8e59e5e21b7d5ac290fe9deb9fef799e1dd799a71bf0b3fbdfa7071d8a0136ecd2ab22ac63bd2571c6181f068c53d4a5d2192784bf7476a18b882508ff3c69736b587528ff9166395f4355a412b34932f6acb4aefb5645f5a0869244aebb85c2b5645ea8e92b3a3ece29010f2cf24dca41fcdcac0fca2c6013c19577596883817fec75f5598f5d133612c9779eaa95d4334526661d0092ea519818d9414cede0ad47c5b548f0fe861743c914fa8e48a664ee5f8dbcbe18fa049135628965b4b746c8378c7dd4f2d53165553380af89e3a16b0b269948777a4f3b19434960232f3b73a9ad1e785fa1420da023500549630211682dc5454cbd1c7e1dc12eb58a4c9d7f40a3712cc3aae3acb893720426610248353168145a44cf8c2108238b899de5d1dae159e839477eca0b9abc65b3b30806e9d4ab194ccc7ca5484c36df18731bf41fcea148aeb3d8b53bcdcdfb0fc5188302b79dde62d6179e4ad813b67fa92a1d60a46e7ab91573dc468d5af2b77e62a5cf65a547dbce3fcadd6d6f8dfe1e3f8fc8751fdda1368486bab58070a778028737bff3938ef4131fa35a336c9e3cc4f17fbee0c9a531b3e126b2562f884c1b8a5dfdf8335bcdcb7146b5e657e83abbbefa49f453e05c5fefce50e531534757144b49106406190612b35210f4b97178e91272c3392410f233b99046419b8a2f1d764a005c5bd30ddf2142de7b588175edfe2ce778c90c3c8e19fb715231acc0fc4241d3295d652c7dd70554af423de8ad2e065c172b299586e9afa215a9ad3cf90b0a765ddbc73321404126ad0ec26a61d3a70a2dd7bbe8c3d6f220bf7a922cc3e1c82357924a19ffcc7f41e430bf414d912585d5465adf0e2f385f41c57ec7d5704bcb97317b80a51eb9743477f614655a253d3410d40c028e8caf20f53bb4a7303d69769cf47afcbf6a90b7467289bc6a60c6b36807891e6d60675417910b0cf125a938ba98b8c9c40807f13de1e9f18ed1fd0ae9091f48cc3d6275c8bb4eccc9f23bf1e700bff185f051d6809e10fc4f6cfa5428256271515b0cdd0687127c9eea0117139d9f001ded5796089b1e8e1664f6ae8d8d05048758439b869037a48b9520c9bf1dbfb5af1122dda170b68348302c8b2c98aa21708045a861e75d8f134f994e0adb11b8dc8313d39bc8715e179b30ac8b96767648681e7e89f9a54f81c5493fea3de340b1de09d4864aa0a80cbbb6561e0d8f1336af02a8d3a24f6fa1bfed53973460e9a6b66fddebe0da536e87b0b5c1212126ba3fc63b3da29541e8973cdc8b93121574ab38695b34feea18f89689154ca77286363ecfdadcaed57f7f216e84021620344df9479b389747ac642d7d2efbcb657bb0ed34fb73b4cbd56a9f15384b4b33f6a5ba74d4edfb0ff6f16d1b23c5fc63ed003619b10e37a201319bc49c67a3b2419e66b6d7e96e8c984f38f061e3864b71bbd2b1eab76bbe7e0db5015153680a6b6dbc71df57b7d47607df6f1bb29516e1c83640e3a682a460ee1c8e8de3da7cad1257532d8b7da5a59ce0fa1e38b1734d35a53b3087e0e9ba459d2e5836d3b715789d23dfc72285b36c9a052d0c1e8983affbc479c74e92aecbbb4dd85532d6e63c1a4f28f687e03512d347b0c1b2bba24931f3b4721aaa4e1fc7fa8196534d9d9d1237e778c83431a7617f567eec7d10b7be11b604332be04276528b7cef0c9df5d16f0bed9f56ab50957a954af38e84bb43ad0db134f64a5f9357e74d38f68180e0aba5cd2f781ed58705e55004b21ad85db3cb84533761bb5ffd0ea141774f2fe7118f4e7b2c5ed09b97fcff98efaf036355e47723c3fd26712dae06f30b77b89336c3f4cf7e309f062b9de7ca85bbd4ec6c7b59f90393b9296f0c58d3c113991412b6000e616eeed02a2ccf15eeba8916ef72e3f7ffb5c23cf55933b9f00773db9b36d3b9e23b66e00a1b8309003819829e8f8ee46a23c8699dda627570e119a61f938aaaa20df918e8a8f14ca97710d923668d5bea1ee29cc8d9d03107b7b6a624ad641e67673be8bf89b68293607b0631597df86aebc2db190787af29e2349b9ea1fc22e9bf5aecb73de77c07bc121f1d7e38270fcbb09247e9f41371d659e332b016c7f8d033530e0ca898763aa5943434bd845e0f0f70bae9b823235c75beac8c7aeca0b23bde5ed6f8ded5fe56bc33b8d34e0794601377afc8dd33e111aba0fe59773399ffdb347615abe1a3852bf6d43bcb819e60f5a2448592f776eae4e8e685c31e8e0bd1c8506a1c9a57dd22bf8ef471f4363700a4360bf2dd5760874b517726df3c214a060d08d3213fc8e138038d8997abbace22841d527af324ab480b648cc24069cf2847d69391ef7b08e081c8abc2ae5000160be0490ddaaa3910eada6db33f5a4733555d340063af4ffdd0d94d78fa572ed94b73d628e85f1d30d81839da49b810e88881d57e39b68bbb150c4e85cb99fb98b92d518130343d5994ed094ce48599f60c5a2b54452ef6bcf920dec8387c81fa90c3dc44523d39ca102a51969c13248a3d02cf38cdcdc74d488cf1fc41f15b78e1bbf1ca55771e89c8d4304f91ad659ba52b80660810cca66fad5b8402c4e493f0ac77a993ab4e15527435bf26c6db4312af8086445d04fd3cc7942143f9fd0458dfbc9f681cb2bc307e8b2bc110eb02c47817667ae443761c4a39f58fe7d1e37a76e8b110293b46511a9c21736a71058ddcc94da6a81fdaae8138dc5437db0d3550c0b881854fc14fea9d04d8324fe0ea21d2551266a2176cae7968633b7e459eb9a4ed52efddfbe77be46fc1a2f5f36232aa4c934413291b7fb23963e3ad876a8dc13b1bf0d0b31ca1d15f4c4c592e7b6c425bb88d11d2a83c4a8ad97835da122b66a145c5e556119468381e1115499a89d53fa4855aef8b11f438e2874d3664a555084eb9dd1adb71fe07279e2d773f31d59bfcad89ed46722f6eb911868bda4acfd8d3ce022fde01d35020ba2eb6f61019621e32547d1087d505ee18c1e175f6a7463849459bba90214cbd3e1f52b0106684d63338d8fc9416c87f260870580f50fcac5605cdde6753b8b7970b2579416e9578c7e6033344246b32514b48d32330a03d0574d96c6ae4cf87784acf9b235bde063e1042954b59bdb1d55dfbbb8b0a2b03b9efdf7ccb03bd37a3f9de9a4f05f7ef3f1d978e642bfcbaa5a5f99e5659ff9387f3b891db0c8b6d2990fb9ff5eac6f2d2b13a21c510784b7b7dac049be9f9da28c2c9a7ab7f2ebf91d1a14ed9147b037cbdd76c260fa4e2021726d02955546eb7824900848324f8012577a6503959b0c264c1c2bcfda1920f08e1fb4190ff57574f2f640fa5470a737f8839678a2c4bc9fe6e2ceeebb78d3fc0804ea19b75559f244992ac9e5daf8423df3537577867fa89d30b6be32e5bec042b28a6325269238accd377db4468a89fb01bff10962e639273ce74957e89d7169a3dbd09cb95eeab10f3ce1693bccb1113b3f50e34c7b7f3a6b9438582bcc98483c9120325c88a0198173cfc4be61d8d2ee443f65694814e55d101517783d04fa5fb57d5956650e16cc4c4e61313628a8150ab33469dd6dc5b8d744ce38e5413907d43d4585e57df2c353d72e5681e831e7e19ab30e95a2b4ab8e9ad5e7f6eaa582a4a4d2d8e42a5a7e15205129f7f302f8dc49ee11c228604ad7c02bf4da04e24aa1d0984eec9ca671190e5c312ba90baec2fc3dd7a1c9f9e5ecc278f659760ed090b2953b79aac407694f5114080d5d6fabd7d0248614af2ae1f94b458a382ad41455689b861d3a96f149df13e6e83b3d95a223dbda4353e135ff67b0994a55996bd46618627b20ea2f08387623daade1fe933bfdd2fc5980dbb69d7cf28fb73586d23ec2fed3c2f6657e4e5355bd3367d3bf8a1c9afe8927cc67c1235f44886b08b2ef5d7c1ff5c1235d793ac39c8c632371b65eef00774105e205024e53bbe2e3ab96a59e2bcbb7a40acb660d3eb325261f3489b9adc2561ee1a57f1e38be41e23a858d1b0cbfb77ac8820280d56f655bff5c3f18f9815dcbedd94c9a883570288387ba8d182f5e44a136eb8fb4153f829ee96bb1e38749d4c205220dc2fa0e3b9db420466d66238749d483d0c087fcb11e6790c85d719addeb402eb5d64dcb3bb72d84e6b5c055804ebe2883a053ef893d0dd48e80456fe87ac91b7539761a3e776537b143312714af45e59389b0bb6f47049ccc4d501e0d3482fd43e0b0b9e6f582997df401f33b4a7720ef0af1a9c50534b0a3f7a85b0aa3cb07f5c8faf540621f079de33e10c2f7ceedd19d157065b13947d76c7750cb9cc956f922119a37679430711d69212d33c1499f135b388dcd70cc924d4602dde56d0c1d764f53217b6079b7a3592b547760e0cc869ec16440486f5533659aa48d1736bd61da4d86888998e9fd0ee58aa3ff6779538cf56da95572e73da75498a42b29e140b4924d95ea7909411f5e49e20de0c63ec360f7da5f9753ca3c721c2e8c9df2ea09735c91b068d5f5f5cd6c8ed131ca09853b14f3f8b9952247d100b94d210e16751b3d75f992672586c9e7b7677b496b8580a75ba76f5bd2c93f5e6bf189c2e9c7c5d05b5c58f0a244c77c6695ad0169d75475e9b60ae96464bf5f7e9246a1faa7c777043c23ad6835a5398ec14089cf297ece9021d515e39b45302a8af4d5a3e77e108ab43d37ab850a0147ba979a27aa77962a229b3af99833735104852794dd0c12b04194355402acd4dadc5cafd4bc13d694140b077fbf973239d3e38b24c842530d2cde2fe8557ba7768d3cf62564bf5f1569d2f6d336243786732b198046930f54fb7d977179e9d26a2c48daa84dc4437a43bf8639e21ae23002d2cfdda3b77906c428df89bcad210a3f40588e6cee43e716c7105ac6473688576b49b837c73937dcc3c098b5a4374fdf5a46bcbea636c8c0f2c17e69b96821ff4f8cc7399477b81aade51f00f2f83aeadaa1e56a5f5e7c7d5fd71642c11879dfeefbccd867214fc0bfa8872fb6b4352990117e73ef5c5cce77bc00b77efcc347078f96dce0bf8f7f3b717c951bfe69dc918b81da2a1801b07933982bbc1a6c51502bb9742dadf71a6efaceee632c63a0a7064055550a422114b3445d20304eb6b71d5a251d1c47ae4f594ba35b74bb6cf23ef47d2ba1068fc66b6f8c691502586bfd5533d231a3201d5b07a297637a4941495e1a086e1ba2f16774ae28ac4ceeae9cd9b46d7d281a76dd66ba1bfcb6c8fd8df58564ce9319d42c5ad9c078a71f021d2f201df2cf2f5dd059b6d69930388eeac8b073dfcd9a28ea52c1bdaf3a4b34063dff797cc87e0f9e5e2cdd709a3996c61895db60430062b35f8c757f128e564935a0a0b91a78b57a83362fbd8203732d78164e1286bb50f2b2203aa441160e0a898832c8deaf942c51677ae52119571662eedd0d7ec0f68f645a682d2aba61cfde397939ba3e2450464f4a395c8a4eae99cac52c12482c7bb7e8cc1d897c7a1e1c9c69da98ad5678d1317098eb58f88ace608723f159903933879493bc9f1b7fbb6d05f236750f7ed10fba4e2a0da41dd2c7ded8cddad32b4f53fe922b8f88c92ed0762790451ae7d3bbe5cd23b5d784e08df90f6b2a6f6fcd6c2483d908fdc268ca750988f807775443f677e351bc07bc3f46b6705aef713bf8d174c7d368115b09fd54ddc44dfcf2feebcc786ca82b074aa340e0e602184d48eb0609573b16777757e804c5b9bea638f78f730bbf0bf903e7a01fa4bbddbfe435c76a3ece10554a197cab4d311ff3ea695325554f13f2bef119503accb2f46234139749ec3a6da50988a879fe783308409b1764a31f858b976f6b161e7f803a9295e955895b3100804a487029fe86b3c408614ddb5495f4a0ebaa9271cc4b00b275e60194d9d00969983fbf01f0a95654fc8ac522fdc95ebb1c2ae9711ee0b9f51a62523029bfe40c0d0751cd089c7a2da9c728ed9fe956bc56b632aebc84b691cc334e33fb42278b9309fa1bf51356b86fca56cb017a53c3a087fdc8f6f17c6f3f583a2cab6d923dda232379afe209b2c698d459f679b5a0e9bcae0ec6139db76022a1f7d10fdf6981c26bba1da2c6c9c1e60e747350bb2e36da2a9eb61d59b869a818c94d6446d2549852ade55b16d7cbb10545e6f42b36b5bed60786fc5f3b4ead59a3d012089101801c7b43da61f535e8d34fc4c101978f1a377bd6ba32c8f536a38b13cb773281b03b0d52e09ab0147481ff7802f624998d1168f7d52e8fc2997ac250bcd6fcb17e117db792c77f28b788883da8e4e96c6ff2e3d87fe1a4abb1f3c93b92d90f966537be0c69cfaed6d82b11244e76310ddc12017a103805bf98c627e0ac98f968aae1a758dd6da4ecfe6bd89ee01d7cb81a3dd65a64f7b50fe98ca112ed57147ef1b5e57565906a94ee2866b56c72299d37d6bae7ac5eabbde165e4c2c57962c835fb5ff53f6bafe7065e5391f944115e014d9bdf6b1019b3f37861f0075204e46e72dcea403fb0767ef4d43ecdea19a228542a81a3646e15706b0313c61f743a81536fc5fd2c4c224ec6dfe500774254bc9cab211854f54774c46dc442afb9083f4fd6505441389c2a9b9be9226d964f15009f1a27aa0337a7fd03417618a9b9a29b90f806cc31c8bee0d588568adad7b84657ae2b0c26d27ece234fdc7f57bd7f5832a3897df1b5d65eecb68dd3d61c566e04e33d72c1b9a92207b44cb32ddbbfe8bf9477609a9729a65ad5667ad2cf25ca79328af42c56b4853ccb72441aec137cb7a6f37d268d779b552ca9c6060670f57f2e13dfcef92b179a10f279b75f75c5af5bae605564e7e53628e8711db01c3f258e7d8e6639cd7b6aaa77219e49fd8a9b013d98125410c12a521242a4e516364af075657db18c0fb797a8cf4cf92da13eb71117b67d7a354ad0c361802307fc5a0ef08e5b3731c1932b105cb46f7ef84bcfd52a08ac474bb1f90588a237e3ce982abd8b76c18cb9135feb744416c2d17fc906653dc09405ac1856ddaa91086b1d9598d40f42c644630923283858f671bd707076a2d825b4f71991cb3549991858e71d52dad4e7395ea417459c2dd3ad1b68263eb4e494bfb39e8ddf0e31cf89a489639b4770b88659599745aeb45795ea011830bbf71a0138ae525d05a10f5f3026ae6f8d5bfe71e1140d810ecbe02bc8d10bb9128a125310320f2e48acb8560291e5d22b47bde54bc37c9ea521a59d6256edd6ed66007822ec7eeab2c32b9a4dbddba6c608b62e7c32a32f127beb88a99441fcb1744e104e4e9f699c4eafec16e0e45b72256fc96a729cf2e22df599bb7486c3c158e799faef87f47a328ee5979542c988599d89cb2c8387322d428fba3dd68bf03d4c5b24d7a017437a301e0c1583dfaa9310e0f6f49b6cf310537d4087579aec6375af2b03699fccd62da5a1aae778ea68ffdefef2aa2ad13dfc5b55d3294ec9847656a8c42665261925abe3796b6011e583cc277cf9162b8ac48eb8fcca2b4dd4ed49c4f7cdc4d178f886afb5bb7fdf97fc1b3b24342b3c3f828c4f6d7aca7a29993fd90a36a2e6eacb751fbe9dc8dd3d793792b5a6d29d76cb6cff85f85f31a717f9715b909675e4d4699d25d20c5e71cf4a8e61419e7f230ca099b15791a4c6609dc92770260e2d698fc82bfbc4c49ee8c0e93ef3df4674bd2a7a3c8b856e01e57c26ea0b89745d79b5c92b0619f3e3dd98944526ddcdaa620f94a9a95f680720c0039f8befbbdca2772c3dcf720d7b67274fb6e41f64f97738af55ce71e6f6be5cb16da9d788a8cc51f30ef544705a479fbd39fa1a5a95f5ef97b31dce39a7732dc774626e3d7c5f2be82e08e5bbd2a7301d96f91badc83b4321c856414645f43bc67a72e65cfe306899942159066f6c8cc3f22898b201daa093d98282532ccbbe46f6b60a52e5e4e37f491a1345ce999590327e90c2c90f08014bce632c7b374a9e2520ae558bc5234fb1efef7e97d4f9829c2e5b1e48449b1dc56b74dcde46d77e3efa63f4e50614ef34a1d33c54086c6f8659feb5389a29a1516d0d6c9482a43d5914901704b07be18f644872efc18ea48d5e8940ac4ea67d22caa81a90965dc91b87789013e2c111c8def58f0978557434d3f95ea9f238747012693d7a0f92458b68284108c974d1227c7ea9b20f4b9392e8bd50875f2eb30de774f2a1c76186bb45b458fc99814bcfe0811368d78845f90f21f442cd64032be575b72210c6e9d806ec0630840aea039a1f9b64bd0a134300665c67e858b917c9d1e7365da665ab4a75f30949de861bd7f57d2eaf619807fb30c3902a3e5f316d95a5f3ab7cf1fa47e080d8417ca5334b312da6aa2fd9618c95e6f1cf45a3bc177b3c1c5370d9e80f1ee71925cdc336eca07c861f61ee40d03a5f98f1335e7da6352d1ff1fb7d11b7bd50234061bf86dbc8e24500cfe488a6da31ec8dfa63dc2dfd98fee0083fc58ba966788ec81ea7c50c36d57a9d23dd6a4bbd9b72dd5f3246301a51dce9dd8ce6c574f1a12dcfb6f747e075a3eb6a4f11af2077fedf70df0fe690416046e4ad61075ba02f9750e728ca963cbdf5445245d7b965bb55b01b227fbc804c88a19169b07328573f0d83c0bdfc266868ab37ae5e03a9bedb6bcf31b58d7aaffe00cbf8c3b747805eea411bcc3e5151078bb8e02bf8a3777245545fa6ebfa5e64e7abbc8c8ccc9a3f4442f9d4ce3b0c82dc21cf823a4f1c58806993a7480d61e94b71091be4c78a48d1dd3e91dba6ef012f47bed94e3ca0ec4b3d316cf4106d49c4404c628b2eef17e0ffd978f7c459b5518f7211b9bee5f1099786ae05af033eafc3334e8efb3804404bb9c58fb29aef03d3b185d94263919522afb1497c23e838e2b4438b1e837a67a09bb57869c39695ba9dc6ff325542c908c11bfc2c1aab3ee1b4e9de0e6fe77534404aeccd7b2c2afc3300f9bf1d6c838102eb0a254c63656c3f256e2011f2d55a2b7d9121c9b9b61a2f973cb4f577996e65040dc3e908c84209ec356803500768605f9ebd9e151f6cabb8673a8b5793237ee2c7b17671b743d7bba0e3ecd5f59f92c53f09457a405f77bae0cd74a22e296bb973667c451feece59279c5273c05cf037a74d39bc2b8e668be7aa4380019aec6142de5f83ffceda5d3c60a43700e46a950108b2dc51f6c5dff83af603a049ae71527f49a39e644f8e09371bfede37e2bc692e3f892cb067b52c797c562adf4a0ee728bd2a0097c163a54624e51ef0ca6379cf5ad9117d5cc9efa1389d0bb43a82aee83d26eb5352ca67f6efabbd6e28a6faf620bbba401726845fcf62dd20082534541d4a568f23628af6ca106d9c45f2a966cf2d8217a3c538738fd4a9ee40758ddbb421b17b2f6c23b0f5de3ac9a5527175650ecbb173ad9a5c703457397f5c28d9b2037fce4688a27a849e06b61ef7ea4ae6dc5756dd13604f3b9010602b95c3cc9f691ab5656d458dfe312c405c09a014eeccdee59254a5370f6aeaba27ad3c8b78f12bb6632177243a0df2153f0b80c1e3f9f1bb92f88fd11180815492205365ea952001fcfaf89299d0d47ec81b7839413614961098ee7785381c0e4a1f27e5c9acbe0361649d482ddbe56b94582d73c26f409fc08e83b8ee993922d8ffd5e3eda4bfd8f6a1fa6f67a106d02a0dae4a2ac64209c8c16c0204879811cc18cdd4800f25573560b084b9f4c3307e1dce9dbe53f0d1948ec7285fe7901a582e7ed35f78fa201eaa638ba0062341e457c2fa4ff3afcf6c6d079f504d61df1b300558b3556d8db5b2152c2ecb8701db047a854e0524fbf9b2ebc58395324105ac48468ccfc5cec26f656404e8e542ce0519580e64a656636fd02732c09c38f64217deea0695b2f9080a9c385b40b29de1b591e265318b3213da2a8bf8a531a16ed07b78c0267f9b6674504b6469bfc07c1562a8e4498a9d9dd5aede3ce05feae585aefa06c7ef820b276543df66a3c11283141788914895b114e0d687b49bd2dace28893499dd7b722dbd36bd59a6b8be31b19e256e13cca2db7bdbede6426e7bc93d8222f1b28b20088a35c8ff9fced616429d0ad16f99e0da18317a07f347e2308320fe3a40e49de454b684d9a5137a603ee73aa0deb56407a1b4b3f532957b2c3f23d342decb63f4e9382bdb01b8cb8f20c355f52d0b5e030e971d2bf91c5e7688011e47c0ee17a633da2bf313f60619664c52fe616aeb55e5d08252f1c4508d24e6ec7a58fbcfe4d1bbeeb6dd399d3d0c7c6eaa1b1ea2db68630cb3052fe0f064f2a72e7b3d7e14a9c24f84819697b8a5383941af6413c199be9ea6be18d8c0e8cc9bb12d21de94827015807b66304e76c5778b87bb6b7d26858adb580054a0aa275452c0c7d3f539a1b9ccefbbadedda36aca575530879e45026a5ab87120d84aced2cf8d4363246fdfd844fdd7e1c41b37a824e983a4d996aa12848c5fb235b1be649bba07f463d2815c38dd0653bb34af0e489c20b54303341471fdeaf87572906dbaf0cd0c9f1d1b1e84dd009fa8cf74c8e5af6f1fcaf75c528f4210d6366262581e76b90a2f2543256261409d256a68e69605e34602a099137c0a7954803b148dadc71bec863002e0603251177515d6eb39b07978e28d47aabc78fc486d76c1008d8361152ebba141cd606b0c880599e12e103fd59ec8a7d39fa24c129b507a03f43daa9383753fa26e4f72443e58954c3a9ccae5926aef9a73a2ea2873bbd52de53bc98a8b170213376e69a5811382f8205dd96b7343ea2c75046c5dbde21553b171150da0c0fa7a2e0addc1a0d8b6e61de8584e1d31b73e9b98ff078c3db597cba5257f75308af7e4d30949b7f95f4bbead236f2dd11a84e617ca55f74eb19063387309429389c45857a7a7b808b20af843143fd22707176de7452ad1c10144a42ae4264a2f8733888e496fd04b5dadd1f08af65ec01eeb658f40b93988bf7ee083c137b1d4125a7589fdfc1fc5458105e955a926b9d2f8d7b631ad9b7e5785cf07472598078f2d25684e307935328aa1f3eda48247b491413d29bb700fd82216680ee1aac03bc5ff8ed4a775c826fbc425c39689168c9f1091aed5266375cde9002991ea85c225fef343ab02a3745702fbbe569d1a5f5d0847e7a13ef720a20e8fcebc3d8373db02792bd362042f8606b6cd0ff9c3a9ba7e9ee9b8b0189b595b18b37db077e5b51c0772d41ac670831a52de5752418aa887adf8d6766b837c93a99d0e759c5922974cd0dbbccb05e0ed067f8618e0b767a833704b7efd08531037fa455b15e591c9d274e2e3416bb8bf23942b7de4838298fb245b5408fdf910923fecc4774caf7002953d812273445238128653e016130e55a9fbab911ec7fa64b7ee43c8ceba97ce3eec94df73e58cae0028bf3b46d89c86edb882f88bbc89cb261b650e4e78ef2c237f5fb6e00ca4a4d20507a171f6053d28dc54989df719a17f3ed2d3b43172b5e4027148a817fa5cfd3d0b160a24c9a1e46f30df3d7780dbb30fd25d4951672f56aa5cce8ebdcbd884075f99f81ea63dbac7e1aca8fca605eb343fd375582463c5483bf33ce283fc171c15d6d5f68975cd44c51758318377cd5ca10a60b97953d80287001a4bd83da3c18723d76a9fffd73c8d8ddb942720ecf4f8d8adb28dcd23ff6ab87a7f4ce4fa471ea8ec1968e9d3ce9b56a9545b25200e841929127c1fe08a0adabf8b2db1249fe3843bd71cb584f4d9e9825108ae538a1c5888c85283af6e1bafbf7f3f1fb844871cb0ed03bd43de331540e895177088be576822f963bd88e9c72bd213a82bb08071ac7b57bbc9ffefe0aa14b890f35d740fb02bb2395fb1ba9fabd279a1ff9d764bb1cc523030c5f24718755ce495b61e8efad800f2609a55a476d06ddc6f22e4e40ca1adc47d3f0af86ff0252afc5566c246ac6eb59ac1345dc97e03f604e397325147f0562ef1a7f0fcdce299e46e7b1b3c8548bc1599ff85cd655139599abefaebd4f63486083eb93766bdd52a2e5be9e7c29756143ad238d5cdc6d9289dbe5a54021fe8311815752f8fbc772736a82d4b5197ee12f51cf7342a5a6ef924abab65f55c56ce471c6ec5ae145df7b7c7b2201688207b4a376ae7cd011cefbfec35f1ed387e745d39e8519c610dd43cb99838fe9bdcc6e22cc411f45bc02c70a8ab37e9e179cd856180849729360ad774a164c0d76a44f1684600191838a77e2beb31dbeb92c099959574d2b44490aad4f8afb28b9e07fa4bc71a3b9e350126ca1419219453c8f1357ce0ef58c163f819108f98440439a8fb0de9ad7428f83814606d072b177f39fe660a189e19029723e56aac130e736838ed4d79654993b8e8f0188383d6b4b1bde5a578e52640f6300f31da45105e9bf0fa300e6153b808afc22d40590158ffa66e60c2b26572e53205a9d0e029a67be69ba7018ff151317b9c8964f4055409b1118eee20be8f565e6d453cfbd795bee409fba4ba290c21c4da0c83f27c714f68ed8278c95d58027a8ab9c15f4e60fe7cdf8b8a67d0e8ffee3872764534d401366d8e5a6f8ef2b8ec764231042220eec2418730ed9b0b2d57edadd4f1c968c227c9e01d0b0ee6903b306c91a8668fa7deb62949832a31e5dd46486986be98a55ababc5c5b08ecbc0b5b05bdbb06d7bb0963448dbb632c5f427a437634be6dd6d4481577d004ad297323af7a2c5c9ff154d6d37d891f724f0ffad64b68f0b8d9d60ca5a56e366f979b8c3e13eccee2138ef2d93999cbcc60a91b980ba00ce90f563fc458602b6494eae782f81c3f824ddf54fa74f8e9ed726ff79a91158aebb0ba58698e5a19aa887754691bebc677d26caf6ac37decf623612409dad510bac203406cd9cb3788aeaddf6d81f56dcb18356d88f208f63e9b474855d7364604b6d5a35f78320d26498f409ef30df1106e265c97492353d6672258f100e23b48417d6d1f022cd355e0124485bca03eb6713750bd85f6687f3f1e6f1f20f56b4419fc3b3288debaca9c6ad8a0bf819506e29b62be3bb8050fd36a2dea0aadbd6c96137bc9afe7ff620f687e2367dd23a54c8e773da199790c2a4d0eb198762dec1b0408aef17297e77e4f21c4c89e5648d5a11ef4765f93e1b5bcac7b965088eb9c99c048e4920a5b159eb684047f8761192e52ee456355846f65f8722cd517acfcdb4eebb9c5e70e6e3c1d370b724955361feb326a1430fefc5c8ea30f8b54b3e9cc544d747cb200079242903fc9e6002e3d626351d1c20e8d82b39892605230ca0caeea875263fe74d925f2ac5703789c808bb6e7fdae788df94923558c7e9b86fd0764314a43b9d41078e001c163418321365841ca70cb61369991dab50b4847d20275a9c29b896a789944eab559affa6a442c6fa095dba543811759af6b44090e0a0c9f04c48d5a271a9177061494d727119e5166b98b9a461f425eee28e29d32ea41dfaa565f48bc4d2ea51b9d853398fd2676d3ff3a48318d01acd7e1312cc663daf211cea6a974fd2b147e110c892d2da25dced81c2fd901a2f39d7db15043e6c11ade76943856b042d397d1589bbb50c889638bc273b1e33f9100dbf83aafd56df915e27e7e3d781b4605d50667ad1606f0bc2f96faeeae7cffe4c49efc90cb2e74a50a541339b7ee5f7236b12a8eec0c2479bf8428939fad57dcec2648551d55f2588c98f3875b3c9a89ab807aef5814f945ae3a151ad55435162bb4ca3e250b43734685b72d625d349cd8d7f1e2fb04f93a7ab9aefb1df98308ae4cacf6347a6f1984356697244aa03fda773a6ea2add1c48e8f333af5b14eb57c88a44749be342499ab56e096e15cf8b1f8c4b1b038c12582c7326b45adca5d824775c591c4eb8abc951abb9ff0c9d5458bc35580e7803f30c735b3df3f1112906114c7cd90baa84a280154d5ee09c592052269ed6a1c5ff858b94bd69c0cd48fd8e6f1260398e679fc0b7a7634480caf19a371b50ae76b1c75155324a7a2a158420e830ef1ca82af09968c6e3d071724c68c8d8caf90f0d58e47933f6d5686f5f0308babdd594bbd898cb19a34ad9aca6ac8f5f4e6940fbec754ae1027b7b47086691ccfbbf98b7eb8d4c07a24f7c6782f18368cdfadf56e1ce404a6a6fdac208e13a7bf17ab762a8c9489ddc5851311ec164db782674fa6260e813927fceba8717666dca0022e84a670c59356bad7edb0f3e06484a93d330784a52b5480d107289571e1801fc5a171fb67f5e12bedad61182b03ee7c7532bf5109bea4f1b9d5eeb4d0661a61b58cadd27e9cfe5fee803ecaaf55cf40f91d582a018115bdccfe25d1f9b0ceb39bed6275f3036fc1c4beac5de955f1584ec1a4d91ee76fe9fccab4bd2d3416a4788cf51cdc7abf5d2c7977fa6cf32a43f0075f56fad51724eab8edcbf406a2841f9831e80e4badddc0ea1a83e8058174a1d0c41428890f5cd9e37bdaa38775146448e0b6dacd5c422a53e2e12a5ada31d70738bfc4ecfb6c1d6226b1fb1a0b910e863d0dd3f61dabbc6434ee8466e39c259b25b802d47bbbd57f9526abc7568405a04833c871a207d5ccdaab62468d5f7d21e1b86fd291cb463fb1c8c6b1d4148e6fc1f9ca32bdf4537ae593581594f4466f57dc4eb90291aa9c35de7ac4f5c1735cbf6159fd4eed5244e67242fa50225cb0a97c7379f1a9ed4e68c1c15127809d56edad1b7e93fb98c87a9d5c68148b1941321d16f287d7c101e3952f81b65907aa914c3e296b4e14f167a0288d8cfebb9c96844fb93c6c15b32c92a70d3f1932834811e3e1ca3921ae7bad50d77d3be9368892a112219e2d2bfff383abf20b4fef88bf8a3b64f7222d3d15361d99e6782444a50fcf4f9bdf476b74041c4485911ffad2cfc8cb5343a49ee192b18f2a4a7a09b9721e028c6e0b75a264a7ca5d9239b67924a72137d3e8d2770aa1f30583a66b69e72ac0f5a3a14f9e4bad9784f0ecf1c0475417d01881302def07aaecc19eda7ed19e25deefc837426f056b38cb6bd4d41c274a7cfc66211cc9f8ed1e9592427d8ef56ccba57532407504cfa818fdbc41f41acb5db4cb8532811a0d5976ab8c61785bc4637688c0115bc2a0a9adb42e6b4b948bdf726486dbe914b84281e1a6792625f923b153f443974cfc40d40112f0a30a8d22c402ae7fcf7cf6f8fee729cf35eddddb3a9245f36fa44c713a32a4d9759d472e1ead3077e09600ccac8b0b4c34c6031ce4804699ad4c3edfb8cef594fe9c086d69204873b730f772bbbb80fa52e3e971352e25d02cf15538f01d700f39448d8dd7cbf6aa14d0859288e99f5815cbdc3227882dbfa038b6254bd04191663b4a0ab20964bd14b3047acef9023025ff63b69bbea2b91bd35472b5c021f2479d4c459aa4a3915091309bdf43fff856229c202269013334ebede2430c3ddbdd3a26e222a8a248293a3580d5eef4477d76181ca02501f3ea3583aa77e2ebd8bdfdbab61cd9be72dbf80db771e133e28b5b5f9ef0d3d411b8b7155535950775f7330e4ad40a183e3c6cfb1b39537b422fbe54da396ad7ccc43ece538246ed7260481c0b61ea83e9bf7b6a1682ae9f0a50b1c71df41b2bf61058cc27eb837e696dd1726c4c29533fc0040ab91c1587338cbc445019dfc3cb39659273c5fa28795a4470b567fd2ad244e97f4db73bae43297cc8027ed2d60bebc9ac99a95cdf858ad2c22bb329fcbb6857b7d2b3ea26d0c0ea1cdcceab44a6825f75032821b8f5d0401f902f0ed7d2ecf369058f4e227660e02b0ec7c5a25d22b5a10d94ccd1fb619534d4b72d421ae42ed092ee010d031c6121fe05fb15a72d99cb8b12025026842fb9c742420963d58abd4f92dcb25c1738dc61e55892ad29ca29fff989b0ef24c4ca0b722a8518621ae8b31b0f765a6252a58c78d7443148ea18740defadfee408426cf604936ceb0f1272d4c2127098a196d5d64d6e83eba49c73776cbadb1f73eda0e27f6df6e43b19c37ea624ebadd386da48b409da170394b97761cb0680cf37a6ca89654c590e12ab51562e95cc2f713a06d08a34f748fc2a9b53e17307693203325da80f855f4cfaa74b32e1204476b3e8dfd89e4aaeea815a4e36fbd5bb5cef6eaa619c6a9b8702d15a963d89dfa9304e990d001f815c00b48be68898a41fbeaeac5e5572a232ba2031cafe8ec779f275b25ee0283c5b74a812ba86f920f7a1193b01c903075b5b24bac874cb903b81fa177727310af2bf1d54b377d94883af5b7052832ca9e28417fa3d890ff2e2c02f1b24432af63096728c6a0259509c4d60a345015b1e9a21ed5b6ca87e76a725472e8b7391f2740f16ccbe36f133e8b59f3d76f4d8e4ff3bda6fc2f381a131fedaa7c3c488e3863657ff502e462d2bcbe45135a779d79007d98ea606b9951bdb01827e7c7010d8716f6e077f79f5fdba287f2a25e5e8dcd072496ee8882333c61eb6f98393c65246b66c93ce008d84029362b88def6967c924b521741f81a2a9d0454007ed952157464d2d94844d4a0faa4c9da9a451e78e3eeea96200edfac8fd28bccfaab01c09de138b7fd849acbf4b6b67c52e66f7eedb8d7b83785b61184c5df0e940ae643dd8bc34568c006aa847d60dbf1eb21aa773f7854003f4b37e2646c612bf878e1f92b72b4d1d734de6cd50c9965f51e83001779b0cb5c0f76c74ca94612b49786a0889766d12a40f6ac54090a65e82d410f6acc112fe7499f2118bb76dc6c2682133b7b751eef0351f09e1a061f700a100ad24fc0bc240f6dc70546e3dee94a8c07bef911f5cc9dc36794e7bc80792df99b0ef62ebb2bc4ca6e96c37ef2292973d224df6d58ad1e4260242d7fcf358e1d6cb6decfac25b2a31b166dff4d73d5f353e27f428ca029f26b8a8c149d3670637844f6229e305d19792f5a6f88d3af20b5e9ddb5bfbb8baa58d93cf7e17ca7a6c6f048695da0bba8075e2b04707ef2dc7a1d9ad0ea26b8e4695e6cfeab21e7c1b5d64db93a3284b7c082cbf1a7e536ee3961265b0da102585d4de4182b5e3c874e3fb19e7bf7a28161e29f5e0942f63960b024095a18b6f1bb57e59f5e485718b8eca7df0f5a207949590c568cce4a333aa4580c4f6613895cead346fbe34a676b7223d2214362383343004737c225ec03918a4e2fa0befcfa23955fc88448bd605aeee54a58e089ef8d2308b4e3fd049a0ff48f5a0563fc3b6d1771d51fd524dec32eca51e1eb34362e91dc6bf8015c6c36fbc1c4101a2a861137f3298c3bff1991b1c0600503328c9bbceb7e9280da57f94a9896eb3413b42c414f5c78897ebe255fb5767224a0b7eb2f6b9632c13d1872108d3efa38d9cb082f7493a27c87165e6dcec700f813a4da7b71206d7e6b27def26ef456acdac6345dddcaf497d04401d080f2c190acef4fccfcb3a87ab6bc7965be9ea268227d4098536ed28d0c5e9e08d056ba8741e472a6a912779144cc71c0248b4ac9249f229a0fcc1254e0b671f747957a647e2b0095f4e1a705ff15cbada1ad5bdb8fedc64d8a9f81b87d16823bf0526146b8662d628b402b4343a8e502eb09b6438ec9628fac0fcc7faff5aaf2adb6f38e129b066d7b9b495f93a38927f5b0e4ada39fcdfc630e6f6f7894302d84c5894d5193c46f3485d18d81b9d5136d17d4407e660c99ddee5a30b5383fedf2e2a54ac8856de7f7f01b99d73b7b65bba210ec65848717ac99c83402898bae322d5bcbc51cc98e0eb84f02c6045a5c29b601fb3159f70ad957286ed9aa207f67f74cb52fbac1b288b66c56400b137c8d0e0347f7004ec901b621a6240bb37e47f105d784a9eda9f50f20397f287f3952e925790edfd82cb613607c96b1327f3e390dc7acbb696b57f1925ff595507fa7ef44f1d27db188c30cc0aeff1bf32eb17b5e6194a36e977424e49b4c78ba8595b72010c612c9c651d52093ae72feaf1a8b70234548fc96403e455ce03ef24f5941f004a745a00c100ad5a3582291c97a53e3014727df5763364e71890eee52fb6b02b9ff0bde4549031a5ec5175bb7e292f1b95897a6a856f7beba1fd0944b4fb334f518b7ff4313f81c90fdf7bb0dfffdf0b5d032c6d547d8e7745576b03e1e68e98d4ff209731875e84b1e2723e27fd514da09deb0e6a2913afcaf932b57925f8d2345871cd4f6d4fbaea9f50716ab4708082c2085933181a0f7edcea12ac2f20564237e134394484640ac18c81d66d81ac1a69a967085498b45c189f87e6caa8e88320a8c6dd49871f883980e83f27533a9195880a1a3e57eee110144c631ac1bf730c55cac8af5bfa97bacf319b59b1d1983210413fe29edd5cd42f89ba5fe9722bfa84ee81dcfa70b736e6a73f38fe2b6e424a79fc948b155f2b8567f39c4c876e6c92f3da0d0531647483ee486917e7337b8c52029ef3d6542bdb95e359e3904daced8197784cf77fd30589e0f8f21f5e798f67501a06dc50dfb85887a31f30d51d9da27c56b1cac55691a7ad27d33b251afc6e41c343bcc201d1b998ce71837df4fb90a3d947a76c1a41559b322ebbb883c40cafcbd7cd3e2d7b5ea6a6ae8c4107ab83b904ef88314784796b78ae80fa421d90cfb16b8139f0cc16e4f4e58c06016ea24b9579689dfef70b3c1058e69879d42ce444417a6b20dc1026d0c212c0d67ebbddcfeca11991962d1f7a7321266f552c3324db7b6ec2c4d32c27d7cda25f874ead94b9001b68b1db203c8e1a79ba331034c1e957fcb7a49858b9b18f59e5fce6171d62a36061451b38d3f8d44afd0a32378abdd16ae418628776fa7af1ad29aa5ee4150849e4da55d57e9149ed9091b19557038342bd92c7a34025935e8ffab6cacdbadd1f48cb26efc263480b61a387d4f82ef407e1fee1606fd095b9a8e08f1e38c1f4669e7eccbf02e6be2ccace1b5e1dfd314c210e6e90773c4de958f6239dd5e26f38064d1907287cb565be7cda4b526be18dbb37891ed307dd17a1ac8d038d250469df64a57b5ac8a51751bdc312859c7d4153f238c480c5bc673eedcf8e5ec1069ff15ad7e58a8f284a07b67599b4a132ec984a7fd434f278411768f181f7cccc4ebc5a31bbbf87ec8d00922f9f62033dd39dbd4be943c91f85a4c019723dbe88225e7e7618f3784e540f983aefc17076745897d0947fba9307a108a8358fe157a8744515b49f2f11d37c0aeeb8931f6a60a19e5e131dbc7c85d4a20d4407b6707874b6267b14d8ce7ff2094fe7d88dc68661c02047e088c8b727bbe8bb27a9261f49e401c5141508ab7873a2dad2854819b1d0d2d7d46fde211db49415927dd33003d12ed5cc69262d19fa1bb1ab43a6970657389d35b4e82614e589c64f464b443df594be5179fae65f7fe86f6d1ad8b671c946682c1eee20c0de9bb27a6ae778229965494ed6fb543473efde26b22719a7085fb1b7a8566fcf3595cbcf7091adcb684a1c1d3146dd8040e7a64548bb7e545b1939e9829ffe8d4d701de7371df1dcd179ac613cfffbbccb99d8826b62e7c12fceb41d08fccddbf99f1e2f8b7d2a30c8991a40bfcf8ef71e0306617c452770e86fd37859fe07d29886aeb9de48003065313be618c9464b3d5f3f2c9c86996d39ead2868b15d07df16246f0392b1bbaff0f2991c3e879ec963b48714f9304387d75ee82578328156805082980eb6ca2ab6df0ccc6ccc4d06772d04801664e32c9b8b2c044b55e2ec4c9361afead2ba25e6c378ead855e3b6c8f88ae0d82909b5c677ba13597976b7ac3af7ff7a2acb4124577cfc7e8e6d1c3a533790aa53d22156dd6137075844e76fe61dc89f8c76c2166848434d822e608638d49380670cd0f7112484acc2e31cf09d585228ac1e5a45878178fe8663865525c35a43338dfcddc70abb6d335c147c6a8a97f0f99e967f7ec385fb756763fb79f3fbb119ce2ec44f30f3146062d2bf49fbbb718e96b63c2c3379d4a7e379837c353c051471d61db2c439c986e86f2398c2ab67eb8d87488a6500f6d2043d60359664770306526be2629c62a6c011274ce50c3d0f0a9739e480d200c733c197421899f00db540c41e0fb9cb484a8e3d8705879e8b0d1e2a295f70a06e541a8b42f967d5e70a136b9dc70b48b85ff5d3ef880df75d2925201f9557e18f17aa0cac91ae6b6496a1b2d6b05a6fba4bb42e8a3c6d823b599192137c00d9ec715994094f2fb9d997f9496407f3d7eb4ad4f927f8cfec88fbd66b1ba41ac49b9255029b14ce6f290518e22479e80283d23b4565c5e2a867727dc1d010504daa38fdbdf0f5496b26b7c845b144c74e57a92eed98cf75b770bbc5a6fb9ee8265298eefc73eb9602195a89a45b8c16d552e95bbf32c794222470001e97fa3355950c7b913b45dd4c8061bae660b03599d9261ebdf42c705a62ef05ece957ada56f93bd180dafa75a08a2452c6a9d353d5ffc5dc8c7a4dd335b7fa24c737ca9acab9952355eee2760f7a646bbd1d2ac7225ee937bbd457bcfdbf800100d674449b866e419ed85a637c56c51a4e0daca246336a7c598c5ff434f5068e8eddc48e6db154ceb27f5cfe93a9cd241d4e8a97c69d556a03ab0720bf26e983d847bab2bedfcc92a04d25864e932e686ad5c34094201021d797b6f20d3937d7f54640194ef93689134c7afaf22535be636112d962c3b43b4f2b3cce2e19a3c49372b85558c191d44305f06ad72bb6f91ac97470c1dd642b78feaa7a5be785bf79bdb1af48ff0b2373f12de7f5e902452aed0be9c3fb334b80d6fe5fd35aa7a2d94810ab56048e28bb62288fe427e7ebdf9852d81c82417a7f4c3be16798031dab6e901951ab1dd561e730df5b234f4e1aa67356db7dced9862bd5da131e033e6355b600675cdea1b100992e60146f7fa7f366658811a0762f1ea0992669eb5d8bdac51a1fdeacd03858727ae9b5594ac68980ad68a077d0e75105521422f498b3f8a0a6b76841c3dee22ab62a76a920588d7f7cb4cdc5ed6073772a0feb9aaa3191e105feb60e5fecbe74d4a525c3d35cb3c6318fd2d286fa7d2570b8810e070120160f199c77c89bb274ddb101264e7e738019e27ff00abe5f42af3ae8ade25488c77588495efd180cfa5d5a678e8e121bda345a372eccd0b4b1dda4704174ed520c80bb3dff79456ba76e9147ad9221afaae10d2f1c25f6396c2dac9f591d7a349e9fadab114337542c8ab4ecc6bc200bc9ebd77a9dad75d9911978b48c43ddb440e19cd7d6cae2f273db1d524b660ea9170d24aa13dc3d667c015e65e4865d0201a926e9365617495a0ca0c024797042925dce3ecb8fbd7c382ae1978ff2ecad4a011ddaae16fb319fbb7dfef66c3607207b4b688e666684ffde77f0b7800acec9423da2a8f4778e8d17471428b725b5518a8ca581af7aa2dc9a556e350556eaf4d605da1f93533d833dcfbcb84c6bf42c2f925ae189c0df968bea6c6a021933e401688dfb17c1ab076dcfb4ad5100aea8c43a70202021573daa0ec53e7fa87fd58eb76b33017ab21d41aed962e2daca731867e81b3ae01d2f9d7a1292332bbd52c74c5691928bb27ca2b500014c2cc9c16e97817723a9c4d442ab6c806a40110b2de31ec35d761c31b16188d5d7ff3e23ecdd53c6f177dede73ca2270b6543cd18d628892eb24e0389b22878050d148f1b743bce800f418103a2c8bf6a5d5afefc0f32c41a87cca79e695a0937ddb9ec55e7f088339f12eebe402b2eb14d106afa6af361033e4dd3e7cd18f56f9b1f761eeb5027a456fe7db2541b4d314247e10d6a35ead8eed316b1df23bac87aff8571cadb62c99bc49a03fff30f5597981cd060ca13e8b7f74702c17faff8ab157ff027fa8b8c2e53cb74e12123fc3f8e578d86462e86bee0605ba36921ef3648366ca1233aacdd3abe7c707187fd11ab65d495ffd7984ff20e80ec38fc7662318e18d7a521d0bf5b281984c55811d5679bcd740e24629b3e172a7cd3a980058e995871b5edf3d4876fe0d9beb96fca687e1be15ec7ba8568fe96b88a91ac22ec63dabd17e8fac7520ee2e42de01fdc88bf17d3e8f58b3aaa07201ef524e4f74a73bbef458dbaceb92f8671bc2c92c6ee2f9f8a4884eca86ecaedd3198ac6fe9c88867800bb26a09d7920253b4dd48bc78a6b736aee123e7e137126e4a489b071d7d5e73832fed1ae54b86c45be3f04d9ec1a37aa8b7ac5e6a85ed16bbb3bf6cf33e5fc4f33730231a64826ebfd2cd5b020464ce55bbfdd5083f83b621b60c3b8578e3e755c66d84eacb435f95754206e783d6b1513f816191c199e5b81811b3d490d035037869729de9c9e1ce7527c32e64eb0064b403b9e54ddbb2ef81261bcee1190e25bb0b8dd3d3f9f755fdc3145c32b1c039296b071646d860c34aa3a0e754d46f9617bfb93536046b72e0add76a1d0f7833250b8d71605cefe7be5d6884623f046c27c8873c8ee84834d9c0cc9b331eeefd8f4a39feb757c412d540b8c5e4ef025daecd3dd1adf2dee2e9578f64be5e0a79a8313461b51abaabdb1ea123766b8fc6c8753e6cc7549e18da1f1477ee28de21a92a01435f5ea723c19993e03bcd4c25aef15fa2de33f34e4c757de5dd9551f8d17478dfe3bdd2829d9993960200ad1c567c9e522c54b40a2a2ac23fabfee9e599ee2599c635f93a5b534668017f6e70f597e054b8965467562e49d4f464ba26c74938d9352596fd44643d6882958c85e9e3d5a9c22cc74b28ab26fb806cb5c58d1b6c2f1b4e399131962f97396df435dd896edb54a7112eae5c15e501769002bb7f9a04d0707775f1c439b9b497c1c7f974fca69b4c50ffe7725982994834950032bba6ce13b6c8b45baa04445c247955de7de04c594cdbb0a5bb603fc74074235cc8dfdb8649950ca024d4d0aaf4688f1496a5758ff373a2563e732280e1981fe1173c0e3e46ad77424410ce62fcfd198fa572a63221c4f6f9aecf513b8880bd7e333573051e7a48994cbd35bc3ff7a9288c6ec42a96be991d61ddc7f72bf79e75ac01ab1689572d25c97bcc484cc4e8c4b0b93817600d7dd9a01595ceeea5ff31aa9445ede1531033023f405f4fd4b384f73fc0aa4aafa95bc89cc70e0365fba72577bf4f2bde3ed0b77c4997f761691f3316e6ae4a2e24b4a4e7bc9987d7671b3fc180074d8d8f86b8330a255094ba3c6dd28b47c21be346a806f4af31186992ec2e5d3cb474f1b1f0e36d0c68e8ccd55e04c2921883a3cc043f9cb490b5746d20b2c7d189ff2384f6878308b7b44060fedfa71361a0f3cd234eb90481c9633cb47ec3b270a57a2f6a9abf7bcb4563efeb5b9351837185ac9760af92442cca4669f2f3b2a608dc1293d1563d44b012a3f665fbb410d802c288fa26b44284a24dfc241017739d4239f5b015a578ee02e5f9d066043c973d94c0b9ecaea638aa91c633fd3074517ede3e2a662371fc750bff3818393e0c7ede81aab055a3705ab66044ab406b5a4c2796d8a891616b17c1246f4235b4382d3f40e73b49dc7a8889315f5d1d1f792de7abc1b3ae08c4bede7f155db1242cae7b08ad0034cb475b024bec32d90693cf5f97d354824a677d0e1f1664b9fffeb9de92e2f0d51401a1be626193a730d3046a8a5d13e4abfdc8cc2f1d66b330a48e7a06a15fac7e062abc5a30d1880f33597ba00d004716f59e66df0ea6cd6a3c60af6a51febdbe6aafded5ff1630579c1d1c1835bfeeebcc90d9724a5fd60fc9c434858c2acb313e13c8238bb7688985b897b56348e53d07248f8c4136088503b3037659e76dce7d69fb1321499f5f2ca31e43d6c2c1f0af1822d0e852cd0351a279a9be0522983b0b056fc9e216bb591b1e720e7a9af775e827b77735e0ea319c82726d3ecfa7706123817ec82e98ad7a5af0e4fbe0203fdfd381a884323bb1b0d7053c9be3d922789a15c7e9e2a19d5cc59c3aefc1ddf1ab479022190b06e93af282e051c4f671e121a20967a0d813db30e03df3a241c49164a9f46555ac2ea287318f422b2e32f37c77264a13d89fcffd1400f69556520b1e823adad949052158a315fbf3aae43ad1f496df5dd1fe5fe09d08d1e8e82298f2ef4d290d6eac3938e1f284a12f31b88db82805abd7f65541d3867fb7429535d8b2a200bf5b8a203e80186c2d52546b534d3eb49329c9947a29f1d1e9e182334d0fe6591d7b3db8fb9a13c25c1a16c71a74ce25d4a0bb327e4b659fde49ade9137b2b4ab2fc0e89a3970fe4801cdcfe1ba8efd93159787bf633336f0929131b5a54599caecdbfddb624676d13cbee9a9e1eafb0805f12b2de0a9db884a6e86e1b3811f8f2935b2804be134c94dd8d4d467724a6e353f950a44328d6bbfc7d2253c2d30dddee3cacef94129ea44aa33e65f62a27b9852ebe3213963f6f5c538ed7bb31cfb4fd1f7987ff0545432df3edd8b60905646aadfd23e332283eb7604bacc7dcf1b779480f4e5cd7dae0dc9b5027304f0f036d89b4dbb0ff1ca059718f73e98ee5fbffda9299f15fd1ae58775e7f0147f57d6168b968e38d12fcf9ceafe022216c5a091a115b66f0fca3a69817fcc340dcad7cd69be1cdd325f01239b500727e300eaf19c378e5ca9d5b80d9129ed39305e0ff84f74fbf6dca9d329865fff9251ecc0262c3f460ffcdde2d4a108b701d58fa620b60ebb2a1034d9f1533e3e19671e70b8c19db4cb3eb213f3af71473ad97067a04db2fe81060f883166ddb6ba47e88f67a0307b1e41327f4eca419138b49ef7b1ecf15ec6d43fabf42c5f4ea7f2668f8c524c1127f2de4a4ddbe6c5471fb4a4db55630ef12a3ce81ebb9233071af8b5ae1138f2f22c2f2212823835be525fde59b138c7dac468a90b361a4d894e38c40d78a8cc53e6b0f1763337eb56708aac1aa2b7af8fa1f8bcd7bfff8ef28234bf4b0aaaee7a26a777dd9a59fed235d31d862bf732ea4a56d44a084adf6a0fbfdad6906ae88cef3369d1f7ec8ed4a4776bfcb69ac8f1ac436d436e9d5ca5979352e5621a7205be3e0677682b5259abc39257cb0884741f2166fae3eb5b978fd2c5497cbba2a5d1a4363e586be158292d5659ebcf1ec3bd5566f01dcd998939cf459e9b7433f26df0ba96536689a7f3c86eb7c9632c2c2bcb053c71eca1a136d871927ba6f860cda7a3bc4660cf20ae3d7c177b25b57d313498d7feb679e1c5b2006c27a0f8ac29da8ffba9fb3222f17cb1c6fa3689dfc1bf59112db8b20fa3f3aba5490a0ee2885d655d95f0a074a25e721120a53a795240295f7d94bc23cfb385d8f99ba3c48d87f18d75dbdf6f983900278f65071b354e304ff83485530d96a3a6a147e142bdb2217e2ed0dbe974b8411f107a97591e12f2f9f89b2b581ddbea5e6cf37bde285b57cae3f62b4a4aef2e911a09ef19aacbda2323f29b057fe6020231932533d4891eca6f388c97aa81b80a4af9c2b86c202b392fa5844eae22a1d3754547a3117f00d515b24d40d508edc2f711aaeb4559c7f805fd4cf8986afbcab6d53ee8d7a8383a867ba130e8d404adaed62085ac09c56b290da77a7f5334370d0272e08e93d142e6456cb623ed48d1106cc871a8440cbebc7b990d519a32e58b433bdd9c9e4be8cdfec84c138d4fb475eecdf8fa9f6a899c83f9aa7a26863473b6e0a3bd0054f20b5c978b291cc6a9b16a940f713a4bdf51e978accd6eab4f9fc0fcd78685599b6556c0fc88738ea7502bbef539794ec69e47c95c3bcd85f94bb9e1dcb239bfbb8a02219924914e403f32fa0122dc66243ea1e5d5d5ecfda0123e35465929b545c8251f03c7f25f179f3dba09e4a3c6abb5792fbf0edd0fd063ff196ad626244340ac2f2063f955fa93d7e2ed4369d9610c78da94e842a4d21777d614ab061eec46a70a831536556da945640587ec548fcc67b551d0ff8116f2ed7d582cd3ffbcb9c55a3be31b4aa8b4061150438a3f1949df8d278ac9c3c624aed8d145127d8a27309d63df71769bcd9fa199ecb8e2e16b974582eeb27fcb76a2af22fbf7dbf3507f2a044f830cee2fcf1d7afc9fb7a244cf3312270ad0ecef404f0d634a704136bb0392fb0b55ff31ce2ab03802a2650ffbf07069e0488d906a2f237dbd65ea96108af4c369b2799ef0d503e3b06b0718d8600d5ca5d21c2c77906cd1b7f3b8f516707e5c61194bbf6822def7da5fc2e978a5d3b7cc77f38622f2e319600c1585618c465758dd3b2b453ff0031fbe8a8ed0c385f187936bd8cb9fd554bf30eb42f7b152515eced012088765a57162a5a90d8f89d40c13bb390e6126f409e636edf2f9e3332f590d57c608aa8d7ce3ef050977a988b24cf07879db0b474d78872551483e3574a3b2702294c3f408ecc87748181e6b92f21fd1f9c3b72210c8f7bfe52c1cdfe33a93c2253d210f95345b7d1a6f277c9d1003f329cd47e30babbba6b2001ba8bb2f37375ea65518211a8302ce1c3e6e09315c3d78552a14f6d5cc6f9d8ac82743f6b67e4c8f68d7cbc933718619cc69dc473269629fbb0e809a576604330a203d93c03dc6625e066763ad200593f2d4569368026c76d4c009625e00631c6d0d2135b43e4bf39a137cb6ba6e19a372c0b261764a0f54fff50407e68a9e2528b7786d12fac959162b2279ddd02d8121466b179ca22daae3af76bdfad63eb2128fd07760b77cc8e881d00ff3af1b2a7b2e7ebcc83c92ea15e170d5c08da6329a74b0f9e3603ca9c08627d9fbb4d8ba16876748c24a6ff9e0ffb5c8cd4a0c82d61bb36a7c8b5e7f170589603cb0b8563d51c46191fb225754779ace4d2f910d43eabe68d6aef4635418d1a6a44cb778765a92e6e985af572eebd31bd7280963fa1ed49755f73b609fcd0adb528ad90db07f954c3e24cc43b690dff9febcae6a8fba23d498cdc5ef3247ae5f6cc70aefd62dd925f5ca1120bca3a3e89a0c330277fba61a55a59ffae5ccd844ae90f67be9f1f8f10786d796bba7c945f8edb6b0cb013eca148a36401ec13816775db86887f201236217dc076f83dbc3310d6302a89f59a999666f7fca3e833b21f99194c57f3bea454425ade44119a87946c492f096445766a44177a8f6506529039cccf188d64fceca8edcbc9da6f582daa45ba96ce7c8d61760c426afb8cbf03d0869138965094b35b70a699d569bedc269047f57a0a57eb9a25fb3520fdd32fd8e9c71f44fef32b012032d7e18d182495f749ca8fcbcb85500ba6cbc9f5b7dbbcb752c989e03daee9dfa0771f19b1e64bf84b07f113db35346ddcd74a8d9a6bd462a1b54c016c4fbf3045befe9955cd9235aa413f0b8f80d849f6253d0de20f091f6c9bcdb67d6554d71bedee38611686ec22e9e3013082cff9a17805356e5df163974503f0823404e7b0723530b5d1c4f4eb6040b40c03a77f43331ba3c4025966b1923657bd2679c427178e5136d6f9f0c9ee39dcffe76d28315832f1ef9387f61c4c0d7c66281f9d7e00a94b0dcbcca44e1a7af8b634a121aec41f74b339fb3e5873244968fbe67647322b1d59b50775ceea192c6b3040cc3c8cc5af01af3e8dca977a677ca140db9c3a2fa76e3a014edfbb34de7e8118318f715cd9acdc3c58c9d51bc3a8747b00a500e08267804f0b693bc99c8154f6eb9fa601865dcf5de786df3b83e4780fe65a8ea6e08c3c3d814aa5b61e227893c1193dce9604742263fcc71e85ccb5f8f727e93b13e3cca2581d403de96538100082d9356a56a32a20ad4ed7a582094bdcf45bdbae23aa9fc1adfe86421b1f48018e2bdfb561587901364c968b4fc782f3364d3be8f11b2022249c68f84dea20e7ad6e0fe6b221c77e0ae7a107cf7adffdbae5dd4778217032cd19d323a02a91d2c0566810d70ec26d97863643bccbaf6510fcc34fe493e571ba7d9fb065efa8cad9da77e7cc4c7e0ad66ff82a79a57dc2e5ac1122fbe9b064650f9e62e78f315018bb2022d76100e9af5075a29ab851ff740dcfee8fbae7e2192c3fafb4d4845102902d5d402267a891c8090742a570f31fbdbaa7a09ee4def93dc9040b9248aaae669e3bf46eda5563db33c9363d04d9dd0c929e87074c5f39b22114bff813d5b63c3064bd0dc5f50f390cb25cbadec430a89162c9848c4261baada64ca813ef329ac4f11012698389789671ebdeaa4e6f0da5c522d002146c259055d1bdac45c766327bfa738f6f49fe249bb7dc8378dd04579b30d6ec615a6fef02cdd04498ef8a63adb6f52da2deeeed4dad9502c681b66fd129c63c476f507867a1d98ca0158280fe86a542e5bc3d70c842a6787edb30bbc46a027ebfc88a858a60d6d702681ed9e2b88ac60eb90b8e55a126c999dcad8ec81bebad70292b147cecb5f999d573f7b0a78664d449f8b4f1af0054afd178c817f259425d33ef3f000a75335ab1f07f26a1f3f2a8b837fc2cab6b786431413cc65b19ef6ccf7d1050255440474e403ff3b607ff1318742eda59bc496d8803a9d949eafb38285920dbfcef41a1ac09177194db8daa5e3a171119f0961bef1380da8c3eef6af3e8edba98f5da1b84b9c7cdba13f9d6d271f6bf35e3d6d0cd8e78b3a930553b3bdd5e2d3e944becaf69d65471df5e1099102696ab387affbe05fdbc6677da26f1dad0ba8d55c434025e5f71fe3f8c2b2471b293bcca632bc3a210f04baa648aa97bc3e8ee05566333ebbe2843b3fc3c42859db8af389df9a47865bf698080d8619c052a6a3456ba8bf865d9f85ea0ebc7b57bc3fa5e62d7013a92ec3949687bcf86a5bc57ac58d4eab80e43e3f748fe13fe584feafe2a04ebb534c6a0250928ef1ebeba716f76ceef243f3b074f1e526af83a76b69b120f200b10eaeb40ef08b1470192add8786afacef809e1878afbe9caf02379c0743c3198c6babc1c5544cc9a04ceee6665069f308fb27645b1c7c0bb39f01a9d739c2c4c50c3a028eb8eb2e5b01b43f99857af068bb93b613719553b0295f0955d2adda90dbc129a1329188b5b6cc4a8169c9b6fd33b56f38e6f89ec32e5fe19f2a3741def82c86e1574d57c0f833b0640cbf4bfd7251c49520b2a78a6da31556f1f911a2093c97d7120d6f2d271a437a71d7236aff15848f97e322817a3c3eb99278a0100ce66b773265c170fe854f0a4fbf122004776bf7d9e91e9542b59f6a6adef22578d848a77b0122ccbaf5f964ac24900afadf2ba9df78c467d8d5678cf25c975e02a49b2ddb39828ccc22cec42fcab7808fd501193af303dbaa59d951ef40a6e660fa0b8f7e55ad5b360ee0dbb4791fc08d0efa215890da3f7fb5094a182f960243b4db271d37576b61e783fda43464fd079d77fbd9f7810ed5369259c630faa16870f5fd4cc7b21d56b9c54130aeab95e7ae3fe85693f4b4d25b7afa44d9e6d236a9773687aea597af784575dcd99cc54e226ffee9f7f31a6dfbdffe0b217a91866b168e27b74244a3c6a4b182355822d1502232c681edfa0cb09232139ac1f3563dd65638a1974d18871d6b42ece16bbeec0afe83ec2ecc78e520accc21823f830586060fd74ad48053b5cb35869f55bdf55c16aa6cf215237d85a00202dc6c2e3ad6c024485817177c41402bd976ba7e895a74d254961a4f2877fc5a2f9d095d509c84b21e439a2e05aed6360bca12285035a9e7ec227378a5d1729ec61c134f403d53ba5581a9c9f2227d18cbbbc533dc8ccabc3427933721482810f3be634f13672308499ca100b32581458e11329624f6770515a76f53316eca4b376a7bbd99ba4bff29def435fcf725f7f0b1108f4f705d316a94019b80c5d453ac8f0b917c51f2e01a1db266745d9a67ddfd46de2e24fdc9b4f2d8d974069ee1871e3d05a20efd3d92ca43c70c5189c2a59ae06d55e5af67407c7de76abbb18e0d1c18545e3c925c76cd6728e794383731a7c99fd1d7a0debb0196924856980031fb9d902f54c1c7cd0b9ecbc81c8eadba643c0e53000f3cbaece68ea56082de259f9876fe6f392feae0c42b58ead5585d36f0eb135bd52f3f94b385ad30f02ca55a6bb3079f4bc3267509809ce4f90cc30cb9eba31ff1159eff8fff123f422eb64fa4d61f521fca9c0654d11b48cc269ce0a82e0856e2d80ab417b65c27fc57362a56ebccceffd6e67e645763c5a89e35d9aa1976713f8b834120265c26456203f36f9fd26627f04ac30721bec75901ccd84a1c526b81710043713bee36614b81be68cabc863e3390e86ff4874d0380babd59ec2362ee02ca117004f54033e3aa97ed8ad78faf91bf2813af4823df2c1ad5ec80e67abe0a7e65259b79e716b3fe9ac3fdf8bcea7655f6c646c592e54944187d34f3df733ed9f3cf5b739f7175783df3a66106391517172eea455184c183739b555ce759ea403d7b9efb0638752d6ed3a17696774dc1d7ede72b7a90d0c725debc985a0440a13f2e5e1d6c884b99e0728b7254d3484cfec7e623021a0a9914bfa27f07b5ee3cce1c66752d2e604473b48a4c961761b2de4b6d16b8fcb5b868f0862cb8ef74422bdac33d449b11f030ca98d4200bb94e78eb3b75bfbfb3d5e837ecffc08a1ee9197d594568079e3b21ba1b00f5c7e6b2f39b6027f316e35243545950287ee796b5bbf6521cc5b04d207e1afd9c510edcb667ff76a8b693877e4b2211fa5a97b702a3144912428dcb7d198efb64157d84080b9f8e3044fbc73ecaa64970ac4f49ce7b4ee9c9e52966948a030d1ff033acacf84a0328c1b7abc64645dda388a46e91beed0fcd1bb834e8b251047b238f91e6db6580de412e1cc5bd5b81dfc7c691d6dee869ac8d2184d7054694caaed14f7d591d80a38b6f9e8c3abbf9e6a5ddc1ea900b564925bd5c0192f5aa20a45fbb07a723dd2cf5b5bad66eeca3599df6dfad2a812f3df9088045b30a4259098bf8f037f9a0f3e52c4eb848c058d80e644391425470038dbf9428b36f60d4c4f610d1ac0100e756ce3a1fb0a6cb37dd64f115607e4b79ff3c39fba1c764db7e835f3b6b67ad9d6764838189a4a052f28de41ed4b6065dd2c69ffa18a21b8feee3b2c567e69bf5174b7a2735e105dc5231df6566583971a340d0f1fa746bc490eb50f72e90c601c92e797fe8a7e6b8bffb873cba2340a24ad1ba592be40f66f92657eeee91ed1152083a8de9e5cb1270f480e4935cf783218a8eaf5a4ce910fceca94c2d59322d7384f7f910c8d6bb9e2601ea48497783cd318c6cd144f247f236fd8450145157655001a8097ea92f272c817769c48da9b6c24daf6bf9caa78c117fd5a70ef2520d52b1c9d929aea8caf594b134bbd8bcc159e75b9d6c30ebaf0777ce2a999caaff7d4304dfb26400ba1a4009b2028d6484793134f4dfe09405ffa6f0256bc5408a780e5421ce7a6da86aee6a59fa32e9fe4b8ea7846dbde6c15e88ac15fc6282604e69aabbfcb1e87128a1f34e9a972da5c511b7d4d04ae53a4de95ccf891c0be257ec5030ee3c0d490bd41e53d66886e0a9d6db84167fbecdffcd22d7f23d449cda9843b6140dc672b13bbbce3d4d8e291381ae965cd0514082dd7c48b04d1276ab64a2a11be9123abb0688a52e67a8bd7584c5a29a266ef8bcbfd8aa1542c1123a7da22aeb2a4fcddef6faa0fec0241d58bfcb2b9c392bba09b1cf2874d5e501117b29c5ce7839abbcab5d9c01eabc8ef10c50914e2f174f237ad0180a5f1383f92a5a74106bd7b2d987d7fdd269f2a29f50db9ff2236e2c36f600c92b95fc7ebefe0d8e6e395a3e5ee3ed0d26b691d595c7a7f07d17791d7e3f7acd758abc9a0170ba29bc3cae8ae5814e9a34407fbe21f1fabc73894fa6941de891c2cc97967981f33cf6d4631293ee443d02bebf5df6a923a3f99f0ba74cebfa0d04c77e281a2f7a258cfa93b8675f686dcbe9c4bd27623fe29f3a285ec380fc4c347afd539079f2186dba4b6fa5f7714933660e58e679795a9c81a55f71e3bf608bf46d9c455edadea37799a547680bfe26d4d6217c1b7b30fcec642892acbfc0acba150539279ede2144f5de3144106f1666b18d0b29aa5ee3e270b813b44bcf4112c91db087238a7777f22aad7e36df3d44fffe6c3a8e4124615405b0865e1cc922d98729d9a9ba3a4a4b85082b069d6a25d7eb516daed15414f2811589cab57e5446439fcfa836f31084d1458d3d772985f36bf34986471f6fc24340e5851fc129dd1d2a2c343fe772387d211002d6349061bf1f4b954183d289497aec27d4f0b2369f6c6d6de3fbf12c1a6af301d51c4ba482ab65e6a4e347bf830fe0b00145ec05553df443db4b2ac5b7ab9a7b348f798835315580625bb94bf6277471710d30f5210e4b8fb2d67ca2960393230e2bd52a163a6ca09d14dc23bc090d86ead996dfc2fac44b82afab1557956cefe1333d00e8b82675f595c0d99f8dd91ad502bd4a431ef1a2056cfb35a1aa06531c4cd1cef13aaa3ea4006b1b29e5b1fafaea498cba92609c4c1b27c44c0fe9dc54811eda1e4c7a8918e2693075b5ea1f79e66e8a3215fa1ebee3ef8365bf21eb9562214fbcd172a791cdc9e1bfb3761113f0b6be439e76e5ac91a320f33755555ac49b91d2fb2d6e8d4fac9702b68a7b476c5ccca729c5d1d79de5751786015c2155a5c26589912993d80f2ac58b961f0921bef64786676a4fef743455973ec365a897b71b9c6c8fc58be2415d479ff00f515b04df3b9b600153a8c301781d72528c3196e09c748f97ad2183d447af06600e2a9b47b72b704fb96e0d4e15ae1e111f342fd4bc5636aff25a098f70b74a8a5c72c9042a3f381c443c81cde7a128dfc1d822351797d73b01df4a9c4f0e58f47408fa47e4cbb690101d9d9d14fe7ebf300f787bee8784788c1c705a9984f22fd6591729750dfbabb21780daabe80d3e99e154fa7a59a5d904daa65fbcdae8abd9f664c2d2c44f5fb2a75ecfd05854574e32215757558d43f5fec5deadb8fee1db877babdf804fb58553ae28db6dd32e0e08f73ed2f15c5705b8ea94f78360bfc0666847e9eab468de1c63d6c32c378f2eb561eac2a8f3055e34acd141e41b4a4fbebc047c865735c970e5f9d74ccb3f462db127880aa9791793265613a824fe6a15f6561fbafa7d8e23c91bb7757a201ce360c6c737065d9e696bda76f84cd075a76c6a900d25ad56543298bba3f9635b4bdd476843d50c58e02d48585b8e533e13b17adc21cf36964eacfc1829cb08d43d5cf3116a49b3cb47cf39c2343fd0ad37529a6b6b213c6d84deecaed4de2eea36ea13d589bdfdbb6dcf677754c5f086df7588a443938994ddddfd6f3e8abc870f23c41661a0b2b967a6d579ad15caaa44772b83f159a24999ed13a24afdaec92b9e317bc03f5d5f35cd83351c95e86f1e8854b37925904922d5d8b4b5818928b513be2816871df7b3a01a0f7ea9159f1188bb372d2eae2cad198323dbf91f4c0718f684127481ff71c02d3f21c7faf2b9bc12ba41c904dba448403113e1d3822d36640c2720ffb0942abb5edf622393690cf05ccf91dcb55eea6871657ace10b20e595f294d75e84761477529e005eab1e68e1e7db20cb012bfde41db05d236eae4d63a6d75d53b01ab03e93311d29813a2f3fd3594527bf0d47d856b51fe814f38eea18ce3b7756134ba3620c293b239338c298f413fbbd4c0a241a17294a1585edd9782a8ff63da5547ca10cad595a9f34148033c8b587315a5ff7d27140e8c2bded93e14d01db7d867518da2c63d877ab942eb7ca19b08f0309fa6c93a5daa7aab56802797a5f1f84136c81187f7a9d43d49ae85772b6b0026a0c47af213dc06fde54b25e08b23aebfd544aba36d52a3e02b041008945fc1f7840089e33c5cdbbb5d655e6fed3abdb19cc0d7359cfb45755885ac2ca9c1e8552209a940b7eb378ffdd962e38df7dafc8bf4c3eaaa99ef68e5489b8e27f4ca3a726445fcd7ab7945f9ba68cba9599c80438d19f3bbfaeb4d0c10fbaac4411d93187d75df5e6a443647e5e4cebc47e27bc8b13512baf19876869d2d1698a6fb8109d06252070da8c888d0e1ef3bc7136a7fdfb453571adbb8e9b449292c7462e4a9c901e10d61cc47b855185c7f68bd3a1068164dc4e45fb2142177ff84f98bd7f41bb167bcf6d7fd96f32a13a90b78e9f9a1f1658237489c44a852a77ac9f0983ab0bdf1dc60a527c4e6735f201fb1630c2821ec6f0c222658e27dc0c7bf1fd0a49aa09dedd3a23e6c517aaeec138a2a2c573ff821cf305552f521ace75f30c00254add9522e65d7203cfb051e27e08f811b61726a4969d441cd4d50966512deb303f6e3b36d44852984386dc1e03a01401ca5cf2897353e489ee13b684fb3b5cdd21c7b5c8177550de22f8ec30643b96c666c2122ab14dc659a10d59a175b96f152a6afd7231f5b105064b3bc2b1ade1e97da61335dcc3e19e112ac0b56df9811449dcddefa1165546cd3ad0adc335835ae88f7fdbdf01532f9f921fb0945b2a16bedad03074677cc5377d376c18de0df96499e535a04b76fb4a4eaa4fd5003d0ee5e105d0979f814dbfe1f59bb2ad7c7d48e19b1a208255aa39c6ed96ab5ee4a6225498064891bf5fd953ba6cbd2ef1ed0afcf8e49cfcacbe034453048e0ddbef59c995cc96868b68511a317262a5defd1ce04c85082f430d597eb6a58c69b43a448263297feaff8f75a99788b629abe2150144b7c18896a95d3e152ccfaa73c931c6a33be31f8110e70837b1e116b34277f302f0bd1dd856e8802e762795c0027ce79243930f019235901eb77fa7dcdcadb8868cb87d5dbfb9dbf6d3ed55dea8ce7fadf353fbf8578984bb9ba4f99f927b2d41c1fc1daac20100463ffcfc640078d2a3668859825ddf19408e661e2af3edd72c7bc7ffdea7757d6c03fadd0df001e67efe0a8e4b9bae5df63b88f491cf8cea155c46f588a107437d142da391ba823d6fbae4af864699fa89f01f083d529ea89f2f5cb203595ca880fc4b71adbe3ddc300aade333f2369da457b5962adac44208450650401e8354a0789f42089e1d81c794010afe9efbac802bec8f2ba31097f552c7474eb2fcfd6b71a46e19d23beedb72f8afc807c8561187e40ecd8304b62c66d0d3b0d8f5686518ecdf9f652e72b923a5b146549b402eaac67053e100814ba0e20f6fb308fbf0de2161321877c3afa7483c403766dd330d16b99690ee0387d6d08ff0c345797eab1960218dabb197249ffff0fb90ec740f4f45b4834e05f22f12c48e1ba33a469b7bb35c05b8af4ad5bb49a0203c5af89a42b17917325aafb145519baab8b725b66194e1a2f57390278d482dfcf21bb2e5766769fb265f2db42567ded2b05a5c9e84aa887d353bfe1ecfb399e1a367288c82572dfc2aa3609d174a78802647c10aaa67dc34fa1213b6a511b92dc8651887f24d27c2ae8718da0f24c08a02aefe2369268956ee25be562a865e139209f0ba41bcaa0b94367998a1f291e3b5923e3226fbd4c97a208a9949a711a27a1fb4eaeb03f211eb55f530b32de7e8b74179b920a853eed5f00df285ee2548ac3af295e991ea8cda87eba92a745c6c9b6ef0bec6a65826317e1fd18a54de3e65ffd65361e7e4653c06f6f0a09581b79b4b807da6724b3c82c7c9e5d3687bc51f2729272d992f5360f0b427a9aeaa516e83ee5103d46a0b37714f72baf46095ba203f21bae23a91310b09daf0f09d46d18aa0e4e61810318b0a3cf6392d9c646fc4ed298f33eb100c4d9306f12a93a24d89e290bba6ae5226bcec85d5b2bd14ad61df53d68ad7654f23166d43e0daf501e9ee4194f85d6404b6e39d7a800b65a9b357ee7486a8acbcf0b8a586f11ea5173e097b3c69f0e8ae68a89547802f8d21ff30a932dbd15ea66db031f5832595d9cea045c8f3031814002aeb7ce1c7645d18b29702553d0c5e34262acd5fbf6d914a3caa5dbd6f19d873d91d5ddf358e85b097e1e3657c7e39baaaf66fff1551425c10f45b07995a54484df2726dbabadb52a49ccd0b8ee793481417cc92261c3378582d438f1b7ea2e7089e1b7632d1cefea0e317481ede5886a26ceab7c8d7f29b479b256d4327d1444994fc1cd173810a8ddc87083944e6a1106202e571297020c834dcc2b08177b3caf9caca39d24c2dd1814de5454a2546e1ab5f7c85019a6502a0dc94a1da44a41b14d5b2ce54ade5bffee36cc757ec0517f2c7a1df176c30767f5a6683d924fb632690c81768eb653f32fd2c005f24c1556a4e0b924b82bcedbbb787ef543a157bd4efada51d56a65fc0ec5ec481e22ada2e4e628a3a31113b1ac441bebbd2e0caf8a745a695285f6cf53076582d5916d9274b4a0238a62e131ad5b1d814a903e1b30cd3e77cc9e58758743dc4f7ddeb147a6aadb4a339d2dde74d86f385913041ef236af63de7715a94af868b52f35827f3bdca6862672bea0a0e3241c04abd5b65dbe131a1b876029e044a8cb54be1a3e01613ffb5dc4be9a816eaf255227564fcdc474272b2bd786f33e21fe0dd62d5108a9b7440e9bd65680f89f7aa7df258f33e83375cfe57c57f4ed8b1254580921b77712e2e76cb5a938c82edd8d33ea6bbfe9dc5c6d2048ea56612eab24345a2638f5a3ed625e093832ca57b1545425a9aff6e9d63f15efaf6892011914d5875d14bd77f489ae7701c744c779afd8190c14fd1e7c84ca41dc384b7a3e8b3b049fdf379c40de739f10d29a130a56266ba75eda34faac6bf6318e826fcfce104c7dd0504d4c4adc188d537189cd2f1a5e21157577308287ce58bb357bf023e2baad2fd07ff8c417b05cbaff977d23b6e5a3c8f3d6d198ad01de391c5584b1e6d84451566da3ed8ba5f73269ee96865bdfc797d3c29f091f5dd5bc1fda4dc2f40e60241aa788e5208b66cd903a379ec89c0c36192f88ecf4e9c5d64f66fdc74e91025ad86c5babaf75e520b68a4ee9f144fa31959b8dd1d9358323235f5f43ce3b8e841753175553081b9d3c3cd0221c69c49d5516f38f666a71e384e0ac42545496b72d6f6abdedafcf8e3d56366a965e8f6d3a3fbeca74668632af1a4169003387c0dedc6c19946450ec5cf783ae6365ba8ab21037505021d3fcb70a34f09f0028826cab62f6494204f49fabf5cd007718240014e75137d045c2f5fb7e39f8e282e8c6085ddf5bf332988a0050eccf6e69496d1532e65b68c1606171a89496bd6f3c44f61e55dc5805a19f850a11903a8911cc949d47a650abd2a836299ff38da9d5fbe30174f3f5801db3d2f69292a60c1f79cbe9fcd8173d9285963dd33e31b8d5823f204dca15a74609c12e281111eaf4e73400dba90c514c4110b78107e7eb44271250489929e6d9180fd109ce5c084713bb04d1e14581fd86ba99b4c3834df7d6acd37b2b08056fdf3a7652b5cd79c746ca32f78a1f54193590763a68c0eb480bac31434991474c52ff00b2b2a5862b1484f34558e697359be36bdfbe668a7bfebd5f98064c16034adcb51ee5cebbb739af596121608bb8dd2f4fb64e5ccda53eb3f638a17f0c6dd364c62eb5ab8d25f9b3efd324a0dd3daf19b8f11a4541216067e8bb1989bda52309f47166838ee75e375181af8c57f66f1713a0c2b12e030c89868153b188f53a721e0d02927dfb33b57481d99bd83e23de87a829ec82a165c1ca898777713f8fc23fb69ac04ad883eb52f05a94a46f9f00dc1aef38ec229d449d703fc053c4232bc475f3d679a159302012344ff8adfc7cbd946299db6451b9f8b40bdcd4e01d8bdd05ac4bf0da70e844581763fc034e2096138b080db97115a931a52f7e86793983a2d661d2fe2f7c0c007ecb1714e4fa4514a08dbf11b6c7d1c3fa1a7c2a944ac6927998b6f326bcba87289b5187fd0752c7d7ee7d66a57eba62cc61602ddc52904cf0c29b6de2a9783358737fbb5a22f4a763cc7be979273f1bbd81826f78d26e327c61940ba77d713b80f85d24233b3c1b00424ec6f720bc2e4f6f26dd10590320299c31dc110d6e7833ef88e896e1417b3618418fca6daeccdf985d68e25ab33f509757c3b3d1f9c817a47584b4d46a06a7ca18accbe686a9f84b22c7803f272b0fe20af27c5e35fc9dfc529492912230546361c7881788861ecb3d49eac2f7a70b379b567d62dbcc47be1919232054f952a804fd2f2b690abb84f0262589808d68136c7eeac9bf4a0f74ff8618e5e01faf0e0505a7cafbe28b263a347c7cd06e6e2f488185a2ecfcfba485f9c695840f75affb51b9f6c5c6f17dd162630d7b1c2c798c9b9be86f6946754795d1a1252f1f72ce1c6a2baa3c315df39e07bc9ef1448a1598070b3dcee80c7f04f4210474753cf0a640ff9ad031e8670a2e5d789687e280df77d6e71faddb23ea0ddbdfab533001b15a7e6eaa10be72a3cd04967f411c9b3c35a84e02419596cad92b0c7236a50251068eb9aef25d028a16e21a7fd2c944c4fc880d3993c392742a82ea84874e2e598622d101ea2bc718dff5719055ea3f4ec32e97386c7f26593ee47c74fa5fb9cf46c6cc571ca55d041848aaf8848514a1d57fec0ed2e6e8c53c121a95d331410f48a7352ec5cb2c7dcb7504164e7261f31ea2e80f57cff4640525756e01409bd9c8dd246e040662f885228cfde9aac4219d97d0a317e09e7bd4b7f5ee4e55efcfd03ef4e9396b83892ad7e3bc108caeb10f5b94e80cb86639300e60823c527fc021ede08504a62faa238850e51a1ec59d589ed5e04cf6de961f1b5a7990511faf20804a1f08a71bab2d1b1122b5e4c1bdb03ee6f57deca7fbdbbe671282278aa867f89bcdb225434db102228fe244c82481e9d9e7ceb646f73780aaf914e290f8ed036122029c2ac51bc223b26802888ad59c4901d3bbca4f3e44a368487f6736e0f932a2f43b589756aff8d8ba56c47ee2d0da04b264204d8e91c8456396dc066f407a5e6c81c81b9c09ed28ff4ae9ddec6cc39e65f686657a964d1e2e7f0117e08db808b289b980741ce5983adba2ff4837f0c6d0b428acbd8f6c5b0018c00f7380ec8394c7f911fe70b97f088407f9e44e8aede7dc9231e6dfe424c998a9153083e59ecc307af06fe5e19a031eddd0954603f0e00a61654732e756c69cc22f0cf12b4a7894f8ba8852a5c5f2209648ed885c6aa370a4fc880af91872966e37eea6a25a350c3bfa1029ed450412abc191db9fc22d19a4fbeb3ae6f7522bafbd9169a799fc67f318edd4455c4e884426f9bb9e4dfc179ca00d4ea62aefe0369ee3c85b1da885faf1c5c946d5bd4842950b91855aabc5e6a40c3a2dcf7d67b08441c4fc1dfb6e65730ed163afb048c44d6d6f7ab92948b9d460fd3497367b41cb842b0ad8202860b3cfb299f35695c702f2a791785ef08a0556aa4a6990dcae200d6b8a7f2f6d85b5e106e0c16ef5c2fa47a2b2b00e35741f19a78b5b5ad49dba55dbbe96c4e107ebafa748e6392fae0e98ee62775693e2876dc6003bdadac69f7ae12d40a5358603e828b8ad4425659d1ee0b38d7cf1544b67533194973718bebacbccaa65f2124fe14c4501a5b32017d6949bb2798b68dce32eeda6229bef7ba098dc2a21eeb02819aba52b5d0c417d37b2341f2b27e0b12b79e52d13ba0619fb2bd3fcb5f18ad5b0ee30b2e64275cc62aae0e24236491e80064eef949e2cb244419375f6ac7954e1102dbd96e16034a894b5efa5e043ab26167cd5f8a23056901050a258e27c1dac3ed8dc13884cfd564f533280bed6b6ede1dc8ec5779d771691224e018829aeeb09b6b4d355b9941324a4a0f8ca2d86ed6cf15eaa4d3c1c9525a59c612e5ba7eba72127f5ba940fa99cd68728859191bbf2ebc0cb5b3e1ca4e20a8be81afff843f94503bb7b30043617601942bee941abf57c85ce289b25d3ba62414129dc93f13a4440cd04afdbab7aeeddb30a5fb0acb1ddba61eddf1fc7069051c4de8ef6996bfd3f2828a7016fec134b21214157be2415487d900ed6b0ffedb41072eeb03f64ce8517649706520d5bf3723841473b956dc1f1af0cf2c310e30a670f2e489c069273682ff094abc64e62587b471b85b5ea82f093e581237c8a123580007255d0ffb9dffdd426fc872d9dd81cff4477637afbad983e59ba98ee6e0cfd484a79e9a762805177eda2ddcb2ef8acf0cfd53e4d7269731889ab0cdd324f191979f67b65b61a88c3b4bf818e4c096091de302f4a57c8ea66a342d550bc6756bccd2bc572babee7d4d696417cb1c8f20e5d0c448e1bc00766a85318e0109cb33d650ae967320e00de54c88d6e4c0c1c5bbc657470a4d29b3fbb1d68393732c94e0c80de3a071b7a30f728ef7732ef68f2853add15d1b2123c75dd4d1781e14a7fb4bfa267389b4e046b63eb4ae27a361bd47e4c202d4c29538bfcff86d1a47ce702aac3ee205bd96efa649556b99795f553426c978337ade5ba42086ae552ef4239a9fb3bd106581f98a44b3eb40bc6f89127f2879f39de6bcf76c2c46bd88abe3cf3fe734739d60bde397e9f58fb0b9e0b59d18d6715f32e8ff5774153f747b09d33a90afc2835c9382d1a93c9983c4d72f26bf26f7525e5dca32af544fcf9516364ed45d1ea90ef8bcc0454fff9f6e40378cfa18b3b058233ec1baf22bf694dafdc3802848a9f509b30e4147337b4e9895d9ff097e46f39dfc9f6dd8e956304988870c86858be413fad31056ef64e65d70724ecdec3870bcc60d8eddeb4fa5944524751eca9c5255f58d4f5832315526e5578105d1110957bbfb80a6f26aecdd79ccce9390b5099cfefd5e581b0894e04ec594d77c814411a25a4b888260562d2e58e6fd7dfd5baa963c28c8947cfac3f0ad15f84236475039a6cc69518c95eff5b5bb9c1c9285c7eb8f4d406c594ec6be38cba6ff749f699f4124535409138dd7b80b3ffd99ed1f20e4aeff59c72e9b73b3fedcac46d5a9bdce5cd5aa283ff14d0ff52fa8d38731aedc9b9d59290351a01644a9895f50acb99d77d60df858c8713a9bda06a625fc4db60c73d71874dcd97bb616795a843d1354e76cf313c3fececa4567f490e7ffb0add9ef35c5c63a2b12ef03b45c798b47798f844ea733e40640135ed3a1c3d94dfa692127976096e6f872298be8f5d2adece4bd9f632b50c22430eed4155a36019d4546ea2a04c53eb3f529e4a41fe35585d0928addd9440ecf250be89aab9c7b423052b4093deb7c83df94b379492420fee5f526568d168ce44996af37ed2c125448b3e84f142c3db8c18f2c745f799ddf7efde77c2377fa80558de9482e244cb34df04787758d75ba5c9c30808213d3462b43dfa0b6154443245c70bf808779dc70e87385da9d3610752b385dcd4939777a313fe8aff9ae108e44abd5d70ceae6b9dc3a2a9feeedf75ba4b597fe088455d7f64864dbd68e9f8ab4146e5ef3f8947274f87e368305a54fa580c4814967d266ae9060a8ce87abdb60d108b7be45358e25f2f009af83165875f3eec2b54fc88bea941bd16038e503d20438a74bdd34b626b10b2dc10053d261ce0c4bc9dd73531f2f562e5009dcd97e0607bcdf0c7349b9ccb218c18c8c53831e948e9eef70504832912963db2152b8ffd27781589f3cf955e9fafc993d19c540dbc0fbfd38aa87ce49dde6bb746e745a939372347c33e938e80f171befbda03f78b53be73f3c050400fd9c554287a50d4d4d98ea96e381b2b09fd0d08a17c83f4fca4bb7a780f327053eee6bc5fec7bb149b24bc1973ae0593199584a696e5d6b7f333a75cfb66cc844f5b1ea6c02dba90123db5bbea8d4cc467b2211fe1c9e172ede81f52e41dd456db525f4ae8eff104b45a1268751f35dde5dbd13a3aacc0a37b7d9ef06a7464dfbe73f28952998f84ef8f13f6c741b824fd340d0be84cb28a0dcb6dd437607bdaa7719277f770e2f92c2c9b93cfb45fdb8d3af0beb07d1c7db083142858b4a5e975345098f70a210a28faf2825e89a46472af23d7cc5456fa1736e5ea0f60df11cdeb6a757420fe1fec35d7e4e0f024bb4d59accab492e32527815f21330a10779d6b449fa320bc5ac7cd5f1a818ec8fa135a7af35346d20f34839848c894d7ef1befd69ef3a5131c063ac01439d1398726b3583e80479f8fbcd16481313a660724b5d4809c972e27dc853778b194d076f6cbe39e6aee2c6ca0ec818117023321944ed22f4ab432c0c1137b2c4e225eb3513e16efb427070c688588c812a19b960cfbe58000a363bb4840bfe2026e518d187c3a9cfd5037e9e30da3d892845428a6afa4dc37f34d28f187c7e7e547e34073604ec2c8fa0f347d43c00bebaf91354b40f1a496903659554382fd837a5a77c152636abf2eaaac86f6cac090d4aea84a249e1e0e097306c24514a776030de0e8ca674d28dbf79a269da9f2bdae697f2364589ecc19908dc317bba26d7ac8466832a2bdca404f5140209db507d2dd0f4c2d57b11e7ed7f671660590143b2990da34bdb1622f34d5e40a388b2d8b6e0b2a61d26e5e0a7fc137b49e2f13e573d2542e1e01cf499846e595a723552fb08822ce905d34983178f46bc73970b63074723be9fc6cf4d79ceeb1ddc8060976e77ce28ea9ae90761d87a78283a9948d25fc7020681338a6fe6cd6a0fcf045712988497fed800865c7ad759a24ba3ff6de665e81c53d56a7da956db6a72a38fd229d9d324a77336ef9ba7ebc074790818b5d0ff90c4dd51994bcefe10b93b938c7dbf65fb3f233c5bb8b36547a4b27ad061a64efe27ce1f026c3da323a3869588173f0a08c1e7dbefb7477842abf90f5ac07c3dc281beca1300efccf4cdca167bd1901a12bd9766ecac9f54bdb3f2e99311417471a49f35bb4ca8c5cab93e579dafad8d5eaad6596a50bcaf2a099bec86b30d5d01b98a04c3185955142e672772c3cc8779bf5c8f4b819c8ed8c3bc522f8d97afcb8f55a954e4928a7818af5e3c0492717e47d9c2d28b29ed50b6b4f605bcc66b54d89241d40ff161b0c5c9d840d717079d5f3cd609b768d7580b8c1afcf437d2354eaec7e2250f7b3b281a5b5e4d188f03cda3612f57c02e44cf3ae2d3d9aaa64394986155e3e750b48749c326d5efc732e02805efb026e6809d1d5bca323fe07bb3fbbc4ffaf8ba85c1d803ed32547f8c078cc652fb225d6ba1c33fc2ac75f9ba9a16b56f1413601ca9d82e65fe2b7f24284b9c5ce647b3b5d30df45326b1b40128ee0e07056d425476f9a38de6c5f981692480d5e2029ee18bddccd0bcfd7ee3cbca0d0bdba751913f6544955f7fd07eff57a9f6c7780abf3f1af0e9f3577cd6f4fc77e7e9974c6c7f92ce17be100d9a432676835c19fbcef6f91053f2463bb5772a00ff510351b46330bf5a8f096347d7463ef29282e8e47ae4186ff29088ac1d4e95de11bce4d19d37428ad442f9c0ac6d12ad2c7d8dc71a86f0f3f171bcc82024f24c0b82b58fd312181b435768d64d7ada862b48bd85c2b5e277807d60c239e39da8ef32a7fd3912b52857c1acfead5dd38875a48f88bdfbb45af30c94ea6e72964bfa4aa2546f6debe25a159c0a6d639605a892acdaa87baaf2c3c816c1561a25b72f4d26060af1ac1eecfdbef93c40a90fcf7f7db0423ff591fe2025b1a8cdff8e08d9b5cf73b2f6b7842213336d6fb565fca50d0f31a6b9fe5216da6cc48fb36f8887419d94848abac19180b7b3dd4f1b6a82041078f24533dad93b87c1f65d24b72ce474edc30c1ce8bb5920bfa75040bcb79f07755046bc4d36be99297a61d222621b57392d2c072eb2fbddaeb55e185511daae24a66a2dd43f4e35b9ed1ce7eebc110de23879d04d0f44b25808ae6eddcccbc5d89013194a10af343c6a284f64a90571f328d917b66ac68c077828f5fc67e774fd18cffc198450609ebc66c30aedfcd92d078be97e0e4782fb51af1ed1e8f66f482811e1e5d84a57aa27a4f666535e3716e58b96cf850bda624e19edb95e8a700a1da7d7d241aad512f332e4038af7730dd641423c3cc87496995347848f857d36132fedd842ce0d713dbb8dd814d61a9e2b37d0f4e6c87fabd6f405549f4480bae42a2b93c69dc6efed3f36a90f01344cbe400085837acac4191d72d238fd2093485442781d9723d488f4b087d4cb2510db64c5e1a8d7ba8ca008550b7cd24e8fa7e11fa26fc35f64026f6ee68b8124db7a330ef196655a69540679ddda0753020b0a10e4e63d5827a31ade7e4bbcc033f59139dfa7423403fa06585b239f3b9841ae80d3a276871d1e3ba5898ad2d51d1252c26bb92c95b46549598a421aa59972bc3cd072370090e832ea7222e71d403bef5c768cf9a635cbafd748fbf963f49c93ab859ef5ca2e254596cc43ed7d80d8a99c7c68ab27d53162d9ca0e899674b97e01b546b05efa75c468014f8f765e7148893db47190cd2e33ad16cda0d5be491b5d7895bb767e5cfd75010e7b57ca320ae3dc37dd5265d9d2c34dbd1fcc7826d896bcc9c8890f46c81a8c99b0bc2472ddbaeab0af49771c95bb9328f428105becaba218c3db4f8cbed86afc832ec80c7e7dd8b47d182e734e2bb7389fd820f5df0ca0a412c89ee866a935ff6f869d078f35ca696a067e687f63889108586dd49c480c8362f9d7faf397bff4a4af5b64435191dbe2b44d909f14310659202f4d3afab31da6c28954278997b6ed81b6f57840aca7f8bc85c98bf9165849d6ab3708863e8ac995219dc60615349408eef9bdd5d47a5ff6a578c6669e8f6600704fbfb8527106e032837d8cfbacd66de1760048bbaca5a4e72491e943bd8028d5351dcfdaaa5efd1cdb21796c31fe494966de8434c3f8d25a0ceb7af128e6ffcdc79a4bf8400cc4bd0bc131b799553dc20d0ed3590d7f1735a29f0c2673d68fcf80ef5bcc38dcaee63f0c907a4563fc3dc33e34935bc4be7144e665a72f74321bde32f29051a85102ab084248fbcfc4714a7863dd2e83c87f5d35e55472e1cc6774f7bcdb141a3aaa836ed37fa3a3e58af902484aec3471c1e0487bb711c4ecf57ec7bc1f5a385ffa168e5afaae487c3040837f0b71a26e17472d758a23221723256538599b230e79627219c5f5237346ada1788f74ed90b6c3807aba4433093c4440df8e7602cf640f4a78b388188cde9c594139b70438675db1b5ea91e7e3b0b31153df67bc9b645f19405053cf1b0c4d15b73b0cbe264d59df83aa18b97f90839e43b8c6bca1c0a69919c748ef7f3fe553375659e95179921989e967553dc3f473412cfd44ebd0568458531b68970bb507d104465a24f467ece99bfe20509b06ef4b0686b0630504087cbb463278e77bdaccd1b8214d2a875af40159cdef2fa442b0495739077d64a52c27cfb0e7fb23fa6e2eb12e5f36a5823e9df636a900f98bd6e4fd730e8669632ee369cd1b7c0f649dfaeb71a5763967c15c4bcb1e94915731cbf8cb26dada71a4661a46717bbda17f0ac9113aa389f65073b430677aa0a52b43fd2639d6c9dfcf6395ef913a9ae543bc03509f137cb489048f99db78fa19cbb451f7f96c1649031677bef501c3306ac66204671b1087b383ce146b96566bad157193412bf55e6ab62c36b4d8e9280d9f9d689a47d40987941e55fa35a63d59571cf6d46ded0db4f8eacbb6da74c48dbf10dc701502ab4186cac53a590f62c8d5b8ef1f6c816b34fc50a0152276ca7962bded32e3e90b1144b9d04a63928102e7aa61803e562fe536c7f0ae60f879af14c4d749b9ea83414ae175352f0aa9c8e0816548fc7f9f97fee9dc10dcd8f4d536c5e3fa76ff2eb5808036d78b98896ecdd6fec4a69897047b7a7c1c3537ab7b24a36453806c3268d50bfb45047a1e1cc0097f34e5d74b8f8fa9bcb715d4133d022a2db348ad175c742615f8530944d054cf5067da8a4868383a65846281e5d491270c63ef460c03015aac790e1b093ad72c5f086b2590b45ef082523d03e0272bb60cfb373f62aa90ea4f4208f09e743fb770401ddbc2e2e24a4561a34d8134159bed9b936793be8f5e29865400533438ce3bcee3216f61df5909865b73b11056e23cc9171d300d3e87c87db40a680bd88862f229bfba80e30ab8cc9d5c0592eef42d4c0f8def46fb81635221ae974e149b6320e551d7d943c812ba263b3929d8495e6876c4146938f9e715288cc41fae2f57e6c8265a87e9e1d8091413b8a30256b71b5e3add9ed97dcf80a33296ec590067e5a1eee9f67e2ccebeedf88587f00515d11c0c5848e44f7cd9f7e54eb356552d4d2c359c58b1672f1a6b86240eca2308599869bd80677f48a68a480fa8bec8ae841b93d1ec7930a8f01aefd8fbc22823d318b14ab8d4df38d6778e41c631e4c32e55a2da6b263fdbe46216c2a599b89c42eae2f88477ff9decbea713cd3057efa8ed24add6b6e89a5c0a8d34d2a07e74cc894eac3741c5424cbb92a7c328dd5010a9b31f9a37e29eb5a6d773e34d898c481b545063969af7cbf44febf1d21b86cb4787f5894ae9119a5c0f550ea91c365dda589fd0067a91c58a70164d88a102ab22b1e5547ec2da57184dc8488501061003e17c5f86200a429d995a3dc6b2c8038de97ab3171313c425d53aaa0085aab5b9b8490a53207aacf70cb427e8f7e2d41f5a0e616c3d0a3ea7cfd426e07e29b6397bd2d744af24fbdce14be1fe4ecf8ee2c2150114362b620c2b6fd396cae990e61d83ea59674043544f8e867bca8123e0f935b00ca1b920e473e4eb71d9fec22c6ca9bcfe7ca67e22e5a8797014aefc6c02aefe7d359638ba9cc0405cf4d69e8b52fbb09e839840eafd0ab20aa3a0ba40d2e3bcf48654ae9e56c8e8041b21759c72dda28f3567465ff7fce1e1d85e9c190b5309e6f872f97cc23ed72a62dc51cf91339f422448a3760a551b807fdfd1350a4833ec03e75aaced280a88c9387b4728193fdb1426d2cb75a8a3af557ef99bd8ab14da00fab67d4e305dba2e6e076a106c827daebaa376e51ccb3772a99ed0151f659fefc2fde94f503a2f52aa1de6652c81635981625206ced0a592e5722829fcfd968b627b9b9b17f5d16b4a78a591186c54cf9174bfc1847f001eda67a527fdef5bf057af98cb62facb1d419c009cfc281bf590a6046619131ff0f3f84dd05eb7a9768cfab87af4233b4038005a8566683e548a2ea36f022d41f8aac6ab16f75598fdfb4fd7cf87493e9ab5e4522499f6d5683026e7079be1bd93e238a7489d8eb59a92a211f70f7e7d7749ed7748d981eda99cf5817f65d901bbd1f90750b64503d68fd9e969eaea22b4f992cd12c3bf2069be9b5adbe8d7d48d282ff3c3c757cba1d0eea6704080d9d81cff67639b0ba03a2878fd6d5933bf8427347089eda87c243298da40f72535fa3dec00b42a9c8f12705b6c5cf7b3e2f2e73050e5bf1f5d305c721b1d8d2283c3268511fd166c0c7987875a12214232e63da612d984180acdd2af31be5f4ee2b5ecfa21de459f1442712f063f6e1bf64cfec4541a13db863140a285daaa0d1838332266a7eef665af287c377c72c9c6010374992d86b0246f38cb86c51218593687e3000b77b6ec41eaee39d32d1ff0c384046f28d0af25f5fe8c4e6c4e3b2df02ddfe686b98aa68892c32b27c6f2e94c312593ddcb33a4d7358c8f904334563447a02af18db29df924b7425ff163e5323773236143b8f7fc9c1b576fe2c916ef32b1ebb1133a31635af6c0acd41f221eb0476bb706126cc966a3858b07bedf349719f9d127bd3e2d7248a771c60b1abd7a42694de0fa53dfd6061e5d59ecae779739dc220447d2c397fd25ddc2c535f2d9c03e3ed4d211dbb41f0c639f1ed2ed77dee3b24bb9df7819debb6d235f6461a75600c544e47babba47f9929ab888fa933a7f702cbf05ec21063a49bf4403d51328c44e20c821f536b0a1a5db65d1f6316747376cd4c328b8c28279caa6b5975c280ef6512b068d8e17b66643d1b71ee0957dd37f5a3e1c991c11570fdb46ae6436a717007a1b4e4f51a0734114206d8591b25bb15d2e5c5530fc233285daecfcbee36772015b1e82410df13cac05ae057958e7f611d95137dc92f4b64a27ed2bcb825bbf2759c4bb1ed8f82a1ba6519432186521f2101890669b270c4499694b2f16d30734b0ad77c2d048e20462a0ff9bc5bfd2c5365a2055d0fb20002ad069fb4d1b1dd008e3235108b94bcbbda6d796dda19396af8bc88172548d1249023622573aa2e09c858e9e9e6adcc52750fb7596e39dc3749d888bc89dd57dd229a316629d56c1d3c84e1cd386f57e882c26e8daef83dbfa814b8a99fe74f3eed28984353e4edc325ffa696feadce9d893944f6fe6ddcce688e87493a7e2a747b64fd8fe89327cf8bc0f5e1580051a62c9cd3349b7d550c64d43757150660824963f5ad29e3a32ae0481d75017e6cf47c6474b7e59eb623d491009d525dcba3f60db3ec228313344dda9fabb32987df4e658dcd1e85129c54928a45fcf4674bbc7bef877885c9874d80a83cfadbc5691ad62d28a023ccf236972ae6302e0e79eaae4d0ed19e1f7feb11b36bf01404be2ed7d9a122025eb93a6037824e34e219b88d34f357a2aa93694e2715b05be70ccf985637c00da2cdf0fd5d408c5b29b52c90902415e20fb62b2575e64fac65061829fa09883a225829d3a23cda9d4308ffca44daa39359d00d3f21ae6af2ca88a4d961967a277aa324f7c3b7382205929d5b5af5723ce7b7d0a39732342cfd835d960cfb5b80a60b40984342b45eb6700754cac677fa9951b7f0893d8d06e763192a3b9f5dc06ddd2c5e2ff285785eece55b9c2c2af9ec7ddcf904f83a1c485f2b698b38d9160580cf16974e8345138abeac5911e7cf94011d6d147dc19a932445ca35e2c817801d67845950a846eac1e3c80e1a835a30c57fa3283964eebf708605dda0484731c6bd49e9d3c78f2b2574ac3791a1c6ef688c06340780259f4ccee38dbc66284f8d8f98001453455d7ac42e545e88654cfa81780e3ddae46f01ce3826075211c3caab58d45e0b76a3d0d24dfbb6c143f6e9e6aba1865f080932d88de5c5ad78e4a6bae9f2caf9c79511ae00550e6b6a2ad52c9d34aec2647f8d828ed07617efcd0bcbaace28788441c07e94cdf714dee61048f9782b7e08feb459c219a90f2ada967e71e63c1d33cbc680378e6e1857ca8c53e40da44c8a776e83e2f3fab98494a72fb2f06af487e55557201d7afadf993f54e513a2b43f022ddfe1e365a81401fe3ec8fb09100cb805664b4c08377f21bcc37894e733dfb1a4d21d1c15021944a916174c5ae08da11cba7fca14d392fd46fc34d681ba0c4a2761d5bdbb22ab32533f156f846797c5586b38ea04efb7349e8872a7d8dd8f6057bf91ea9318cee9295cc0fe1f48ef83a112f55df4e8902a1e0ebe2d803597b13f0a1dceffa68d5da31095c93516197b2ce52ef247a61160459e9a0138a62d60d32b900b88dae6d52cd8187abcbcc37b6fad3352b75419b13289416ef9194ef46a9d881123c31c70ca409c87f138a7e02e6011230be2ccd7c528b5c525e713ffbdd376220d287e6377ec107249ebeb7d5587ecf766825e3e28938a494c838afd6a62301755b68ce522ac74abf0bd30fa1fe3e6ff542fc14f98451f635b4d22a97fc3c6c7f016378fa5c0396a80d260a3e1ef6b7ba80109795e2e65ac6b3a47eb24c052ea3042516c93548dd35f3e5f9ae991353f40ce6c055145854669e9cd243787f4ea1d6da8be437ac03c316eb71d80b14c0c3450afaa90ba869c6b567e0983921a7a53e4d67faba20bf74cfe58b4f3816b1d25fe054933aaa16ac3646240e62f190ce6d1f102916e94023341eaccbd43adabd39c5443b3e659ffa16f8eeb2a1074e99ecf0a57f02b5992ef4266f2fc08d39073a26a018f6bec7c6faa7f5f75564334b1dbebb600b8c7206ff8ff960945908c18d52492b13fecfbf895c80402a22a34e640516f281e8a46715bc2e0f4bc42d435038f576c88ca1108078cc2e9602221cb5e8a102ff21cb3e4e1c879bef83188c69ccdf89a5bf500ef8996870d2cd9ba6be63d6129d5e5b9446787f10a3901622ad12f0e1110b2d6e92d570544b28cf55a38504efb744a0007199267c184766deb5e22406cbaa1bf24a50a2e1481ac42551c295a15f2dae6634e965aad2d58ca13c00ac451b4afa577570fe924d7f0352297c70dbec90b9fd6dff3037ddf3b44ebdcaaa807617013f1c28d661de9629b7f8c3323b5828db41a73a16ef7eb522489b64976bb2e4802d0a3c98b9ad1cb986ef1d1414c91f6300d42b3d18e2401fc0786194aa540131aa085da1c351892d389b7f55c151d5b0eb9195b348e6cee737f31a439fa2d4ed5198a4d55b8b9d4849532b133210390d845b1e325c1443962e93193b42736c4f959921893e6102ff31c33cd4113d2334de0fa17955a02366f84bd172633962e58d67442b50dacb803bb17ec69463a9b5b99a2591755eb33b90b4252b5059f4e62da8d05fbc9cfaba3e82bba2d4f8b0e5928bdac94427e7823a1d941775539e4fb9b63f2ac9b8e780679f0a7d476d7fe01ab796f24e7a81573617a5c4e7bf4ddee480685e0c7c8df45d512006c832caa1125f3a3597c8e2c6ad1ad683f91ce02a9dfacf6fc3c98520425e7546426e9388a084217804f38c32d245795021db1e13c5a7a7af30c55410ec0f27c4b0e1ed736848dc8126fde9a9c04a108a6b084672d17d9a4e737eb1e3e2f92698e5b3c6e9ed1a6b69082edf780e0ce4541b96f082082d62fa562daff127ea5698095b6f88febf1452a4762e02db72e78c0caff97e851e79e8089c25fd034593a1774573e4815e55c20718c37f4894ccb9de5f3406ec1ca25c1bb6bac6e22ca5f8d01c02b14e2f359e1e373fd4b2366df3cfb40a9f6b38d1bf067ea86fcb65a498308e4929b2e89f11d2f2bf1e48fa6638f0c7dd045c63f449a168df087df1b1ef1f26b192e19cd028a1996984bc17fe881a8cf7a743043dbca865d32a2254a7d40942f6a8d0b86ecf009238b5499399fa346e93841e190926f831ab26b0040245905f53f2d8d688ba1489e433df75a02cca9baf21da053935367ed221a833df55d9f4c605c0c3619abc32138bb8d7842a3c3e30ff3085ddf9e0076e628d0b4a11894c297d2cb212662d3a7543c2b2edb4fcc9279a24178bbe8ce0f2047175fe136879ec36a2339dd90c2665d97a97a51922106fa860e7b45fc15ac47ed53ff43f736d5be8618a254c7eeaa77094727416061197696c447efdb5ae0a230076180cd7fe70b84a817b89690b874d421dc3c68acae8bafa61ca81f8822c6b6945884020451a1b71dc5e839f720586c41aa0ccc70da94ff314d37d9e2ca56dda6a53d028d3032bd2355fe462f9cd5743e4c1230031f5ea480fb116690d481f5362d34d7c348ddb9cc510791a6cb0fb1e6f4a7f6690e67f02873dea01305669cc0a0b8bbdd29367b5f7519775300ee6aa2078a650d311338488babf323ded17741fec8628acf249a23ef428506b8b3d3444b67de624bf315a8e2a611beb3817a7d2fff76bf374b1df7bdf5a54400c9fc45011e8458689f9e37ced8e4c06e932b889c2020ad0b6d7869b4df54963af4a85c4a70c7536329c1f01e4b94e50e2a696413af1dc5a8c416ad959dd1ead43aaaa25305270cd4f97ddf653075e5dbf6ed2f56ade6a89686a114274a55bd2e10532f3a532fb6c1b679af1b3621de052a9c8a26a681cf23174a1e8b78daea3378963ce3cce2ebf7a9183c81c45191366d8f4319489d97110d4be5d6a5b34d63cebf63dafb4b6630a0adc873d6f156b2229dd1acf486edae1f67fb8e59a8f2e52c7fa37189ccbeca2db9b59d7f2b00cbeece11cd87a37055be3f0fba696a874a725cfd09d8bd97af508ef07fe0adf2762b77d5163def500e60ed7593a62cb464d3e29e27321a2e1592653df1723d570c351c9f99e54de24b6d2c568a800479950f5bade99dbcc1cbb953d45bc47581774030ae8189c00ca4c3de62797455e7c4f4158a8dc086106846d55e83f08d80b811ddf769da0af8f3a433e30b2d6aa6987a4cd87191cc06b01270561dd7c8de33d513949d125be52a374d07de45ce86cf93c7a2e9f3ea4937a917ee8f7d1d3b4b7a364968d028dcf0d8a30b34a74404d54580dbd7db0de510b9560f1d8d3f832c1d20572717cc2ca59908e5b6c014ed6c3d230cff6d2cb9cd91e64c48ea9acdb983d49267ad5d7d812d35110aa68afdc39e02dfec83600ef7d07e9bab6ff29a76a1a5f0786a4432eb2b55d797390985ce2f607ff14a02ad228e2cd0f456239d39c8b3bfee461157bf7f1c9f66720448cba0f01d7bcd022444810f09449dac99ae282156cc297401fc4405a0cb54b77c8dfad35a3231fb5a20887842eb73e0cc5a65a4cf8a99d55fc04503872f1a8e9c6ad1c9ac4a076865959628ed78d529a1f097c520789aabf431de9aec12febd55f49e2c9a572ba1a2bcd69043c30c22969ee46b13a5963e78904b40cf3120696fcd57f67b2c972b0d52f3b23040f2a1f69d62a67c1a78cfb1f31cae85b9c414730a73e9f7ef2e4941c992f5280c27fc22380a41812307009961fa71961b2a1f2512ebbb9798ec4edc413a16a034d87c8be34c1f1c7c9492a63770f5687274755b4dfb33ce0658689cebb27e997308b628b7eced2466121c1a014242c41e4fabe6bc87da080f767eaeb5d37d01798b031f7315af84698596b16079a8c1f1d2dfed52ddc3b1ec0ac95e23b4f5559c9f36bc9d718181f8920793b310f55e0321f8e57fd94a807b469e5ab697126e016ff225317e404c0a7792d60118e9a64d8cedfcad5d20e46f7215e933d12a75c22a004db9dbf2d7078e6f2e85a9cc89ea9a97703c469f694a633aca930db6285be17f6a0847f603bc66d02a23b2ecf8b5b3b353ba7dac4ec513f4d11bc6ca264efb2206d51e582471dbce2efac7fe8cc9e34a334669790d3e607ce2129798f91b57e52864288f0f6c85ccf145aae93076a038a348bb4adef8bb50b09bbb7478d312b8437840b44c364a5bb48c430eb8f808edcd26e72b8107741cd6f08c3286bbee67f7c13458b3629561690b658eeb9bbf8647a20247b6b68fbc62e2289aa44f9664131c039dd8cf672785b02349bcf5290dc0ef04baa8b50934f78e698e088c4572d5f3bba7ec039624830429a5843a035349f12623fa051ae635131ac1f07e31201809cb23424452c84abbebf1bec4dbabbdd940203271ffa17e31866b4807fe6599666cd0a9200f23cf82a0dff94b513ee97f8a2c5a3a239de2203f6ed366dac10d610c5dcb3bdde288ddd2b421f45c57879d61a900d64a7200d391874e5b2b31876308bf2b0579cb1d6420f5e1aa2f23f963af386d05d79de0f155573ad90afbc1aff0f18905f22323f1c0bee15130e9486ede985c913a29f3c24d4f38e264d5ea7a55bc7049cf37b8b85ea1b13105be38eaefc2a35acfc9eaa75de0493ae610ed84a1f391196b3006a7029aa213e91d6cef1fdbbaa060befab8613fa680cee8a3f0829009872400a24516c2b56d93aa55019d1bffa8743d412a1125cec70d54d501791a3c03fb8380999d3a85e91849f87fa6721055dcb55295ee9ab452aa995b86b1c7b82f17e34d601bbd297b27462adbc2c4168207275b337bc0a7ab4aaea6d3e068bca9735f274c2b1b8677ade6017b777b7341a2ee2e6e6718b0fe102178ab13cc6b8165002745d50f6f8346e385509f678e5ace30ff7e97a4f0a7e6788f0722d8d3060edd8bf157b20414cb169dc44fc9293e3e3dee37dc41ad24201d6c090c8675742e8858cc21e3aa634c52ec1d4f1d16eb3c8b920b921649669e5839e4194ba233ab27d6d30e78f8aec4d70f4c5da8984617e26466039f299322b31db5db5b5a8c2661c1bddf2c8003310a79dab32922bcea8f2290c521726817242404918e1cdd09c8f696eb9ec3066de5868353cc50b0499059619a7001cc957d3b1a2fb4494f9f9eec5b2eff16e2965927fbea0c6f3bf87e6265385aa2b3943e3901aa97e518f4147318de38e185b49dbe16980859dcfa53bfec7b735882bf64c8800a260c35076e2fefaae43f70cb8a33d9742e90a275fbe4862244e2f68a0fbeef0919a38ed7ae77d1120762804653767c3157887ec1b5ed3437d9791ef7bfdb8ff16d3ee33b682fb056341b0b2b96a452dc3e8ef28f15d501778a47bb29651fc46e4ed8e9f443a9b63ece9112f503d310a908325fe6ee14103902dc2c8c09bd42e2aafb6f7344cee2c5a871cbf9d77e622e0d3404c92efbc36d740df85866990c7657221af7cb163e2ad4e01ac12e8eebbcb91bffdeaa6c36a2513f00af2391c3e9128971abc5da983e9a92c75a91a54df121bac623a2c1801660e8518542f41ed7a5d62d4bfcc81a61fbdd53a17b3429a385f83e249f024b551d2912668f2f478aaded3ade6327c0983027ee9c9d32d95109a9c668f29860fc4be68ef58a18c95bf309e59efd151095a0743fe061a787b7068a1e301c552dcfb43218a72db419984dafa33c3d039fc4dcd1c3bade575c4d27abfb48c2efdd347573f76c72206bcce7aa96f1d0693b038cd31c8f0a5a238925298d0e68dc2bb8359ffe986695a93b55dd4b665c614c91ab4097ac9a3562be56c7119363079c32ea000bd4ce0731e86940e8122b3b2a5c55a23d5c35acccdfbbd5a77fb1aad9fa2ff0f3e2a254db008a499862c939f57c19f75227c62068fa1b2e55f5a1729bf388bb522f0192bfb6a91fcb8a140f054286bf0f7f338c1419cec2d913d1fa2f86770b02b0b810ae706344872180d60d923e8e6982561abbab0ecabed27bf86fbebfadb2387a183a57410ffcc633f589f476e52a11f997530a82aac299ae068afaaedb948da294e641071ffb3539a024e883c50c87c47e08f5ee83b1644a4d81d47300f9d6260a8dccead8c1222a6e6013fffe41f3a21846f6e5e71b9ea4acbe57895ec3727f511d55921c7e8e3fe47c34748a716695f5db6c855a70b39a73231a201763cc6d1cb746c7c22252a813d71024fd8f074019f6e74cb9bdf07bb9483548e13d31c3961f06abbac08b3ecff38b1af3c0ff168d43aeaa6a3bb66cb8d51b0fbef8904f618bb75e4b694078317afaeca1b04c55e579ebb39dde29e01cd963cea5b89a01fccb6ad4ccabf72e5162d38016ae67207116d625d80516d2b067f81a9090163f1c2fcb00b6ff48bd24484d9051487defd421294fed3c69e9477e0cf24eeb42a3e5eac1d28b8b577982a7fa8b1d69205164360c6d069d5abc1f6dcd71a76242c79871dd0501cea98e0ea1b09c91c380ce87bb7d800143dfffb25d3db261fbec3eaee1b1c1194059f189bfdda2cf45bc4f253367933ba9bfab4a3296412a2510f1d477a55e94148337d65e4cebf63b37d4c348ed63fb0c7b0030fb5bfc8c51d25ab8574033c0c5fafc7398a1daba31698238b9a2f8fd1bba40481dada8bd65b40a0391bac422d983cc2a6c8045b36372d7f40d9bd6c22351585ba4c9aa20feb2288cb6c549f770d59c803be6338f5658606e7f86bc034eb8019a333a2752e1270327c042e1ea9f3c871f4b68f45f35d9e99525f08d0f36d048c5fbc8e2f2f329d6dc79dfb89335530ec30012160cb0c982a14318da8366f0c5bb80015743f758eceeef705f05349c8403eaee159060108e0ac96aa93fb7152d474b27c1109bae0edfe53df1a38e11d7ca3ae36cce3b9dc127fa4455723256d5d9f8838ac0b869a8bd3e750113589b39c1b294aaad2d77d9d1570497ee20b98feb48c1a5f829921ad120088a0a09b73596a9df3302badcdd9c3e585e547eaccd95fd7e993e93d806db22d05f43db1b08eda565b2b1e2d4f819497e02465c0438bc49186b3ea7a230860d925a2e25f66ef3e442c2f2a84afcdfd32436aa1b47c4d4759a6cc680376296c40fdff10327a7293ce79dd048c76e12727bf06a153af369478864301b7b93542fe7b33b9cb7634e199b23e863378f02db19bbdd5052e0a68e1bc1c47be840541ce70028ee283ebea54ff72877209bb950ab9b67b17593cb7bad06d68954176f58d1413430bc1f067f32762cf0e069cd2e324502df540e8c8429ef1f0b22352989e9f7e83aee65c04191e5a2001b68ccde1834e61acf0b0957b733ae68a16b1eea6572b83604ce0122020bde1ef70535d47f561ec4c11129d5f16046733ac0ec0f438113689c5d4406c98e2ec4cfb3d336e0590149d942aee8b485cb865c0e4ddfb132b61d1cf2802e6eb4128f1a421ff237ab193facfb88754501b776de9851535cb7f23c35152eb5cb2c670f83beadee623533a2a2c270ad6e8a3a8d01aee9e49d9201bb6861c82351cc65b76c5ea0a88b59a2e59c9366fd4d7d854cae911b1bb7b89d9eb2cc3bf87ab5c66aa43e2d1ce3a89f70789b303fc565d04ab638e1900a1f914fc980d86204e192e18f7ba28129d8b0674fce9c7b60ae59385f6bc5a7180d2ba8b1600e918c977844da68b39d32c6e020a5c3a21a81265a07a5ee8f01ccbaeef70ed6de1ada366dfcddfc95074a7edd535dbfa83e9b9a4980c089e4aeb9103d99b2cc230a04fc3bcbfc7c9f826b49b184465ddaa94712d470ea4f361bbd745678ce1274958a3582f75d257c6a2b1b0c108f51c111270c45e28e482e82a7cfb17c36120a09e48bdf7a0e4ab854a72528c84431bc4ae3ad025555656fef51b5683cc8b11491d39d0613b8bd47b48615dbf09e05241c964f8338c5507fd2984337fd86444457ef2d9056565045ed67d9b0a55a800249d410f2df5b144d51741fd8d16d5b628a6b558287b13a300b4121a2308135901a239b525d6a20c15ad6df83114ed163341e7e91b6d7d304b95df8d92970a458cddc801bff057ad73113ea76b33c4b2e5d588aa4199229c00db49484b6082e1a16b85ec63cade7e4f4ac65026bb69a98ddc63bd6c84e9e75c495ecf72fbdbe8161c019ac8e7440333bd72850d518a9e9254b00b050477f2bfee4827c13f10a9adafbca4ef55ad614d170c63aff6cb6bb4c3c7f7666f747bba8b296b92fd71ded31dcda3ec0f1bf290043b8d04ad0afb95d7d284e8bad046b5ced69562648edbc4ab1b1e5081be6e9e60370c8106a6fe05f1aa69554a626e1eae59f9cdbd7e5494ece7288cdfdf8d11c8918549217fd8387f39d3c2383969977ac0408f70f9fa46725c49ee0038580b68996b06bfd28cf5df84f410ea612da1974f1a658e6e1948d969714fa6f4bbff6c0f0ce83b2c238e7697c9d6aca4c28ce6e80796ec95a5db9aa2adfea54ccd23931832f9d62586f338b3c35b5a238bde5ed166ad48705032b3020c26a0b4418eb54d65a54471e911351354d9f72dce1428f3d2d9471673088a9055c5f895e7a2e527def6dab46291fdd3b168cc4a763b37cef39fd6c293e2b5fc8207d9c9901a9448758c7e3e7535c693aabef6ac6061ba3e76b4b3b74d00081ff70cbc875ca9e46fef78315577738a5666182a66e71ada8fa7f23b1143e6c6a7a61250faab23d777854a41591ba7bc10b6d62353f34bccd64a8616b49b83fa6b37609137599ce65043c65d83ca9391c09781498ddddf15207fe93caaa83d9179058d676e1cf0f21c44748220bf0c1631370b456ba052069e769bf5236e8076ba4a93100595f1a83928e8bca9f469456d4788aa5957039cee868d993d5342d1d75a746cca800c0c13a3827ee66f9ab902898faa64a0dac827e5ac68b32d35872cd7331e44f9d710105dffe51422f88f2e88a3bad31ee6a0f00a51b98f7e9f8c09217707d008f324d1bd751def8595f9a0b8e5cd03119ef242c896812249bca7d04954bf19d1b80121ef0d95ef384f1d2e3b1b246de4bf107ec9a5cf9dc22b858f66cfa5e79231c0154b9a8d99de8e3b395e73563bbda8e8440bb7d528fdde1ce1a4c4b3406609d9d021555fb466699bba0f26ac42b253e9b4626d732d250da3a340db151fa414cd1efbeaeed7b01c7012726a43d1bd9c5f3d28923f4a713e5f44f984d93588e041f8b4d2240ece8a4a2e94cfbd131197efe45b7811a7667c154c69aa0a5821d0688b298de014f6af3043fd827b92c70d012f13f7460d6357fb99c1dd51800790df9dc4f21180b2d8d1c436311fea43232401429440e05f403c1a9e1f5e643194ea70764b22d0e8204e0c6cc3bcc65d6b397b093dbe87eb639baa773ffeec4a503da4443421b414990da7a682250a4b09a4a6c8a11529d8308772333826a21cb25266055050b7e6e4019be236459f9d877faa12ac737416acd9af53c0cf743a8b719c2e092c6c9c458d171e2b641c36c6e3b83d00f48f11f6e2862fc42380f3ba507163f905cf34b507d9cd1e8cc225e2c6cf167a694db1568627fb104620cc68c44c76111e54a09ee5e8b1a89e269f7cb83ed27aa4bbb19184e80bce0a51998fb5b674b81708c47862a78ac1ad6f3b36619f8dba482a4c0a1603e110cfd07eb1fe7b7f36047102f95a9fd594349927708d308fc5f9911a54a8cd63b68b9bbef62abc34bf7dc3d97d24e524d3a12680c3267a6443f22816e19c925b314387880a4a65c3370abd51d6a699c9e10f9413ae75e82512d93b2422ac4681ae84368d18aa063f92a1807c635a4d046c3c5598c5ef74df5c2b253bc0bb98bc978622b4324abd6a8389e233ee1192fa6f8fdfd3728b271d2b839cfbb6f52e20ad5329b59b06374ad784e91e7f62ba792145a8c6edc480ab20bc268d7bc4888bf76eff9f4ca3b06b41fca5217d8b29e08457483e5f1211f2d654d4eb0309e0dfc9bb38b006b79acbea878866a9499cd1baf4c3468f4cb7c5b76b6d870ffc884f4ce3a22e2f45c111dcbd75c829fa15f61b7c6b7eddb79bc449149f3aa5638c4f28baa1b0fa673724b3a48743758df2c9c0f7756f4b6a048620b77dbd29a4701f60293def305c305a39bac14c14a35b0315a7b04a2c40aef9fb1a848c4d66c12bb27a8bc69ff3b645ee9403d2414c97a22e8d89d5d93a79b52209b1bf49e373294418f36d4dd688eacc1f9dfcf6b1f6f463f6bc591fc154b5abff77507ac0feedbde2ec46ad379adc0f0ab4140093dc0ffd8eaaee1bc70e3d9f4b24229d1a89c1469f8e4502826fa797f4242d830bcd3800539a138a1df272ee0420843a0ea4f216ea4f03eef09e948db17583d32475797568bcb3e72f802bd6a31ac83dfa1c46a8e195db181c24a783048ee4037e5dd1aabf477afe7412b3aba276cb74e56367267d14ba4510ef15f35950c5d29f7609285f5aa9f19615e13c188a93cea9f9ee9531b20f6690da9eb4cb3e22a6073e6986af58f77ed6136a9fbcdba6c6f4d3978b3dd9faf4ca843d025108733ca9be07034e6834cfb9c5c1cce85059903b281a4f2fb816d6e39d9f4a0794a09efc071e94cd2d0eb9a408d12dbde33d1ecccc14ecc7683282c7ee8f9007ac1106a8501f3e6a2c4dadfc0de93090820f3a66e239d2b84f7256e37dde366afcffd84a0a76bad5430e69464c1542cc891342ae8a4f1f5f4f07ec6fa2dac8298bdec6b2b6f802a1a5ec3f79ded63c201994253ceb3848eb46ebc4210e13d8d4630647c5336fe8b4c6698d9e7b775508a25e87884b937ff04b6f34b4efba7265bb4e96d543ede1f0a4caefd079a85bbb7b2e39096d37d8451027056573b9c511850d1de604b98c79a0042d0282480d05094af7a9f885e0180d7ca25c366796b3ba7f3d050763bd3a4ab18d273fb16dd0b6794e7e56565098e4257d37a01c3d4edb1d1c8df1829889116cf407f75d79db4b60d8298dce2c248c73735e0feef2587de81ea9e9d32b01ff40514cac700f261a131646bccec7fa72feda2356d8e776ed2b077bdfd32fa49ae6736af49410e5f151db09e3da2b50ff9bb67b051068a792d782e731e3bf71e8312cf620036875b4d1c94f529e604393514b8d206d1d5101c9893b0d1e343c6b5ab8079013508411df48b0b04c7f189f65bb9e45599675562bb84453773aff798cca6c5ee78f612638cfc8b3cd78a9cbc31d606afbad9008c66e4b45ab0d5231884bfdc6ac2d9f0b62fea76e01c68f29760738f727dff9016ec6ae2cf95dd49bd8c82831845f2061ac17c391130b1683650cf387360123edc6e0591448ce9cc238ace5898841d5dcddce5b142daac099c032d6e3a4ba0de405a56a3bb41a20ebe68881501677c52f6ea02bff0ece75344ebd0d48dd9be71ae1fc99452f056060c2a31e96e55f1e06fc9afdf71bc72dddf66ce470dd9affa552722fc382995676a59c870bf607fa08e272314c85121c459f078067113fbcdf1c8d8105bf50a91f73f0dfdd946e2f5411dfe1f6ec309f7d69f062b6027aac1e721212c7d37f7192f39efc5d0a07434ad43c71d8791b8e57e64ee813d85d0982bb716d32be2e821e9431139316efe4a3c25c27d5a430121bfd587356435b88ac34183f0c1319236eb2f5443dcfa24fc53740ee72aef902f2b9490384255435a0aed5054ad2b616e4fbff9ac74f6081978b61cf198912d4995835aa8e276d5fd289aafafa10c3c4fefc72c053ad7345150436b4a552d14ea6c03219adcdeb75717f84cbb0740a75a663e02f56d75fdcbaa6d59a7a3212a8094cd029238d4e753b24c9f62183f7840cde52cb036fee66fe6d6656c810cc2587253f319b6f4ae3bf184646de22368ae1a9cfedc4ff87eac3600ec50db0d3064b9fe20dd1f43d7d1dd04b8975b7bb3ec529f01f8ecbe7a40faebac8b32b691093e3291c7334b291345c5c17214aac08a2381345f871c3f054d6533cbdd723381286c63211e67f2d6f07e2c410c0f7e6e8c53524d49ed0c5d3f69017fad9354223731673cedd693307fddf4001f7295a1f0935b60a1d8f18c401689051fa4cb13948d8c7b0cc89d52cd66ede51162377224dafe1d6f70384f6c26cd19fa4f90c1268e18fc240d271d52d6689b20f9d60a67787bc582569d7693e3f1eaa9ff9914dd38c13830d3b1b4a351b0fecf7022e5057c15d6e524ffa0be29604eb8318d6278f5fc504db78ca302b9de0e5bf31d5a93fb757754e275acd20c13ef7fcd3e8454a3eb26eb0a3954afd6e064aee227f4cce9393aec1d1320ed7ed8235c457e848d41876be4849fe595098f1c41f6f750ccc221b1d2f09d55c671cc7f6075d1dc4b4af13dc08597abfe2c999c15f0fb66083030a1fbbed1f0dc17b4411f4be5a663cd2447675f95d56913eb08407f11952f424a79c04a6aa436f085f0bd7c5e3eaf6ed184770d581785a40cc2ffbc658191f132079adb666a675fc2c1411bdab69e0fb86e6b590a89b1e82d25d914303febe529529f04235a328e3d6374bffe0bca8b27f84582fda4448bddaec5cceb09e652f5c79f7d6c6b9fa3453f7a7bacbffd1ad4b83ca4b4f552d8d9fe9bb41ecf23a8987bfef98c05cead9864355b481adbe1acce9f6924199f993055617ab97ec7373559db6b8a0fd8eabd512965f9b77eac4fe80e8c2af17435f87f6099b1e47e5dd843f5e1c2cac227c9c69852a89db3e2a6a65aa1eebed886a7375857a774ecedf8fc3325069ba67b6676497af1addbf9f6ce7a3518ff0ab93368710f61b3cc6a14509a983b55003892905a681568d95bbb89b64f79b7462312e35f7b85911839e90c3107e53dabe5926f2dc9e3090c5bccc01d6e1347e4c3c26e4a783fe7bd066ef5a718cb4cd08179102dda698fbfc34d65873c0ba852e3bf9b02a441675ef5f7f024837df126e3a86fa3be5e26a2dd4cbf6d3a319700ce8ed955b9d4e6320f6acb714074d11c5cebe8b085237cf5ff8c1dfc498093dbfe78cb5b6ded6dfa4f8852af675bd7f00f3ac431c2f0a0079274d72ef9620798f3eb817da3de6dad8e0cb8b77cbb89cc8ad259f3434d7613383f529e247ece48e1dd61e8f3bb57174992aab32ee9cb7416f2f2f3cd7b7721356df5c6886fc8e57854cfdc45649821a931e483566ad18cd7c1f3fae6c2e2d4a1ae2f4d30334d16eb349b7cd6ad4149530de1b124565650e64c505efc12f027edfd21b9d090f034bfeac00accdd380ae4755e63d9215e74af8305733e9e6521b2cae0af1e1ef9000a0b76f9887576442d6dd46a3fe81586037dffb33ba9a46c6c6066d41a7dd2bf32c89d7b0b4255df16ef2117e90d5445284dfbb6d7f86b7729f7638d9674c113d3c70facc9718362057455a52577d1c8eb80cb785d27414f787fc3eb3666e2b6b6beaff30b0ff15833c2100701492e8f6b0b7b52fa0902a8db8465a3cb7e94b7bb2b38b9a571c4c49f0f181e7aa297d566ee6d4dd83b593f7fb7cff7da88986bace5cc55cbcfa01b2146066bbb8d513d3a95de226ad65706ad594d6ae3346812ee9e4d878ab40e8659f0e2caaca3ce2abc778f94dd86b436417bf4cd46c49953817c35297a9e6dc07c6136120200a2375d1dc51fa38693998986b8d12ffbb17f1be073b0fafc044b11c71a56a58f85e6c0f42da219</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>
    
    
    <summary type="html">这是一篇加密文章，需要密码才能继续阅读。</summary>
    
    
    
    <category term="学习笔记" scheme="https://blog.jishuqin.cn/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="private" scheme="https://blog.jishuqin.cn/tags/private/"/>
    
  </entry>
  
  <entry>
    <title>大话设计模式</title>
    <link href="https://blog.jishuqin.cn/posts/4a5b6c7d/"/>
    <id>https://blog.jishuqin.cn/posts/4a5b6c7d/</id>
    <published>2023-05-20T20:20:00.000Z</published>
    <updated>2025-09-03T08:59:30.029Z</updated>
    
    <content type="html"><![CDATA[<h2 id="大话设计模式">大话设计模式</h2><p class="note note-primary">此文为我学习大话设计模式时的笔记，代码样例也是书里的。这本书对学习理解设计模式还是挺有帮助，推荐大家可以看看~</p><h3 id="第-0-章-面向对象基础">第 0 章 面向对象基础</h3><h4 id="1-类与实例">1. 类与实例</h4><p>万物皆对象，对象是一个自包含的实体，用一组可识别的特性和行为来标识。</p><p>类就是具有相同的属性和功能的对象的抽象的集合。</p><p>实例，就是一个真实的对象。而实例化就是创建对象的过程，使用new关键字来创建。</p><h4 id="2-构造方法">2. 构造方法</h4><p>构造方法，又叫构造函数，其实就是对类进行初始化。构造方法与类同名，无返回值，也不需要void，在 new 的使用调用。</p><p>所有类都有构造方法，如果你不编码则系统默认生成空的构造方法，若你有定义的构造方法，那么默认的构造方法就会失效了。</p><h4 id="3-方法重载">3. 方法重载</h4><p>方法重载提供了创建同名的多个方法的能力，但这些方法需使用不同的参数类型。</p><p>方法重载时，需方法名相同，但参数类型或个数必须要有所不同。</p><p>方法重载可在不改变原方法的基础上，新增功能。</p><h4 id="4-属性与修饰符">4. 属性与修饰符</h4><p>属性是一个方法或一对方法，即属性适合于以字段的方式使用方法调用的场合。</p><p>字段是存储类要满足其设计所需要的数据，字段是与类相关的变量。</p><h4 id="5-封装">5. 封装</h4><p>每个对象都包含它能进行操作所需要的所有信息，这个特性称为封装，因此对象不必依赖其他对象来完成自己的操作。</p><p>封装有多个好处：</p><ul><li>良好的封装能够减少耦合。</li><li>类内部的实现可以自由地修改。</li><li>类具有清晰的对外接口。</li></ul><h4 id="6-继承">6. 继承</h4><p>对象的继承代表了一种‘is-a’的关系，如果两个对象A和B，可以描述为‘B是A’，则表明B可以继承A。</p><p>继承者还可以理解为是对被继承者的特殊化，因为它除了具备被继承者的特性外，还具备自己独有的个性。</p><p>继承定义了类如何相互关联，共享特性。</p><p>继承的工作方式是：定义父类和子类，或叫作基类和派生类，其中子类继承父类的所有特性。</p><p>子类不但继承了父类的所有特性，还可以定义新的特性。</p><p>如果子类继承与父类：</p><ul><li>子类拥有父类非 private 的属性和功能</li><li>子类具有自己的属性和功能，即子类可以扩展父类没有的属性和功能</li><li>子类还可以以自己的方式实现父类的功能（方法重写）</li></ul><h3 id="第-1-章-简单工厂模式">第 1 章 简单工厂模式</h3><p>题目：请用C++、Java、C#或Python等任意一种面向对象语言实现一个计算器控制台程序，要去输入两个数和运算符号，得到结果。</p><p>​<img src="https://cdn.gumengyo.top//image-20230424201833506.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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><span class="line">83</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">import</span> java.util.*;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 顾梦</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@create</span> 2023/4/24</span><br><span class="hljs-comment"> * 简单工厂模式 实现简单计算器</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">SimpleFactory</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Scanner</span> <span class="hljs-variable">sc</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Scanner</span>(System.in);<br><br>        System.out.println(<span class="hljs-string">&quot;请输入数字A: &quot;</span>);<br>        <span class="hljs-type">double</span> <span class="hljs-variable">numberA</span> <span class="hljs-operator">=</span> Double.parseDouble(sc.nextLine());<br>        System.out.println(<span class="hljs-string">&quot;请选择运算符号(+、-、*、/): &quot;</span>);<br>        <span class="hljs-type">String</span> <span class="hljs-variable">strOperate</span> <span class="hljs-operator">=</span> sc.nextLine();<br>        System.out.println(<span class="hljs-string">&quot;请输入数字B: &quot;</span>);<br>        <span class="hljs-type">double</span> <span class="hljs-variable">numberB</span> <span class="hljs-operator">=</span> Double.parseDouble(sc.nextLine());<br><br>        <span class="hljs-type">Operation</span> <span class="hljs-variable">operate</span> <span class="hljs-operator">=</span> OperationFactory.createOperate(strOperate);<br>        <span class="hljs-type">double</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> operate.getResult(numberA, numberB);<br><br>        System.out.println(<span class="hljs-string">&quot;结果是: &quot;</span> + result);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">OperationFactory</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Operation <span class="hljs-title function_">createOperate</span><span class="hljs-params">(String operate)</span> &#123;<br>        <span class="hljs-type">Operation</span> <span class="hljs-variable">oper</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br>        <span class="hljs-keyword">switch</span> (operate) &#123;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;+&quot;</span>:<br>                oper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Add</span>();<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;-&quot;</span>:<br>                oper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Sub</span>();<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;*&quot;</span>:<br>                oper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Mul</span>();<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;/&quot;</span>:<br>                oper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Div</span>();<br>                <span class="hljs-keyword">break</span>;<br>        &#125;<br>        <span class="hljs-keyword">return</span> oper;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Operation</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> numberA, <span class="hljs-type">double</span> numberB)</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-number">0d</span>;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Add</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Operation</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> numberA, <span class="hljs-type">double</span> numberB)</span> &#123;<br>        <span class="hljs-keyword">return</span> numberA + numberB;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Sub</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Operation</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> numberA, <span class="hljs-type">double</span> numberB)</span> &#123;<br>        <span class="hljs-keyword">return</span> numberA + numberB;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Mul</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Operation</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> numberA, <span class="hljs-type">double</span> numberB)</span> &#123;<br>        <span class="hljs-keyword">return</span> numberA * numberB;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Div</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Operation</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> numberA, <span class="hljs-type">double</span> numberB)</span> &#123;<br>        <span class="hljs-keyword">if</span> (numberB == <span class="hljs-number">0</span>) &#123;<br>            System.out.println(<span class="hljs-string">&quot;除数不能为0&quot;</span>);<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArithmeticException</span>();<br>        &#125;<br>        <span class="hljs-keyword">return</span> numberA / numberB;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><h3 id="第-2-章-策略模式">第 2 章 策略模式</h3><p><strong>策略模式（Strategy）：它定义了算法家族，分别封装起来，让它们之间可以互相替换，此模式让算法的变化，不会影响到使用算法的客户。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230428085826966.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">import</span> java.util.*;<br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 顾梦</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@create</span> 2023/4/27</span><br><span class="hljs-comment"> * 策略模式 解决商场收银问题</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">StrategyPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br><br>        <span class="hljs-type">double</span> <span class="hljs-variable">price</span> <span class="hljs-operator">=</span> <span class="hljs-number">0d</span>; <span class="hljs-comment">// 商品单价</span><br>        <span class="hljs-type">int</span> <span class="hljs-variable">num</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;    <span class="hljs-comment">// 商品购买数量</span><br>        <span class="hljs-type">double</span> <span class="hljs-variable">totalPrices</span> <span class="hljs-operator">=</span> <span class="hljs-number">0d</span>; <span class="hljs-comment">// 当前商品合计费用</span><br>        <span class="hljs-type">double</span> <span class="hljs-variable">total</span> <span class="hljs-operator">=</span> <span class="hljs-number">0d</span>;  <span class="hljs-comment">// 总计所有商品费用</span><br><br>        <span class="hljs-type">Scanner</span> <span class="hljs-variable">sc</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Scanner</span>(System.in);<br>        <span class="hljs-keyword">do</span> &#123;<br>            System.out.println(<span class="hljs-string">&quot;请输入商品销售模式 1.原价 2.八折 3.满300返100&quot;</span>);<br>            <span class="hljs-type">int</span> <span class="hljs-variable">discount</span> <span class="hljs-operator">=</span> Integer.parseInt(sc.nextLine());<br>            System.out.println(<span class="hljs-string">&quot;请输入商品单价：&quot;</span>);<br>            price = Double.parseDouble(sc.nextLine());<br>            System.out.println(<span class="hljs-string">&quot;请输入商品数量：&quot;</span>);<br>            num = Integer.parseInt(sc.nextLine());<br>            System.out.println();<br><br>            <span class="hljs-keyword">if</span> (price &gt; <span class="hljs-number">0</span> &amp;&amp; num &gt; <span class="hljs-number">0</span>)&#123;<br>                <span class="hljs-type">CashContext</span> <span class="hljs-variable">cc</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashContext</span>(discount);<br>                totalPrices = cc.getResult(price, num);<br>                total = total + totalPrices;<br><br>                System.out.println();<br>                System.out.println(<span class="hljs-string">&quot;单价：&quot;</span> + price +<span class="hljs-string">&quot;元，数量：&quot;</span> + num + <span class="hljs-string">&quot; 合计：&quot;</span> + totalPrices + <span class="hljs-string">&quot;元&quot;</span>);<br>                System.out.println();<br>                System.out.println(<span class="hljs-string">&quot;总计：&quot;</span> + total + <span class="hljs-string">&quot;元&quot;</span>);<br>                System.out.println();<br>            &#125;<br><br>        &#125;<span class="hljs-keyword">while</span> (price &gt; <span class="hljs-number">0</span> &amp;&amp; num &gt; <span class="hljs-number">0</span>);<br><br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 收费抽象类</span><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">CashSuper</span>&#123;<br><br>    <span class="hljs-comment">// 收取费用的抽象方法，参数为单价和数量</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-type">double</span> <span class="hljs-title function_">acceptCash</span><span class="hljs-params">(<span class="hljs-type">double</span> price,<span class="hljs-type">int</span> num)</span>;<br>&#125;<br><br><span class="hljs-comment">// 正常收费</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">CashNormal</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">CashSuper</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">acceptCash</span><span class="hljs-params">(<span class="hljs-type">double</span> price, <span class="hljs-type">int</span> num)</span> &#123;<br>        <span class="hljs-keyword">return</span> price * num;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">CashRebate</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">CashSuper</span>&#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">double</span> <span class="hljs-variable">moneyRebate</span> <span class="hljs-operator">=</span> <span class="hljs-number">1d</span>;<br><br>    <span class="hljs-comment">// 初始化时必须输入折扣率。八折就输入0.8</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">CashRebate</span><span class="hljs-params">(<span class="hljs-type">double</span> moneyRebate)</span>&#123;<br>        <span class="hljs-built_in">this</span>.moneyRebate = moneyRebate;<br>    &#125;<br><br>    <span class="hljs-comment">// 计算收费时需要在原价基础上乘以折扣率</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">acceptCash</span><span class="hljs-params">(<span class="hljs-type">double</span> price, <span class="hljs-type">int</span> num)</span> &#123;<br>        <span class="hljs-keyword">return</span> price * num * <span class="hljs-built_in">this</span>.moneyRebate;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">CashReturn</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">CashSuper</span>&#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">double</span> <span class="hljs-variable">moneyCondition</span> <span class="hljs-operator">=</span> <span class="hljs-number">0d</span>; <span class="hljs-comment">// 返利条件</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">double</span> <span class="hljs-variable">moneyReturn</span> <span class="hljs-operator">=</span> <span class="hljs-number">0d</span>; <span class="hljs-comment">// 返利值</span><br><br>    <span class="hljs-comment">// 返利收费。初始化时需要输入返利条件和返利值。</span><br>    <span class="hljs-comment">// 比如&quot;满300返100&quot;，就是moneyCondition=300，moneyReturn100</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">CashReturn</span><span class="hljs-params">(<span class="hljs-type">double</span> moneyCondition, <span class="hljs-type">double</span> moneyReturn)</span> &#123;<br>        <span class="hljs-built_in">this</span>.moneyCondition = moneyCondition;<br>        <span class="hljs-built_in">this</span>.moneyReturn = moneyReturn;<br>    &#125;<br><br>    <span class="hljs-comment">// 计算收费时，当达到返利条件，就原价减去返利值</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">acceptCash</span><span class="hljs-params">(<span class="hljs-type">double</span> price, <span class="hljs-type">int</span> num)</span> &#123;<br>        <span class="hljs-type">double</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> price * num;<br>        <span class="hljs-keyword">if</span> (moneyCondition &gt; <span class="hljs-number">0</span> &amp;&amp; price &gt;= moneyCondition)&#123;<br>            result = result - Math.floor(result / moneyCondition) * moneyReturn;<br>        &#125;<br>        <span class="hljs-keyword">return</span> result;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">CashContext</span>&#123;<br>    <span class="hljs-keyword">private</span> CashSuper cs; <span class="hljs-comment">// 声明一个CashSuper对象</span><br><br>    <span class="hljs-comment">// 通过构造方法，传入具体的收费策略</span><br><span class="hljs-comment">//    public CashContext(CashSuper csuper)&#123;</span><br><span class="hljs-comment">//        this.cs = csuper;</span><br><span class="hljs-comment">//    &#125;</span><br><br>    <span class="hljs-comment">// 结合简单工厂模式</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">CashContext</span><span class="hljs-params">(<span class="hljs-type">int</span> cashType)</span>&#123;<br>        <span class="hljs-keyword">switch</span> (cashType)&#123;<br>            <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:<br>                <span class="hljs-built_in">this</span>.cs = <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashNormal</span>();<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:<br>                <span class="hljs-built_in">this</span>.cs = <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashRebate</span>(<span class="hljs-number">0.8d</span>);<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-number">3</span>:<br>                <span class="hljs-built_in">this</span>.cs = <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashReturn</span>(<span class="hljs-number">300d</span>,<span class="hljs-number">100d</span>);<br>                <span class="hljs-keyword">break</span>;<br>        &#125;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> price, <span class="hljs-type">int</span> num)</span> &#123;<br>        <span class="hljs-comment">// 根据收费策略的不同，获得计算结果</span><br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.cs.acceptCash(price, num);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><h3 id="第-3-章-单一职责原则">第 3 章 单一职责原则</h3><p><strong>单一职责原则（SRP），就一个类而言，应该仅有一个引起它变化的原因。</strong></p><ul><li>如果一个类承担的职责过多，就等于把这些职责耦合在一起，一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计，当变化发生时，设计会遭受到意想不到的破坏。</li><li>软件设计真正要做的许多内容，就是发现职责并把那么些职责相互分离。</li><li>如果你能够想到多于一个的动机去改变一个类，那么这个类就是具有多于一个的职责。</li></ul><h3 id="第-4-章-开放-封闭原则">第 4 章 开放-封闭原则</h3><p><strong>开放-封闭原则，是说软件实体（类、模块、函数等）应该可以扩展，但是不可修改。</strong></p><ul><li>对于扩展是开放的（Open for extension)</li><li>对于修改是封闭的（Closed for modification）</li></ul><p><img src="https://cdn.gumengyo.top//image-20230428090233389.png" srcset="/img/loading.gif" lazyload alt=""></p><p>开放-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处，也就是可维护、可扩展、可复用、灵活性好。</p><h3 id="第-5-章-依赖倒转原则">第 5 章 依赖倒转原则</h3><p>依赖倒转原则：</p><ul><li>高层模块不应该依赖低层模块。两个都应该依赖抽象。</li><li>抽象不应该依赖细节。细节应该依赖抽象。</li></ul><p>里氏代换原则（LSP）：子类型必须能够替换掉它们的父类型。</p><p>由于子类型的可替换性才使得使用父类类型的模块在无须修改的情况下就可以扩展。</p><p><img src="https://cdn.gumengyo.top//image-20230428092805695.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="第-6-章-装饰模式">第 6 章 装饰模式</h3><p><strong>装饰模式（Decorator），动态地给一个对象添加一些额外的职责，就增加功能来说，装饰模式比生成子类更为灵活。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230428141827346.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 顾梦</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@create</span> 2023/4/28</span><br><span class="hljs-comment"> * 装饰模式</span><br><span class="hljs-comment"> */</span><br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">DecoratorPattern</span> &#123;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">ConcreteComponent</span> <span class="hljs-variable">c</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteComponent</span>();<br>        <span class="hljs-type">ConcreteDecoratorA</span> <span class="hljs-variable">d1</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteDecoratorA</span>();<br>        <span class="hljs-type">ConcreteDecoratorB</span> <span class="hljs-variable">d2</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteDecoratorB</span>();<br><br>        d1.SetComponent(c); <span class="hljs-comment">// 首先用d1来包装c</span><br>        d2.SetComponent(d1); <span class="hljs-comment">// 再用d2来包装d1</span><br>        d2.Operation(); <span class="hljs-comment">// 最终执行d2的Operation()</span><br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Component</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">Operation</span><span class="hljs-params">()</span>;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteComponent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Component</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">Operation</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;具体对象的实际操作&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Decorator</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Component</span>&#123;<br>    <span class="hljs-keyword">protected</span> Component component;<br><br>    <span class="hljs-comment">// 装饰一个Component 对象</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">SetComponent</span><span class="hljs-params">(Component component)</span>&#123;<br>        <span class="hljs-built_in">this</span>.component = component;<br>    &#125;<br><br>    <span class="hljs-comment">// 重写Operation()，实际调用component的Operation方法</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">Operation</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">if</span> (component != <span class="hljs-literal">null</span>)&#123;<br>            component.Operation();;<br>        &#125;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteDecoratorA</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Decorator</span>&#123;<br><br>    <span class="hljs-keyword">protected</span> String addedState; <span class="hljs-comment">// 本类独有字字段，以区别于ConcreteDecoratorB类</span><br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">Operation</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-built_in">super</span>.Operation();  <span class="hljs-comment">// 首先运行了原有Component的Operation()</span><br><br>        <span class="hljs-built_in">this</span>.addedState = <span class="hljs-string">&quot;具有装饰对象A的独有操作&quot;</span>; <span class="hljs-comment">// 再执行本类独有的功能</span><br>        System.out.println(<span class="hljs-built_in">this</span>.addedState);<br><br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteDecoratorB</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Decorator</span>&#123;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">Operation</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-built_in">super</span>.Operation(); <span class="hljs-comment">// 首先运行了原有Component的Operation()</span><br>        <span class="hljs-built_in">this</span>.AddedBehavior(); <span class="hljs-comment">// 再执行本类独有功能</span><br>    &#125;<br><br>    <span class="hljs-comment">// 本类独有方法，以区别于ConcreteDecoratorA类</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">AddedBehavior</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;具有装饰对象B的独有操作&quot;</span>);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p><strong>商场促销——简单工厂+策略+装饰模式实现</strong></p><p><img src="https://cdn.gumengyo.top//image-20230428141722534.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuin;<br><br><span class="hljs-keyword">import</span> java.util.*;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 顾梦</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@create</span> 2023/4/28</span><br><span class="hljs-comment"> * 商场促销——简单工厂+策略+装饰模式</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Promotion</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;**********************************************&quot;</span>);<br>        System.out.println(<span class="hljs-string">&quot;《大话设计模式》代码样例&quot;</span>);<br>        System.out.println();<br><br>        <span class="hljs-type">int</span> <span class="hljs-variable">discount</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;         <span class="hljs-comment">//商品折扣模式</span><br>        <span class="hljs-type">double</span> <span class="hljs-variable">price</span> <span class="hljs-operator">=</span> <span class="hljs-number">0d</span>;         <span class="hljs-comment">//商品单价</span><br>        <span class="hljs-type">int</span> <span class="hljs-variable">num</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;            <span class="hljs-comment">//商品购买数量</span><br>        <span class="hljs-type">double</span> <span class="hljs-variable">totalPrices</span> <span class="hljs-operator">=</span> <span class="hljs-number">0d</span>;<span class="hljs-comment">//当前商品合计费用</span><br>        <span class="hljs-type">double</span> <span class="hljs-variable">total</span> <span class="hljs-operator">=</span> <span class="hljs-number">0d</span>;        <span class="hljs-comment">//总计所有商品费用</span><br><br>        <span class="hljs-type">Scanner</span> <span class="hljs-variable">sc</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Scanner</span>(System.in);<br><br>        <span class="hljs-keyword">do</span> &#123;<br>            System.out.println(<span class="hljs-string">&quot;商品折扣模式如下:&quot;</span>);<br>            System.out.println(<span class="hljs-string">&quot;1.正常收费&quot;</span>);<br>            System.out.println(<span class="hljs-string">&quot;2.打八折&quot;</span>);<br>            System.out.println(<span class="hljs-string">&quot;3.打七折&quot;</span>);<br>            System.out.println(<span class="hljs-string">&quot;4.满300送100&quot;</span>);<br>            System.out.println(<span class="hljs-string">&quot;5.先打8折，再满300送100&quot;</span>);<br>            System.out.println(<span class="hljs-string">&quot;6.先满200送50，再打7折&quot;</span>);<br>            System.out.println(<span class="hljs-string">&quot;请输入商品折扣模式:&quot;</span>);<br>            discount = Integer.parseInt(sc.nextLine());<br>            System.out.println(<span class="hljs-string">&quot;请输入商品单价：&quot;</span>);<br>            price = Double.parseDouble(sc.nextLine());<br>            System.out.println(<span class="hljs-string">&quot;请输入商品数量：&quot;</span>);<br>            num = Integer.parseInt(sc.nextLine());<br>            System.out.println();<br><br>            <span class="hljs-keyword">if</span> (price&gt;<span class="hljs-number">0</span> &amp;&amp; num&gt;<span class="hljs-number">0</span>)&#123;<br><br>                <span class="hljs-comment">//根据用户输入，将对应的策略对象作为参数传入CashContext对象中</span><br>                <span class="hljs-type">CashContext</span> <span class="hljs-variable">cc</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashContext</span>(discount);<br><br>                <span class="hljs-comment">//通过Context的getResult方法的调用，可以得到收取费用的结果</span><br>                <span class="hljs-comment">//让具体算法与客户进行了隔离</span><br>                totalPrices = cc.getResult(price,num);<br><br>                total = total + totalPrices;<br><br>                System.out.println();<br>                System.out.println(<span class="hljs-string">&quot;单价：&quot;</span>+ price + <span class="hljs-string">&quot;元 数量：&quot;</span>+ num +<span class="hljs-string">&quot; 合计：&quot;</span>+ totalPrices +<span class="hljs-string">&quot;元&quot;</span>);<br>                System.out.println();<br>                System.out.println(<span class="hljs-string">&quot;总计：&quot;</span>+ total+<span class="hljs-string">&quot;元&quot;</span>);<br>                System.out.println();<br>            &#125;<br>        &#125;<br>        <span class="hljs-keyword">while</span>(price&gt;<span class="hljs-number">0</span> &amp;&amp; num&gt;<span class="hljs-number">0</span>);<br><br>        System.out.println();<br>        System.out.println(<span class="hljs-string">&quot;**********************************************&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">interface</span> <span class="hljs-title class_">ISale</span> &#123;<br>    <span class="hljs-type">double</span> <span class="hljs-title function_">acceptCash</span><span class="hljs-params">(<span class="hljs-type">double</span> price,<span class="hljs-type">int</span> num)</span>;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">CashSuper</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">ISale</span> &#123;<br><br>    <span class="hljs-keyword">protected</span> ISale component;<br><br>    <span class="hljs-comment">//装饰对象</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">decorate</span><span class="hljs-params">(ISale component)</span> &#123;<br>        <span class="hljs-built_in">this</span>.component=component;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">acceptCash</span><span class="hljs-params">(<span class="hljs-type">double</span> price,<span class="hljs-type">int</span> num)</span>&#123;<br><br>        <span class="hljs-type">double</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> <span class="hljs-number">0d</span>;<br>        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.component != <span class="hljs-literal">null</span>)&#123;<br>            <span class="hljs-comment">//若装饰对象存在，则执行装饰的算法运算</span><br>            result = <span class="hljs-built_in">this</span>.component.acceptCash(price,num);<br>        &#125;<br>        <span class="hljs-keyword">return</span> result;<br><br>    &#125;<br><br>&#125;<br><br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">CashNormal</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">ISale</span> &#123;<br>    <span class="hljs-comment">//正常收费，原价返回</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">acceptCash</span><span class="hljs-params">(<span class="hljs-type">double</span> price,<span class="hljs-type">int</span> num)</span>&#123;<br>        <span class="hljs-keyword">return</span> price * num;<br>    &#125;<br>&#125;<br><br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">CashRebate</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">CashSuper</span> &#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">double</span> <span class="hljs-variable">moneyRebate</span> <span class="hljs-operator">=</span> <span class="hljs-number">1d</span>;<br>    <span class="hljs-comment">//打折收费。初始化时必需输入折扣率。八折就输入0.8</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">CashRebate</span><span class="hljs-params">(<span class="hljs-type">double</span> moneyRebate)</span>&#123;<br>        <span class="hljs-built_in">this</span>.moneyRebate = moneyRebate;<br>    &#125;<br><br>    <span class="hljs-comment">//计算收费时需要在原价基础上乘以折扣率</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">acceptCash</span><span class="hljs-params">(<span class="hljs-type">double</span> price,<span class="hljs-type">int</span> num)</span>&#123;<br>        <span class="hljs-type">double</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> price * num * <span class="hljs-built_in">this</span>.moneyRebate;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">super</span>.acceptCash(result,<span class="hljs-number">1</span>);<br>    &#125;<br><br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">CashReturn</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">CashSuper</span> &#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">double</span> <span class="hljs-variable">moneyCondition</span> <span class="hljs-operator">=</span> <span class="hljs-number">0d</span>; <span class="hljs-comment">//返利条件</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">double</span> <span class="hljs-variable">moneyReturn</span> <span class="hljs-operator">=</span> <span class="hljs-number">0d</span>;    <span class="hljs-comment">//返利值</span><br><br>    <span class="hljs-comment">//返利收费。初始化时需要输入返利条件和返利值。</span><br>    <span class="hljs-comment">//比如“满300返100”，就是moneyCondition=300,moneyReturn=100</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">CashReturn</span><span class="hljs-params">(<span class="hljs-type">double</span> moneyCondition,<span class="hljs-type">double</span> moneyReturn)</span>&#123;<br>        <span class="hljs-built_in">this</span>.moneyCondition = moneyCondition;<br>        <span class="hljs-built_in">this</span>.moneyReturn = moneyReturn;<br>    &#125;<br><br>    <span class="hljs-comment">//计算收费时，当达到返利条件，就原价减去返利值</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">acceptCash</span><span class="hljs-params">(<span class="hljs-type">double</span> price,<span class="hljs-type">int</span> num)</span>&#123;<br>        <span class="hljs-type">double</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> price * num;<br>        <span class="hljs-keyword">if</span> (moneyCondition&gt;<span class="hljs-number">0</span> &amp;&amp; result &gt;= moneyCondition)<br>            result = result - Math.floor(result / moneyCondition) * moneyReturn;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">super</span>.acceptCash(result,<span class="hljs-number">1</span>);<br>    &#125;<br><br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">CashContext</span> &#123;<br>    <span class="hljs-keyword">private</span> ISale cs;   <span class="hljs-comment">//声明一个ISale接口对象</span><br><br>    <span class="hljs-comment">//通过构造方法，传入具体的收费策略</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">CashContext</span><span class="hljs-params">(<span class="hljs-type">int</span> cashType)</span> &#123;<br>        <span class="hljs-keyword">switch</span> (cashType) &#123;<br>            <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:<br>                <span class="hljs-built_in">this</span>.cs = <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashNormal</span>();<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:<br>                <span class="hljs-type">CashRebate</span> <span class="hljs-variable">cr1</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashRebate</span>(<span class="hljs-number">0.7d</span>);<br>                cr1.decorate(<span class="hljs-keyword">new</span> <span class="hljs-title class_">CashNormal</span>());<br>                <span class="hljs-built_in">this</span>.cs = cr1;<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-number">3</span>:<br>                <span class="hljs-type">CashRebate</span> <span class="hljs-variable">cr2</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashRebate</span>(<span class="hljs-number">0.8d</span>);<br>                cr2.decorate(<span class="hljs-keyword">new</span> <span class="hljs-title class_">CashNormal</span>());<br>                <span class="hljs-built_in">this</span>.cs = cr2;<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-number">4</span>:<br>                <span class="hljs-type">CashReturn</span> <span class="hljs-variable">cr3</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashReturn</span>(<span class="hljs-number">300d</span>, <span class="hljs-number">100d</span>);<br>                cr3.decorate(<span class="hljs-keyword">new</span> <span class="hljs-title class_">CashNormal</span>());<br>                <span class="hljs-built_in">this</span>.cs = cr3;<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-number">5</span>:<br>                <span class="hljs-comment">//先打8折,再满300返100</span><br>                <span class="hljs-type">CashNormal</span> <span class="hljs-variable">cn</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashNormal</span>();<br>                <span class="hljs-type">CashReturn</span> <span class="hljs-variable">cr4</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashReturn</span>(<span class="hljs-number">300d</span>, <span class="hljs-number">100d</span>);<br>                <span class="hljs-type">CashRebate</span> <span class="hljs-variable">cr5</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashRebate</span>(<span class="hljs-number">0.8d</span>);<br>                cr4.decorate(cn);   <span class="hljs-comment">//用满300返100算法包装基本的原价算法</span><br>                cr5.decorate(cr4);  <span class="hljs-comment">//打8折算法装饰满300返100算法</span><br>                <span class="hljs-built_in">this</span>.cs = cr5;      <span class="hljs-comment">//将包装好的算法组合引用传递给cs对象</span><br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-number">6</span>:<br>                <span class="hljs-comment">//先满200返50，再打7折</span><br>                <span class="hljs-type">CashNormal</span> <span class="hljs-variable">cn2</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashNormal</span>();<br>                <span class="hljs-type">CashRebate</span> <span class="hljs-variable">cr6</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashRebate</span>(<span class="hljs-number">0.7d</span>);<br>                <span class="hljs-type">CashReturn</span> <span class="hljs-variable">cr7</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CashReturn</span>(<span class="hljs-number">200d</span>, <span class="hljs-number">50d</span>);<br>                cr6.decorate(cn2);  <span class="hljs-comment">//用打7折算法包装基本的原价算法</span><br>                cr7.decorate(cr6);  <span class="hljs-comment">//满200返50算法装饰打7折算法</span><br>                <span class="hljs-built_in">this</span>.cs = cr7;      <span class="hljs-comment">//将包装好的算法组合引用传递给cs对象</span><br>                <span class="hljs-keyword">break</span>;<br>        &#125;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> price,<span class="hljs-type">int</span> num)</span>&#123;<br>        <span class="hljs-comment">//根据收费策略的不同，获得计算结果</span><br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.cs.acceptCash(price,num);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><h3 id="第-7-章-代理模式">第 7 章 代理模式</h3><p><strong>代理模式（Proxy），为其他对象提供一种代理以控制对这个对象的访问。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230503180154059.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 顾梦</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@create</span> 2023/4/27</span><br><span class="hljs-comment"> * 代理模式——为别人做嫁衣</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ProxyPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">SchoolGirl</span> <span class="hljs-variable">girlLjj</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SchoolGirl</span>();<br>        girlLjj.setName(<span class="hljs-string">&quot;李娇娇&quot;</span>);<br><br>        <span class="hljs-type">Proxy</span> <span class="hljs-variable">boyDl</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Proxy</span>(girlLjj);<br>        boyDl.giveDolls();<br>        boyDl.giveFlowers();<br>        boyDl.giveChocolate();<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">interface</span> <span class="hljs-title class_">IGiveGift</span>&#123;<br>    <span class="hljs-keyword">void</span> <span class="hljs-title function_">giveDolls</span><span class="hljs-params">()</span>;<br>    <span class="hljs-keyword">void</span> <span class="hljs-title function_">giveFlowers</span><span class="hljs-params">()</span>;<br>    <span class="hljs-keyword">void</span> <span class="hljs-title function_">giveChocolate</span><span class="hljs-params">()</span>;<br>&#125;<br><br><span class="hljs-comment">// 被追求者类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">SchoolGirl</span>&#123;<br>    <span class="hljs-keyword">private</span> String name;<br><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getName</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.name;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setName</span><span class="hljs-params">(String name)</span>&#123;<br>        <span class="hljs-built_in">this</span>.name = name;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 追求者类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Pursuit</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">IGiveGift</span>&#123;<br><br>    <span class="hljs-keyword">private</span> SchoolGirl mm;<br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Pursuit</span><span class="hljs-params">(SchoolGirl mm)</span>&#123;<br>        <span class="hljs-built_in">this</span>.mm = mm;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">giveDolls</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-built_in">this</span>.mm.getName() + <span class="hljs-string">&quot;,你好！送你洋娃娃。&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">giveFlowers</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-built_in">this</span>.mm.getName() + <span class="hljs-string">&quot;,你好！送你鲜花。&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">giveChocolate</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-built_in">this</span>.mm.getName() + <span class="hljs-string">&quot;,你好！送你巧克力。&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 代理类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Proxy</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">IGiveGift</span>&#123;<br><br>    <span class="hljs-keyword">private</span> Pursuit gg;     <span class="hljs-comment">// 认识追求者</span><br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Proxy</span><span class="hljs-params">(SchoolGirl mm)</span>&#123;<br>        <span class="hljs-built_in">this</span>.gg = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Pursuit</span>(mm);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">giveDolls</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-built_in">this</span>.gg.giveDolls();<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">giveFlowers</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-built_in">this</span>.gg.giveFlowers();<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">giveChocolate</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-built_in">this</span>.gg.giveChocolate();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p><strong>代理模式应用</strong>：</p><ul><li>远程代理，也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。</li><li>虚拟代理，是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。</li><li>安全代理，用来控制真实对象访问的权限。</li><li>智能指引，是指当调用真实的对象时，代理处理另外一些事。</li></ul><h3 id="第-8-章-工厂方法模式">第 8 章 工厂方法模式</h3><p><strong>工厂方法模式（Factory Method），定义一个用于创建对象的接口，让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。</strong></p><p>工厂方法模式是简单工厂模式的进一步抽象和推广。</p><p>优点：</p><ul><li>对于复杂的参数构造对象，可以很好地对外层屏蔽代码的复杂性</li><li>很好的解耦能力</li></ul><p><img src="https://cdn.gumengyo.top/Snipaste_2023-05-04_09-20-36.png" srcset="/img/loading.gif" lazyload alt=""><br><img src="https://cdn.gumengyo.top/Snipaste_2023-05-04_11-22-06.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter08;<br><br><span class="hljs-keyword">import</span> java.util.*;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">FactoryMethod</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Scanner</span> <span class="hljs-variable">sc</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Scanner</span>(System.in);<br><br>        System.out.println(<span class="hljs-string">&quot;请输入数字A: &quot;</span>);<br>        <span class="hljs-type">double</span> <span class="hljs-variable">numberA</span> <span class="hljs-operator">=</span> Double.parseDouble(sc.nextLine());<br>        System.out.println(<span class="hljs-string">&quot;请选择运算符号(+、-、*、/、pow、log): &quot;</span>);<br>        <span class="hljs-type">String</span> <span class="hljs-variable">strOperate</span> <span class="hljs-operator">=</span> sc.nextLine();<br>        System.out.println(<span class="hljs-string">&quot;请输入数字B: &quot;</span>);<br>        <span class="hljs-type">double</span> <span class="hljs-variable">numberB</span> <span class="hljs-operator">=</span> Double.parseDouble(sc.nextLine());<br><br>        <span class="hljs-type">Operation</span> <span class="hljs-variable">operate</span> <span class="hljs-operator">=</span> OperationFactory.createOperate(strOperate);<br>        <span class="hljs-type">double</span> <span class="hljs-variable">result</span> <span class="hljs-operator">=</span> operate.getResult(numberA, numberB);<br><br>        System.out.println(<span class="hljs-string">&quot;结果是: &quot;</span> + result);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Operation</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> numberA, <span class="hljs-type">double</span> numberB)</span> ;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Add</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Operation</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> numberA, <span class="hljs-type">double</span> numberB)</span> &#123;<br>        <span class="hljs-keyword">return</span> numberA + numberB;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Sub</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Operation</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> numberA, <span class="hljs-type">double</span> numberB)</span> &#123;<br>        <span class="hljs-keyword">return</span> numberA + numberB;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Mul</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Operation</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> numberA, <span class="hljs-type">double</span> numberB)</span> &#123;<br>        <span class="hljs-keyword">return</span> numberA * numberB;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Div</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Operation</span> &#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> numberA, <span class="hljs-type">double</span> numberB)</span> &#123;<br>        <span class="hljs-keyword">if</span> (numberB == <span class="hljs-number">0</span>) &#123;<br>            System.out.println(<span class="hljs-string">&quot;除数不能为0&quot;</span>);<br>            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArithmeticException</span>();<br>        &#125;<br>        <span class="hljs-keyword">return</span> numberA / numberB;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 指数运算类，求numberA的numberB次方</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Pow</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Operation</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> numberA, <span class="hljs-type">double</span> numberB)</span> &#123;<br>        <span class="hljs-comment">// 此处缺两参数的有效性检测</span><br>        <span class="hljs-keyword">return</span> Math.pow(numberA,numberB);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 对数运算类，求以numberA为底的numberB的对数</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Log</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Operation</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">double</span> <span class="hljs-title function_">getResult</span><span class="hljs-params">(<span class="hljs-type">double</span> numberA, <span class="hljs-type">double</span> numberB)</span> &#123;<br>        <span class="hljs-comment">// 此处缺两参数的有效性检测</span><br>        <span class="hljs-keyword">return</span> Math.log(numberB) / Math.log(numberA);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">interface</span> <span class="hljs-title class_">IFactory</span>&#123;<br>    Operation <span class="hljs-title function_">createOperation</span><span class="hljs-params">(String operType)</span>;<br>&#125;<br><br><span class="hljs-comment">// 基础运算工厂</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">FactoryBasic</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">IFactory</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Operation <span class="hljs-title function_">createOperation</span><span class="hljs-params">(String operType)</span> &#123;<br>        <span class="hljs-type">Operation</span> <span class="hljs-variable">oper</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br>        <span class="hljs-keyword">switch</span> (operType)&#123;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;+&quot;</span>:<br>                oper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Add</span>();<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;-&quot;</span>:<br>                oper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Sub</span>();<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;*&quot;</span>:<br>                oper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Mul</span>();<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;/&quot;</span>:<br>                oper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Div</span>();<br>                <span class="hljs-keyword">break</span>;<br>        &#125;<br>        <span class="hljs-keyword">return</span> oper;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 高级运算工厂</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">FactoryAdvanced</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">IFactory</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Operation <span class="hljs-title function_">createOperation</span><span class="hljs-params">(String operType)</span> &#123;<br>        <span class="hljs-type">Operation</span> <span class="hljs-variable">oper</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br>        <span class="hljs-keyword">switch</span> (operType)&#123;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;pow&quot;</span>:<br>                oper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Pow</span>(); <span class="hljs-comment">// 指数运算类实例</span><br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;log&quot;</span>:<br>                oper = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Log</span>(); <span class="hljs-comment">// 对数运算类实例</span><br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-comment">// 此处可扩展其他高级运算类的实例化，可修改</span><br>            <span class="hljs-comment">// 当前工厂类不会影响到基础运算工厂类</span><br><br>        &#125;<br>        <span class="hljs-keyword">return</span> oper;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">OperationFactory</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Operation <span class="hljs-title function_">createOperate</span><span class="hljs-params">(String operate)</span>&#123;<br>        <span class="hljs-type">Operation</span> <span class="hljs-variable">oper</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br>        <span class="hljs-type">IFactory</span> <span class="hljs-variable">factory</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br>        <span class="hljs-keyword">switch</span> (operate)&#123;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;+&quot;</span>:<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;-&quot;</span>:<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;*&quot;</span>:<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;/&quot;</span>:<br>                <span class="hljs-comment">// 基础运算工厂实例</span><br>                factory = <span class="hljs-keyword">new</span> <span class="hljs-title class_">FactoryBasic</span>();<br>                <span class="hljs-keyword">break</span>;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;pow&quot;</span>:<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&quot;log&quot;</span>:<br>                <span class="hljs-comment">// 高级运算工厂实例</span><br>                factory = <span class="hljs-keyword">new</span> <span class="hljs-title class_">FactoryAdvanced</span>();<br>        &#125;<br>        <span class="hljs-comment">// 利用多态返回实际的运算类实例</span><br>        oper = factory.createOperation(operate);<br>        <span class="hljs-keyword">return</span> oper;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><h3 id="第-9-章-原型模式">第 9 章 原型模式</h3><p><strong>原型模式（Prototype），用原型实例指定创建对象的种类，并且通过复制这些原型创建新的对象。</strong></p><p>原型模式其实就是从一个对象再创建另外一个可定制的对象，而且不需要知道任何创建的细节。</p><p><strong>浅复制与深复制：</strong></p><ul><li>浅复制：被复制对象的所有变量都含有与原来的对象相同的值，而所有的对其他对象的引用都仍然指向原来的对象。</li><li>深复制：深复制把引用对象的变量指向复制过的新对象，而不是原有的被引用的对象。</li></ul><p><img src="https://cdn.gumengyo.top/Snipaste_2023-05-04_11-21-15.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter09;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 顾梦</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@create</span> 2023/5/4</span><br><span class="hljs-comment"> * 简历复印——原型模式</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">PrototypePattern</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Resume</span> <span class="hljs-variable">resume1</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Resume</span>(<span class="hljs-string">&quot;大鸟&quot;</span>);<br>        resume1.setPersonalInfo(<span class="hljs-string">&quot;男&quot;</span>,<span class="hljs-string">&quot;29&quot;</span>);<br>        resume1.setWorkExperience(<span class="hljs-string">&quot;1998-2000&quot;</span>,<span class="hljs-string">&quot;xx公司&quot;</span>);<br><br>        <span class="hljs-type">Resume</span> <span class="hljs-variable">resume2</span> <span class="hljs-operator">=</span> resume1.clone();<br>        resume2.setWorkExperience(<span class="hljs-string">&quot;2000-2003&quot;</span>,<span class="hljs-string">&quot;YY集团&quot;</span>);<br><br>        <span class="hljs-type">Resume</span> <span class="hljs-variable">resume3</span> <span class="hljs-operator">=</span> resume1.clone();<br>        resume3.setPersonalInfo(<span class="hljs-string">&quot;男&quot;</span>,<span class="hljs-string">&quot;24&quot;</span>);<br><br>        resume1.display();<br>        resume2.display();<br>        resume3.display();<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 工作经历类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">WorkExperience</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">Cloneable</span>&#123;<br>    <span class="hljs-comment">// 工作时间范围</span><br>    <span class="hljs-keyword">private</span> String timeArea;<br><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getTimeArea</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> timeArea;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setTimeArea</span><span class="hljs-params">(String timeArea)</span> &#123;<br>        <span class="hljs-built_in">this</span>.timeArea = timeArea;<br>    &#125;<br><br>    <span class="hljs-comment">// 所在公司</span><br>    <span class="hljs-keyword">private</span> String company;<br><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getCompany</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> company;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setCompany</span><span class="hljs-params">(String company)</span> &#123;<br>        <span class="hljs-built_in">this</span>.company = company;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> WorkExperience <span class="hljs-title function_">clone</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-type">WorkExperience</span> <span class="hljs-variable">object</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br>        <span class="hljs-keyword">try</span>&#123;<br>            object = (WorkExperience) <span class="hljs-built_in">super</span>.clone();<br>        &#125;<span class="hljs-keyword">catch</span> (CloneNotSupportedException exception)&#123;<br>            System.out.println(<span class="hljs-string">&quot;Clone异常。&quot;</span>);<br>        &#125;<br>        <span class="hljs-keyword">return</span> object;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 简历类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Resume</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">Cloneable</span>&#123;<br>    <span class="hljs-keyword">private</span> String name;<br>    <span class="hljs-keyword">private</span> String sex;<br>    <span class="hljs-keyword">private</span> String age;<br>    <span class="hljs-keyword">private</span> WorkExperience work;<br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Resume</span><span class="hljs-params">(String name)</span> &#123;<br>        <span class="hljs-built_in">this</span>.name = name;<br>        <span class="hljs-built_in">this</span>.work = <span class="hljs-keyword">new</span> <span class="hljs-title class_">WorkExperience</span>();<br>    &#125;<br><br>    <span class="hljs-comment">// 设置个人信息</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setPersonalInfo</span><span class="hljs-params">(String sex,String age)</span>&#123;<br>        <span class="hljs-built_in">this</span>.sex = sex;<br>        <span class="hljs-built_in">this</span>.age = age;<br>    &#125;<br><br>    <span class="hljs-comment">// 设置工作经历</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setWorkExperience</span><span class="hljs-params">(String timeArea,String company)</span>&#123;<br>        <span class="hljs-built_in">this</span>.work.setTimeArea(timeArea);    <span class="hljs-comment">// 给工作经历实例的时间范围赋值</span><br>        <span class="hljs-built_in">this</span>.work.setCompany(company);      <span class="hljs-comment">// 给工作经历实例的公司赋值</span><br>    &#125;<br><br>    <span class="hljs-comment">// 展示简历</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">display</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-built_in">this</span>.name + <span class="hljs-string">&quot; &quot;</span> + <span class="hljs-built_in">this</span>.sex + <span class="hljs-string">&quot; &quot;</span> + <span class="hljs-built_in">this</span>.age);<br>        System.out.println(<span class="hljs-string">&quot;工作经历 &quot;</span> + <span class="hljs-built_in">this</span>.work.getTimeArea() + <span class="hljs-string">&quot; &quot;</span> + <span class="hljs-built_in">this</span>.work.getCompany());<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">protected</span> Resume <span class="hljs-title function_">clone</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-type">Resume</span> <span class="hljs-variable">object</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br>        <span class="hljs-keyword">try</span> &#123;<br>            object = (Resume) <span class="hljs-built_in">super</span>.clone();<br>            object.work = <span class="hljs-built_in">this</span>.work.clone(); <span class="hljs-comment">// 深复制</span><br>        &#125;<span class="hljs-keyword">catch</span> (CloneNotSupportedException exception)&#123;<br>            System.out.println(<span class="hljs-string">&quot;Clone 异常。&quot;</span>);<br>        &#125;<br>        <span class="hljs-keyword">return</span> object;<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure><h3 id="第-10-章-模板方法模式">第 10 章 模板方法模式</h3><p><strong>模板方法（Template Method）模式，定义一个操作中的算法的骨架，而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230504142740007.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter10;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">TemplateMethod</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">AbstractClass</span> <span class="hljs-variable">abstractClass</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteClassA</span>();<br>        abstractClass.templateMethod();<br><br>        abstractClass = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteClassB</span>();<br>        abstractClass.templateMethod();<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 模板方法抽象类</span><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AbstractClass</span>&#123;<br>    <span class="hljs-comment">// 模板方法</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">templateMethod</span><span class="hljs-params">()</span>&#123;<br><br>        <span class="hljs-comment">// 写一些可以被子类共享的代码</span><br>        System.out.println(<span class="hljs-string">&quot;共享的代码~&quot;</span>);<br><br>        <span class="hljs-built_in">this</span>.primitiveOperation1();<br>        <span class="hljs-built_in">this</span>.primitiveOperation2();<br><br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">primitiveOperation1</span><span class="hljs-params">()</span>; <span class="hljs-comment">// 子类个性的行为，放到子类去实现</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">primitiveOperation2</span><span class="hljs-params">()</span>; <span class="hljs-comment">// 子类个性的行为，放到子类去实现</span><br>&#125;<br><br><span class="hljs-comment">// 模板方法具体类A</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteClassA</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">AbstractClass</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">primitiveOperation1</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;具体类A方法1实现&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">primitiveOperation2</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;具体类A方法2实现&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 模板方法具体类B</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteClassB</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">AbstractClass</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">primitiveOperation1</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;具体类B方法1实现&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">primitiveOperation2</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;具体类B方法2实现&quot;</span>);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p><strong>模板方法模式的特点</strong></p><ul><li>模板方法模式是通过把不变行为搬移到超类，去除子类中的重复代码来体现它的优势。</li><li>模板方法模式就是提供了一个很好的代码复用平台。</li></ul><h3 id="第-11-章-迪米特法则">第 11 章 迪米特法则</h3><p>迪米特法则（LoD），也叫最少知识原则。<br><strong>迪米特法则（LoD）：如果两个类不必彼此直接通信，那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话，可以通过第三者转发这个调用。</strong></p><h3 id="第-12-章-外观模式">第 12 章 外观模式</h3><p><strong>外观模式（Facade），为子系统中的一组接口提供一个一致的界面，此模式定义了一个高层接口，这个接口使得这一子系统更加容易使用。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230505171033965.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter11;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 顾梦</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@create</span> 2023/5/5</span><br><span class="hljs-comment"> * 外观模式</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">FacadePattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Facade</span> <span class="hljs-variable">facade</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Facade</span>();<br><br>        facade.methodA();<br>        facade.methodB();<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 子系统1</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">SubSystemOne</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">methodOne</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;子系统方法一&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 子系统2</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">SubSystemTwo</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">methodTwo</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;子系统方法二&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 子系统3</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">SubSystemThree</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">methodThree</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;子系统方法三&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 子系统1</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">SubSystemFour</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">methodFour</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;子系统方法四&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 外观类</span><br><span class="hljs-comment">// 它需要了解所有子系统的方法或属性，进行组合以被外界调用</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Facade</span>&#123;<br>    SubSystemOne one;<br>    SubSystemTwo two;<br>    SubSystemThree three;<br>    SubSystemFour four;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Facade</span><span class="hljs-params">()</span>&#123;<br>        one = <span class="hljs-keyword">new</span> <span class="hljs-title class_">SubSystemOne</span>();<br>        two = <span class="hljs-keyword">new</span> <span class="hljs-title class_">SubSystemTwo</span>();<br>        three = <span class="hljs-keyword">new</span> <span class="hljs-title class_">SubSystemThree</span>();<br>        four = <span class="hljs-keyword">new</span> <span class="hljs-title class_">SubSystemFour</span>();<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">methodA</span><span class="hljs-params">()</span>&#123;<br>        one.methodOne();<br>        two.methodTwo();<br>        three.methodThree();<br>        four.methodFour();<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">methodB</span><span class="hljs-params">()</span>&#123;<br>        two.methodTwo();<br>        three.methodThree();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><h3 id="第-13-章-建造者模式">第 13 章 建造者模式</h3><p><strong>建造者模式（Builder），将一个复杂对象的构建与它的表示分离，使得同样的构建过程可以创建不同的表示。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230505194106302.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter13;<br><br><span class="hljs-keyword">import</span> java.util.*;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 顾梦</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@create</span> 2023/5/5</span><br><span class="hljs-comment"> * 建造者模式</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">BuilderPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Director</span> <span class="hljs-variable">director</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Director</span>();<br>        <span class="hljs-type">Builder</span> <span class="hljs-variable">b1</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteBuilder1</span>();<br>        <span class="hljs-type">Builder</span> <span class="hljs-variable">b2</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteBuilder2</span>();<br><br>        <span class="hljs-comment">// 指挥者用ConcreteBuilder1的方法来建造产品</span><br>        director.construct(b1); <span class="hljs-comment">// 创建的是产品A和产品B</span><br>        <span class="hljs-type">Product</span> <span class="hljs-variable">p1</span> <span class="hljs-operator">=</span> b1.getResult();<br>        p1.show();<br><br>        <span class="hljs-comment">// 指挥者用ConcreteBuilder2的方法来建造产品</span><br>        director.construct(b2); <span class="hljs-comment">// 创建的是产品X和产品Y</span><br>        <span class="hljs-type">Product</span> <span class="hljs-variable">p2</span> <span class="hljs-operator">=</span> b2.getResult();<br>        p2.show();<br><br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 产品类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Product</span> &#123;<br>    ArrayList&lt;String&gt; parts = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span>&lt;String&gt;();<br><br>    <span class="hljs-comment">// 添加新的产品部件</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">add</span><span class="hljs-params">(String part)</span>&#123;<br>        parts.add(part);<br>    &#125;<br><br>    <span class="hljs-comment">// 列举所有产品部件</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">show</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">for</span> (String part : parts) &#123;<br>            System.out.println(part);<br>        &#125;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 抽象的建造者类</span><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Builder</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">buildPartA</span><span class="hljs-params">()</span>; <span class="hljs-comment">// 建造部件A</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">buildPartB</span><span class="hljs-params">()</span>; <span class="hljs-comment">// 建造部件B</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> Product <span class="hljs-title function_">getResult</span><span class="hljs-params">()</span>; <span class="hljs-comment">// 得到产品</span><br>&#125;<br><br><span class="hljs-comment">// 具体建造者1</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteBuilder1</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Builder</span> &#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">Product</span> <span class="hljs-variable">product</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Product</span>();<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">buildPartA</span><span class="hljs-params">()</span> &#123;<br>        product.add(<span class="hljs-string">&quot;部件A&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">buildPartB</span><span class="hljs-params">()</span> &#123;<br>        product.add(<span class="hljs-string">&quot;部件B&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Product <span class="hljs-title function_">getResult</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> product;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 具体建造者2</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteBuilder2</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Builder</span> &#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">Product</span> <span class="hljs-variable">product</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Product</span>();<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">buildPartA</span><span class="hljs-params">()</span> &#123;<br>        product.add(<span class="hljs-string">&quot;部件X&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">buildPartB</span><span class="hljs-params">()</span> &#123;<br>        product.add(<span class="hljs-string">&quot;部件Y&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Product <span class="hljs-title function_">getResult</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> product;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 指挥者</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Director</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">construct</span><span class="hljs-params">(Builder builder)</span> &#123;<br>        builder.buildPartA();<br>        builder.buildPartB();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>建造者模式的好处就是使得建造代码与表示代码分离，由于建造者隐藏了该产品是如何组装的，所以若需要改变一个产品的内部表示，只需要再定义一个具体的建造者就可以了。</p><p>建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时适用的模式。</p><h3 id="第-14-章-观察者模式">第 14 章 观察者模式</h3><p>观察者模式又叫作发布-订阅（Publish/Subscri）模式。</p><p><strong>观察者模式定义了一种一对多的依赖关系，让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时，会通知所有观察者对象，使它们能够自动更新自己。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230506133700094.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter14;<br><br><span class="hljs-keyword">import</span> java.util.*;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 顾梦</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@create</span> 2023/5/6</span><br><span class="hljs-comment"> * 观察者模式</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ObserverPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Subject</span> <span class="hljs-variable">subject</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteSubject</span>();<br>        subject.attach(<span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteObserver</span>(<span class="hljs-string">&quot;NameX&quot;</span>,subject));<br>        subject.attach(<span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteObserver</span>(<span class="hljs-string">&quot;NameY&quot;</span>,subject));<br>        subject.attach(<span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteObserver</span>(<span class="hljs-string">&quot;NameZ&quot;</span>, subject));<br>        subject.setSubjectState(<span class="hljs-string">&quot;ABC&quot;</span>);<br><br>        subject.notifyObserver();<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 通知者抽象类</span><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Subject</span> &#123;<br>    <span class="hljs-keyword">private</span> ArrayList&lt;Observer&gt; list = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span>&lt;Observer&gt;(); <span class="hljs-comment">// 针对抽象的Observer编程</span><br><br>    <span class="hljs-comment">// 增加观察者</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">attach</span><span class="hljs-params">(Observer observer)</span>&#123;<br>        list.add(observer);<br>    &#125;<br><br>    <span class="hljs-comment">// 减少观察者</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">detach</span><span class="hljs-params">(Observer observer)</span>&#123;<br>        list.remove(observer);<br>    &#125;<br><br>    <span class="hljs-comment">// 通知观察者</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">notifyObserver</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">for</span> (Observer item : list) &#123;<br>            item.update();<br>        &#125;<br>    &#125;<br><br>    <span class="hljs-keyword">protected</span> String subjectState;<br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getSubjectState</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.subjectState;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setSubjectState</span><span class="hljs-params">(String value)</span> &#123;<br>        <span class="hljs-built_in">this</span>.subjectState = value;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 抽象观察者</span><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Observer</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">update</span><span class="hljs-params">()</span>;<br>&#125;<br><br><span class="hljs-comment">// 具体通知者</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteSubject</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Subject</span>&#123;<br>    <span class="hljs-comment">// 具体通知者的方法</span><br>&#125;<br><br><span class="hljs-comment">// 具体观察者类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteObserver</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Observer</span>&#123;<br>    <span class="hljs-keyword">private</span> String name;<br>    <span class="hljs-keyword">private</span> Subject  sub;<br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">ConcreteObserver</span><span class="hljs-params">(String name,Subject sub)</span>&#123;<br>        <span class="hljs-built_in">this</span>.name = name;<br>        <span class="hljs-built_in">this</span>.sub = sub;<br>    &#125;<br><br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">update</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;观察者&quot;</span>+<span class="hljs-built_in">this</span>.name+<span class="hljs-string">&quot;的新状态是&quot;</span>+<span class="hljs-built_in">this</span>.sub.getSubjectState());<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p><strong>特点：</strong></p><ul><li>当一个对象的改变需要同时改变其他对象，而且它不知道具体有多少对象有待改变时，应该考虑使用观察者模式。</li><li>抽象模型有两个方面，其中一方面依赖于另一方面，这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。</li><li>观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象，而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。</li></ul><h3 id="第-15-章-抽象工厂模式">第 15 章 抽象工厂模式</h3><p><strong>抽象工厂模式（Abstract Factory），提供一个创建一系列相关或相互依赖对象的接口，而无须指定它们具体的类。</strong></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter15;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@author</span> 顾梦</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@create</span> 2023/5/6</span><br><span class="hljs-comment"> * 抽象工厂模式</span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AbstractFactory</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>();<br>        <span class="hljs-type">Department</span> <span class="hljs-variable">department</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Department</span>();<br><br>        <span class="hljs-type">IFactory</span> <span class="hljs-variable">factory</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SqlserverFactory</span>();<br><br>        <span class="hljs-type">IUser</span> <span class="hljs-variable">iu</span> <span class="hljs-operator">=</span> factory.createUser();<br>        iu.insert(user);        <span class="hljs-comment">// 新增一个用户</span><br>        iu.getUser(<span class="hljs-number">1</span>);      <span class="hljs-comment">//得到用户ID为1的用户信息</span><br><br>        <span class="hljs-type">IDepartment</span> <span class="hljs-variable">idept</span> <span class="hljs-operator">=</span> factory.createDepartment();<br>        idept.insert(department);<br>        idept.getDepartment(<span class="hljs-number">2</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 用户类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">User</span>&#123;<br><br>    <span class="hljs-comment">// 用户ID</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">int</span> _id;<br>    <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">getId</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._id;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setId</span><span class="hljs-params">(<span class="hljs-type">int</span> value)</span> &#123;<br>        <span class="hljs-built_in">this</span>._id = value;<br>    &#125;<br><br>    <span class="hljs-comment">// 用户姓名</span><br>    <span class="hljs-keyword">private</span> String _name;<br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getName</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._name;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setName</span><span class="hljs-params">(String value)</span>&#123;<br>        <span class="hljs-built_in">this</span>._name = value;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 部门类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Department</span>&#123;<br><br>    <span class="hljs-comment">// 部门ID</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">int</span> _id;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">get_id</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._id;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">set_id</span><span class="hljs-params">(<span class="hljs-type">int</span> value)</span>&#123;<br>        <span class="hljs-built_in">this</span>._id = value;<br>    &#125;<br><br>    <span class="hljs-comment">// 部门名称</span><br>    <span class="hljs-keyword">private</span> String _name;<br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getName</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._name;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setName</span><span class="hljs-params">(String value)</span>&#123;<br>        <span class="hljs-built_in">this</span>._name = value;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">interface</span> <span class="hljs-title class_">IUser</span>&#123;<br>    <span class="hljs-keyword">void</span> <span class="hljs-title function_">insert</span><span class="hljs-params">(User user)</span>;<br>    User <span class="hljs-title function_">getUser</span><span class="hljs-params">(<span class="hljs-type">int</span> id)</span>;<br>&#125;<br><br><span class="hljs-comment">// 部门类接口</span><br><span class="hljs-keyword">interface</span> <span class="hljs-title class_">IDepartment</span>&#123;<br>    <span class="hljs-keyword">void</span> <span class="hljs-title function_">insert</span><span class="hljs-params">(Department department)</span>;<br>    Department <span class="hljs-title function_">getDepartment</span><span class="hljs-params">(<span class="hljs-type">int</span> id)</span>;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">SqlserverUser</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">IUser</span>&#123;<br><br>    <span class="hljs-comment">// 新增一个用户</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">insert</span><span class="hljs-params">(User user)</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;在SQL Server中给User表增加一条记录&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-comment">// 获取一个用户信息</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> User <span class="hljs-title function_">getUser</span><span class="hljs-params">(<span class="hljs-type">int</span> id)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;在SQL Server中根据用户ID得到User表一条记录&quot;</span>);<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">AccessUser</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">IUser</span>&#123;<br><br>    <span class="hljs-comment">// 新增一个用户</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">insert</span><span class="hljs-params">(User user)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;在Access中给User表增加一条记录&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> User <span class="hljs-title function_">getUser</span><span class="hljs-params">(<span class="hljs-type">int</span> id)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;在Access中根据用户ID得到User表一条记录&quot;</span>);<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">SqlserverDepartment</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">IDepartment</span>&#123;<br><br>    <span class="hljs-comment">// 新增一个部门</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">insert</span><span class="hljs-params">(Department department)</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;在SQLServer中给Department表增加一条记录&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Department <span class="hljs-title function_">getDepartment</span><span class="hljs-params">(<span class="hljs-type">int</span> id)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;在SQL Server中根据部门ID得到Department表一条记录&quot;</span>);<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">AccessDepartment</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">IDepartment</span>&#123;<br><br>    <span class="hljs-comment">// 新增一个部门</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">insert</span><span class="hljs-params">(Department department)</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;在Access中给Department表增加一条记录&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Department <span class="hljs-title function_">getDepartment</span><span class="hljs-params">(<span class="hljs-type">int</span> id)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;在Access中根据部门ID得到Department表一条记录&quot;</span>);<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 工厂接口</span><br><span class="hljs-keyword">interface</span> <span class="hljs-title class_">IFactory</span>&#123;<br>    IUser <span class="hljs-title function_">createUser</span><span class="hljs-params">()</span>;<br>    IDepartment <span class="hljs-title function_">createDepartment</span><span class="hljs-params">()</span>; <span class="hljs-comment">// 增加的接口方法</span><br>&#125;<br><br><span class="hljs-comment">// Sqlserver工厂</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">SqlserverFactory</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">IFactory</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> IUser <span class="hljs-title function_">createUser</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SqlserverUser</span>();<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> IDepartment <span class="hljs-title function_">createDepartment</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SqlserverDepartment</span>();<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// Access工厂</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">AccessFactory</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">IFactory</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> IUser <span class="hljs-title function_">createUser</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">AccessUser</span>();<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> IDepartment <span class="hljs-title function_">createDepartment</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">AccessDepartment</span>();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p><strong>特点：</strong></p><ul><li>易于交换产品系列，由于具体工厂类，在一应用中只需要在初始化的时候出现一次，这就使得改变一个应用的具体工厂变得非常容易，它只需要改变具体工厂即可使用不同的产品配置。</li><li>它让具体的创建实例过程与客户端分离，客户端是通过它们的抽象接口操纵实例，产品的具体类名也被具体工厂的实现分离，不会出现在客户代码中。</li></ul><h3 id="第-16-章-状态模式">第 16 章 状态模式</h3><p><strong>状态模式（State），当一个对象的内在状态改变时允许改变其行为，这个对象看起来像是改变了其类。</strong></p><p><img src="https://cdn.gumengyo.top/Snipaste_2023-05-11_08-37-15.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter16;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">StatePattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-comment">// 紧急项目</span><br>        <span class="hljs-type">Work</span> <span class="hljs-variable">emergencyProjects</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Work</span>();<br>        emergencyProjects.setHour(<span class="hljs-number">9</span>);<br>        emergencyProjects.writeProgram();<br>        emergencyProjects.setHour(<span class="hljs-number">10</span>);<br>        emergencyProjects.writeProgram();<br>        emergencyProjects.setHour(<span class="hljs-number">12</span>);<br>        emergencyProjects.writeProgram();<br>        emergencyProjects.setHour(<span class="hljs-number">13</span>);<br>        emergencyProjects.writeProgram();<br>        emergencyProjects.setHour(<span class="hljs-number">14</span>);<br>        emergencyProjects.writeProgram();<br>        emergencyProjects.setHour(<span class="hljs-number">17</span>);<br><br>        emergencyProjects.setWorkFinished(<span class="hljs-literal">false</span>);<br><br>        emergencyProjects.writeProgram();<br>        emergencyProjects.setHour(<span class="hljs-number">19</span>);<br>        emergencyProjects.writeProgram();<br>        emergencyProjects.setHour(<span class="hljs-number">22</span>);<br>        emergencyProjects.writeProgram();<br><br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 工作类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Work</span>&#123;<br><br>    <span class="hljs-keyword">private</span> State current;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Work</span><span class="hljs-params">()</span>&#123;<br>        current = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ForenoonState</span>();<br>    &#125;<br>    <span class="hljs-comment">// 设置状态</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setState</span><span class="hljs-params">(State value)</span>&#123;<br>        <span class="hljs-built_in">this</span>.current =value;<br>    &#125;<br><br>    <span class="hljs-comment">// 写代码的状态</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">writeProgram</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-built_in">this</span>.current.writeProgram(<span class="hljs-built_in">this</span>);<br>    &#125;<br><br>    <span class="hljs-comment">// 时间终点</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">int</span> hour;<br>    <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">getHour</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.hour;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setHour</span><span class="hljs-params">(<span class="hljs-type">int</span> value)</span> &#123;<br>        <span class="hljs-built_in">this</span>.hour = value;<br>    &#125;<br>    <span class="hljs-comment">// 是否完成工作任务</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">boolean</span> <span class="hljs-variable">workFinished</span> <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">getWorkFinished</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.workFinished;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setWorkFinished</span><span class="hljs-params">(<span class="hljs-type">boolean</span> value)</span>&#123;<br>        <span class="hljs-built_in">this</span>.workFinished = value;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">State</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">writeProgram</span><span class="hljs-params">(Work w)</span>;<br>&#125;<br><br><span class="hljs-comment">// 上午工作状态</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ForenoonState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">State</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">writeProgram</span> <span class="hljs-params">(Work w)</span>&#123;<br>        <span class="hljs-keyword">if</span> (w.getHour() &lt; <span class="hljs-number">12</span>)&#123;<br>            System.out.println(<span class="hljs-string">&quot;当前时间：&quot;</span> + w.getHour() + <span class="hljs-string">&quot;点 上午工作，精神百倍&quot;</span>);<br>        &#125;<span class="hljs-keyword">else</span> &#123;<br>            w.setState(<span class="hljs-keyword">new</span> <span class="hljs-title class_">NoonState</span>());<br>            w.writeProgram();<br>        &#125;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 中午工作状态</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">NoonState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">State</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">writeProgram</span> <span class="hljs-params">(Work w)</span>&#123;<br>        <span class="hljs-keyword">if</span> (w.getHour() &lt; <span class="hljs-number">13</span>)&#123;<br>            System.out.println(<span class="hljs-string">&quot;当前时间：&quot;</span> + w.getHour() + <span class="hljs-string">&quot;点 饿了，午饭：犯困，午休&quot;</span>);<br>        &#125;<span class="hljs-keyword">else</span> &#123;<br>            w.setState(<span class="hljs-keyword">new</span> <span class="hljs-title class_">AfternoonState</span>());<br>            w.writeProgram();<br>        &#125;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 下午工作状态</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">AfternoonState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">State</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">writeProgram</span> <span class="hljs-params">(Work w)</span>&#123;<br>        <span class="hljs-keyword">if</span> (w.getHour() &lt; <span class="hljs-number">17</span>)&#123;<br>            System.out.println(<span class="hljs-string">&quot;当前时间：&quot;</span> + w.getHour() + <span class="hljs-string">&quot;点 下午状态还不错，继续努力&quot;</span>);<br>        &#125;<span class="hljs-keyword">else</span> &#123;<br>            w.setState(<span class="hljs-keyword">new</span> <span class="hljs-title class_">EveningState</span>());<br>            w.writeProgram();<br>        &#125;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 晚间工作状态</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">EveningState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">State</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">writeProgram</span> <span class="hljs-params">(Work w)</span>&#123;<br>        <span class="hljs-keyword">if</span> (w.getWorkFinished())&#123;<br>            w.setState(<span class="hljs-keyword">new</span> <span class="hljs-title class_">RestState</span>());<br>            w.writeProgram();<br>        &#125;<span class="hljs-keyword">else</span> &#123;<br>            <span class="hljs-keyword">if</span> (w.getHour() &lt; <span class="hljs-number">21</span>)&#123;<br>                System.out.println(<span class="hljs-string">&quot;当前时间：&quot;</span> + w.getHour() + <span class="hljs-string">&quot;点 加班哦，疲累之极&quot;</span>);<br>            &#125;<span class="hljs-keyword">else</span> &#123;<br>                w.setState(<span class="hljs-keyword">new</span> <span class="hljs-title class_">SleepingState</span>());<br>                w.writeProgram();<br>            &#125;<br>        &#125;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 睡眠状态</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">SleepingState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">State</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">writeProgram</span><span class="hljs-params">(Work w)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;当前时间:&quot;</span>  + w.getHour() + <span class="hljs-string">&quot;点 不行了，睡着了。&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 下班休息状态</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">RestState</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">State</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">writeProgram</span><span class="hljs-params">(Work w)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;当前时间:&quot;</span>  + w.getHour() + <span class="hljs-string">&quot;点 下班回家了。&quot;</span>);<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure><p><strong>状态模式的好处与用处：</strong></p><ul><li>将与特定状态相关的行为局部化，并且将不同状态的行为分割开来。</li><li>消除庞大的条件分支语句，状态模式通过把各种状态转移逻辑分布到State的子类之间，来减少相互间的依赖。</li><li>当一个对象的行为取决于它的状态，并且它必须在运行时刻根据状态改变它的行为时，就可以考虑使用状态模式了。</li></ul><h3 id="第-17-章-适配器模式">第 17 章 适配器模式</h3><p><strong>适配器模式（Adapter），将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。</strong></p><p><img src="https://cdn.gumengyo.top/Snipaste_2023-05-11_09-32-09.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter17;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AdapterPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Player</span> <span class="hljs-variable">forwards</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Forwards</span>(<span class="hljs-string">&quot;巴蒂尔&quot;</span>);<br>        forwards.attack();<br><br>        <span class="hljs-type">Player</span> <span class="hljs-variable">guards</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Guards</span>(<span class="hljs-string">&quot;麦克格雷迪&quot;</span>);<br>        guards.attack();<br><br>        <span class="hljs-type">Player</span> <span class="hljs-variable">center</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Translator</span>(<span class="hljs-string">&quot;姚明&quot;</span>);<br><br>        center.attack();<br>        center.defense();<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 球员</span><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Player</span>&#123;<br>    <span class="hljs-keyword">protected</span> String name;<br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Player</span><span class="hljs-params">(String name)</span>&#123;<br>        <span class="hljs-built_in">this</span>.name = name;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">attack</span><span class="hljs-params">()</span>; <span class="hljs-comment">// 进攻</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">defense</span><span class="hljs-params">()</span>; <span class="hljs-comment">// 防守</span><br>&#125;<br><br><span class="hljs-comment">// 前锋</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Forwards</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Player</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Forwards</span><span class="hljs-params">(String name)</span>&#123;<br>        <span class="hljs-built_in">super</span>(name);<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">attack</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;前锋 &quot;</span> + <span class="hljs-built_in">this</span>.name + <span class="hljs-string">&quot; 进攻&quot;</span>);<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">defense</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;前锋 &quot;</span> + <span class="hljs-built_in">this</span>.name + <span class="hljs-string">&quot; 防守&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 前锋</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Center</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Player</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Center</span><span class="hljs-params">(String name)</span>&#123;<br>        <span class="hljs-built_in">super</span>(name);<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">attack</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;中锋 &quot;</span> + <span class="hljs-built_in">this</span>.name + <span class="hljs-string">&quot; 进攻&quot;</span>);<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">defense</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;中锋 &quot;</span> + <span class="hljs-built_in">this</span>.name + <span class="hljs-string">&quot; 防守&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 后卫</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Guards</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Player</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Guards</span><span class="hljs-params">(String name)</span>&#123;<br>        <span class="hljs-built_in">super</span>(name);<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">attack</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;后卫 &quot;</span> + <span class="hljs-built_in">this</span>.name + <span class="hljs-string">&quot; 进攻&quot;</span>);<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">defense</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;后卫 &quot;</span> + <span class="hljs-built_in">this</span>.name + <span class="hljs-string">&quot; 防守&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 外籍中锋</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ForeignCenter</span>&#123;<br>    <span class="hljs-keyword">private</span> String name;<br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getName</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.name;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setName</span><span class="hljs-params">(String value)</span> &#123;<br>        <span class="hljs-built_in">this</span>.name = value;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> 进攻()&#123;<br>        System.out.println(<span class="hljs-string">&quot;外籍中锋 &quot;</span> +<span class="hljs-built_in">this</span>.name + <span class="hljs-string">&quot; 进攻&quot;</span>);<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> 防守()&#123;<br>        System.out.println(<span class="hljs-string">&quot;外籍中锋 &quot;</span> +<span class="hljs-built_in">this</span>.name + <span class="hljs-string">&quot; 防守&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 翻译者</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Translator</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Player</span>&#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">ForeignCenter</span> <span class="hljs-variable">foreignCenter</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ForeignCenter</span>();<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Translator</span><span class="hljs-params">(String name)</span>&#123;<br>        <span class="hljs-built_in">super</span>(name);<br>        foreignCenter.setName(name);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">attack</span><span class="hljs-params">()</span> &#123;<br>        foreignCenter.进攻();<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">defense</span><span class="hljs-params">()</span> &#123;<br>        foreignCenter.防守();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><h3 id="第-18-章-备忘录模式">第 18 章 备忘录模式</h3><p><strong>备忘录（Memento）：在不破坏封装性的前提下，捕获一个对象的内部状态，并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。</strong></p><p><img src="https://cdn.gumengyo.top/Snipaste_2023-05-11_10-19-19.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter18;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">MementoPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Originator</span> <span class="hljs-variable">o</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Originator</span>();<br>        o.setState(<span class="hljs-string">&quot;On&quot;</span>);<br>        o.show();<br><br>        <span class="hljs-type">Caretaker</span> <span class="hljs-variable">c</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Caretaker</span>();<br>        <span class="hljs-comment">// 保存状态时，由于有了很好的封装，可以隐藏Originator的实现细节</span><br>        c.setMemento(o.createMemento());<br><br>        <span class="hljs-comment">// Originator改变了状态属性为&quot;off&quot;</span><br>        o.setState(<span class="hljs-string">&quot;off&quot;</span>);<br>        o.show();<br><br>        <span class="hljs-comment">// 恢复原初始状态</span><br>        o.recoveryMemento(c.getMemento());<br>        o.show();<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 发起人</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Originator</span>&#123;<br><br>    <span class="hljs-comment">// 状态</span><br>    <span class="hljs-keyword">private</span> String state;<br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getState</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.state;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setState</span><span class="hljs-params">(String value)</span>&#123;<br>        <span class="hljs-built_in">this</span>.state = value;<br>    &#125;<br>    <span class="hljs-comment">// 显示数据</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">show</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;State:&quot;</span> + <span class="hljs-built_in">this</span>.state);<br>    &#125;<br>    <span class="hljs-comment">// 创建备忘录</span><br>    <span class="hljs-keyword">public</span> Memento <span class="hljs-title function_">createMemento</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Memento</span>(<span class="hljs-built_in">this</span>.state);<br>    &#125;<br>    <span class="hljs-comment">// 恢复备忘录</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">recoveryMemento</span><span class="hljs-params">(Memento memento)</span>&#123;<br>        <span class="hljs-built_in">this</span>.setState(memento.getState());<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 备忘录</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Memento</span>&#123;<br>    <span class="hljs-keyword">private</span> String state;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Memento</span><span class="hljs-params">(String state)</span>&#123;<br>        <span class="hljs-built_in">this</span>.state = state;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getState</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.state;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setState</span><span class="hljs-params">(String value)</span>&#123;<br>        <span class="hljs-built_in">this</span>.state = value;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 管理者</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Caretaker</span>&#123;<br>    <span class="hljs-keyword">private</span> Memento memento;<br>    <span class="hljs-keyword">public</span> Memento <span class="hljs-title function_">getMemento</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.memento;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setMemento</span><span class="hljs-params">(Memento value)</span>&#123;<br>        <span class="hljs-built_in">this</span>.memento = value;<br>    &#125;<br><br><br>&#125;<br><br></code></pre></td></tr></table></figure><h3 id="第-19-章-组合模式">第 19 章 组合模式</h3><p><strong>组合模式（Composite），将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230515181230670.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter19;<br><br><span class="hljs-keyword">import</span> java.util.ArrayList;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">CompositePattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Composite</span> <span class="hljs-variable">root</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Composite</span>(<span class="hljs-string">&quot;root&quot;</span>);<br>        root.add(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Leaf</span>(<span class="hljs-string">&quot;Leaf A&quot;</span>));<br>        root.add(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Leaf</span>(<span class="hljs-string">&quot;Leaf B&quot;</span>));<br><br>        <span class="hljs-type">Composite</span> <span class="hljs-variable">comp</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Composite</span>(<span class="hljs-string">&quot;Composite X&quot;</span>);<br>        comp.add(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Leaf</span>(<span class="hljs-string">&quot;Leaf XA&quot;</span>));<br>        comp.add(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Leaf</span>(<span class="hljs-string">&quot;Leaf XB&quot;</span>));<br>        root.add(comp);<br><br>        <span class="hljs-type">Composite</span> <span class="hljs-variable">comp2</span> <span class="hljs-operator">=</span>  <span class="hljs-keyword">new</span> <span class="hljs-title class_">Composite</span>(<span class="hljs-string">&quot;Composite XY&quot;</span>);<br>        comp2.add(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Leaf</span>(<span class="hljs-string">&quot;Leaf XYA&quot;</span>));<br>        comp2.add(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Leaf</span>(<span class="hljs-string">&quot;Leaf XYB&quot;</span>));<br>        comp.add(comp2);<br><br>        <span class="hljs-type">Leaf</span> <span class="hljs-variable">leaf</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Leaf</span>(<span class="hljs-string">&quot;Leaf C&quot;</span>);<br>        root.add(leaf);<br><br>        <span class="hljs-type">Leaf</span> <span class="hljs-variable">leaf2</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Leaf</span>(<span class="hljs-string">&quot;Leaf D&quot;</span>);<br>        root.add(leaf2);<br>        root.remove(leaf2);<br><br>        root.display(<span class="hljs-number">1</span>);<br><br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Component</span>&#123;<br>    <span class="hljs-keyword">protected</span> String name;<br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Component</span><span class="hljs-params">(String name)</span>&#123;<br>        <span class="hljs-built_in">this</span>.name = name;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">add</span><span class="hljs-params">(Component component)</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">remove</span><span class="hljs-params">(Component component)</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">display</span><span class="hljs-params">(<span class="hljs-type">int</span> depth)</span>;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Leaf</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Component</span> &#123;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Leaf</span><span class="hljs-params">(String name)</span>&#123;<br>        <span class="hljs-built_in">super</span>(name);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">add</span><span class="hljs-params">(Component component)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;Cannot add to a leaf.&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">remove</span><span class="hljs-params">(Component component)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;Cannot remove from a leaf.&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">display</span><span class="hljs-params">(<span class="hljs-type">int</span> depth)</span> &#123;<br>        <span class="hljs-comment">// 叶节点的具体显示方法，此处是显示其名称和级别</span><br>        <span class="hljs-keyword">for</span> (<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i &lt; depth; i++)<br>            System.out.print(<span class="hljs-string">&quot;-&quot;</span>);<br>        System.out.println(name);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Composite</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Component</span>&#123;<br><br>    <span class="hljs-keyword">private</span> ArrayList&lt;Component&gt; children = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span>&lt;Component&gt;(); <span class="hljs-comment">// 一个子对象集合用来存储其下属的枝节点和叶节点</span><br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Composite</span><span class="hljs-params">(String name)</span>&#123;<br>        <span class="hljs-built_in">super</span>(name);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">add</span><span class="hljs-params">(Component component)</span> &#123;<br>        children.add(component);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">remove</span><span class="hljs-params">(Component component)</span> &#123;<br>        children.remove(component);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">display</span><span class="hljs-params">(<span class="hljs-type">int</span> depth)</span> &#123;<br>        <span class="hljs-comment">// 显示其枝节点名称</span><br>        <span class="hljs-keyword">for</span> (<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;i&lt;depth;i++)<br>            System.out.print(<span class="hljs-string">&quot;-&quot;</span>);<br>        System.out.println(name);<br>        <span class="hljs-comment">// 对其下级进行遍历</span><br>        <span class="hljs-keyword">for</span> (Component item : children) &#123;<br>            item.display(depth+<span class="hljs-number">2</span>);<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>需求中是体现部分与整体层次的结构时，希望用户可以忽略组合对象与单个对象的不同，统一地使用组合结构中的所有对象时，就应该考虑用组合模式。</p><h3 id="第-20-章-迭代器模式">第 20 章 迭代器模式</h3><p><strong>迭代器模式（Iterator），提供一种方法顺序访问一个聚合对象中的各个元素，而又不暴露该对象的内部表示。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230515193830432.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter20;<br><br><span class="hljs-keyword">import</span> java.util.ArrayList;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">IteratorPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">ConcreteAggregate</span> <span class="hljs-variable">bus</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteAggregate</span>();<br>        bus.add(<span class="hljs-string">&quot;大鸟&quot;</span>);<br>        bus.add(<span class="hljs-string">&quot;小菜&quot;</span>);<br>        bus.add(<span class="hljs-string">&quot;行李&quot;</span>);<br>        bus.add(<span class="hljs-string">&quot;老外&quot;</span>);<br>        bus.add(<span class="hljs-string">&quot;公交内部员工&quot;</span>);<br>        bus.add(<span class="hljs-string">&quot;小偷&quot;</span>);<br><br>        <span class="hljs-type">Iterator</span> <span class="hljs-variable">conductor</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteIterator</span>(bus);<br><br>        conductor.first();<br>        <span class="hljs-keyword">while</span> (!conductor.isDone())&#123;<br>            System.out.println(conductor.currentItem() + <span class="hljs-string">&quot;，请买车票!&quot;</span>);<br>            conductor.next();<br>        &#125;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 聚集抽象类</span><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Aggregate</span>&#123;<br>    <span class="hljs-comment">// 创建迭代器</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> Iterator <span class="hljs-title function_">createIterator</span><span class="hljs-params">()</span>;<br>&#125;<br><br><span class="hljs-comment">// 具体聚集类，继承Aggregate</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteAggregate</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Aggregate</span>&#123;<br><br>    <span class="hljs-comment">// 声明一个ArrayList泛型变量，用于存放聚合对象</span><br>    <span class="hljs-keyword">private</span> ArrayList&lt;Object&gt; items = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span>&lt;Object&gt;();<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Iterator <span class="hljs-title function_">createIterator</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteIterator</span>(<span class="hljs-built_in">this</span>);<br>    &#125;<br><br>    <span class="hljs-comment">// 返回聚焦总个数</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">getCount</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">return</span> items.size();<br>    &#125;<br><br>    <span class="hljs-comment">// 增加新对象</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">add</span><span class="hljs-params">(Object object)</span>&#123;<br>        items.add(object);<br>    &#125;<br><br>    <span class="hljs-comment">// 得到指定索引对象</span><br>    <span class="hljs-keyword">public</span> Object <span class="hljs-title function_">getCurrentItem</span><span class="hljs-params">(<span class="hljs-type">int</span> index)</span>&#123;<br>        <span class="hljs-keyword">return</span> items.get(index);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 迭代器抽象类</span><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Iterator</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> Object <span class="hljs-title function_">first</span><span class="hljs-params">()</span>;             <span class="hljs-comment">// 第一个</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> Object <span class="hljs-title function_">next</span><span class="hljs-params">()</span>;              <span class="hljs-comment">// 下一个</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isDone</span><span class="hljs-params">()</span>;            <span class="hljs-comment">// 是否到最后</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> Object <span class="hljs-title function_">currentItem</span><span class="hljs-params">()</span>;       <span class="hljs-comment">// 当前对象</span><br>&#125;<br><br><span class="hljs-comment">// 具体迭代器类，继承Iterator</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteIterator</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Iterator</span>&#123;<br><br>    <span class="hljs-keyword">private</span> ConcreteAggregate aggregate;<br>    <span class="hljs-keyword">private</span> <span class="hljs-type">int</span> <span class="hljs-variable">current</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;<br><br>    <span class="hljs-comment">// 初始化时将具体的聚焦对象传入</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">ConcreteIterator</span><span class="hljs-params">(ConcreteAggregate aggregate)</span>&#123;<br>        <span class="hljs-built_in">this</span>.aggregate = aggregate;<br>    &#125;<br><br>    <span class="hljs-comment">// 得到第一个对象</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Object <span class="hljs-title function_">first</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> aggregate.getCurrentItem(<span class="hljs-number">0</span>);<br>    &#125;<br><br>    <span class="hljs-comment">// 得到下一个对象</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Object <span class="hljs-title function_">next</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-type">Object</span> <span class="hljs-variable">ret</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br>        current++;<br>        <span class="hljs-keyword">if</span> (current &lt; aggregate.getCount())&#123;<br>            ret = aggregate.getCurrentItem(current);<br>        &#125;<br>        <span class="hljs-keyword">return</span> ret;<br>    &#125;<br><br>    <span class="hljs-comment">// 判断当前是否遍历到结尾，到结尾返回true</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isDone</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> current &gt;= aggregate.getCount() ? <span class="hljs-literal">true</span> : <span class="hljs-literal">false</span>;<br>    &#125;<br><br>    <span class="hljs-comment">// 返回当前的聚集对象</span><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> Object <span class="hljs-title function_">currentItem</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> aggregate.getCurrentItem(current);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>当你需要对聚集有多种方式遍历时，可以考虑用迭代器模式。</p><p>迭代器（Iterator）模式就是分离了集合对象的遍历行为，抽象出一个迭代器类来负责，这样既可以做到不暴露集合的内部结构，又可以让外部代码透明地访问集合内部的数据。</p><h3 id="第-21-章-单例模式">第 21 章 单例模式</h3><p><strong>单例模式（Singleton），保证一个类仅有一个实例，并提供一个访问它的全局访问点。</strong></p><p><strong>懒汉单例：要在第一次被引用时，才会将自己实例化</strong></p><figure class="highlight java"><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 java"><span class="hljs-comment">// 单例模式（懒汉单例）</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Singleton</span> &#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Singleton instance;<br><br>    <span class="hljs-comment">// 构造方法private化</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-title function_">Singleton1</span><span class="hljs-params">()</span>&#123;<br><br>    &#125;<br><br>    <span class="hljs-comment">// 得到Singleton的实例（唯一途径）</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title function_">getInstance</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">if</span> (instance == <span class="hljs-literal">null</span>)&#123;<br>            instance = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Singleton</span>();<br>        &#125;<br>        <span class="hljs-keyword">return</span> instance;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p><strong>饿汉单例：静态初始化的方式是在自己被加载时就将自己实例化</strong></p><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Singleton</span> &#123;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-type">Singleton</span> <span class="hljs-variable">instance</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Singleton</span>();<br><br>    <span class="hljs-comment">// 构造方法private化</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-title function_">Singleton</span><span class="hljs-params">()</span>&#123;<br><br>    &#125;<br><br>    <span class="hljs-comment">// 得到Singleton的实例（唯一途径）</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title function_">getInstance</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> instance;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><h3 id="第-22-章-桥接模式">第 22 章 桥接模式</h3><p><strong>合成/聚合复用原则（CAPP），尽量使用合成/聚合，尽量不要使用类继承。</strong></p><p><strong>桥接模式（Bridge），将抽象部分与它的实现部分分离，使它们都可以独立地变化。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230516164259051.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter22;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">BridgePattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        Abstraction ab;<br>        ab = <span class="hljs-keyword">new</span> <span class="hljs-title class_">RefinedAbstraction</span>();<br><br>        ab.setImplementor(<span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteImplementorA</span>());<br>        ab.operation();<br><br>        ab.setImplementor(<span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteImplementorB</span>());<br>        ab.operation();<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Implementor</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">operation</span><span class="hljs-params">()</span>;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteImplementorA</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Implementor</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">operation</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;具体实现A的方法执行&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteImplementorB</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Implementor</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">operation</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;具体实现B的方法执行&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Abstraction</span>&#123;<br>    <span class="hljs-keyword">protected</span> Implementor implementor;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setImplementor</span><span class="hljs-params">(Implementor implementor)</span>&#123;<br>        <span class="hljs-built_in">this</span>.implementor = implementor;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">operation</span><span class="hljs-params">()</span>;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">RefinedAbstraction</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Abstraction</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">operation</span><span class="hljs-params">()</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;具体的Abstraction&quot;</span>);<br>        implementor.operation();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p><strong>实现系统可能有多角度分类，每一种分类都有可能变化，那么就把这种多角度分离出来让它们独立变化，减少它们之间的耦合。</strong></p><h3 id="第-23-章-命令模式">第 23 章 命令模式</h3><p><strong>命令模式（Command），讲一个请求封装为一个对象，从而使你可用不同的请求对客户进行参数化；对请求排队或记录请求日志，以及支持可撤销的操作。</strong></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter23;<br><br><span class="hljs-keyword">import</span> java.text.SimpleDateFormat;<br><span class="hljs-keyword">import</span> java.util.ArrayList;<br><span class="hljs-keyword">import</span> java.util.Date;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">CommandPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-comment">// 开店前的准备</span><br>        <span class="hljs-type">Barbecuer</span> <span class="hljs-variable">boy</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Barbecuer</span>(); <span class="hljs-comment">// 烤肉厨师</span><br>        <span class="hljs-type">Command</span> <span class="hljs-variable">bakeMuttonCommand1</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BakeMuttonCommand</span>(boy);    <span class="hljs-comment">// 烤羊肉串</span><br>        <span class="hljs-type">Command</span> <span class="hljs-variable">bakeChickenWingCommand1</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BakeChickenWingCommand</span>(boy);    <span class="hljs-comment">// 烤羊肉串</span><br>        <span class="hljs-type">Waiter</span> <span class="hljs-variable">girl</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Waiter</span>(); <span class="hljs-comment">// 服务员</span><br><br>        System.out.println(<span class="hljs-string">&quot;开门营业，顾客点菜&quot;</span>);<br>        girl.setOrder(bakeMuttonCommand1);      <span class="hljs-comment">// 下单烤羊肉串</span><br>        girl.setOrder(bakeMuttonCommand1);      <span class="hljs-comment">// 下单烤羊肉串</span><br>        girl.setOrder(bakeMuttonCommand1);      <span class="hljs-comment">// 下单烤羊肉串</span><br>        girl.setOrder(bakeMuttonCommand1);      <span class="hljs-comment">// 下单烤羊肉串</span><br>        girl.setOrder(bakeMuttonCommand1);      <span class="hljs-comment">// 下单烤羊肉串</span><br><br>        girl.cancelOrder(bakeMuttonCommand1);   <span class="hljs-comment">// 取消一串羊肉串订单</span><br><br>        girl.setOrder(bakeChickenWingCommand1); <span class="hljs-comment">// 下单烤鸡翅</span><br><br>        System.out.println(<span class="hljs-string">&quot;点菜完毕，通知厨房烧菜&quot;</span>);<br>        girl.notifyCommand();       <span class="hljs-comment">//通知厨师</span><br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 烤肉串者</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Barbecuer</span>&#123;<br>    <span class="hljs-comment">// 烤羊肉</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">bakeMutton</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;烤羊肉串！&quot;</span>);<br>    &#125;<br>    <span class="hljs-comment">// 烤鸡翅</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">bakeChickenWing</span><span class="hljs-params">()</span>&#123;<br>        System.out.println(<span class="hljs-string">&quot;烤鸡翅！&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 抽象命令类</span><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Command</span>&#123;<br>    <span class="hljs-keyword">protected</span> Barbecuer receiver;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Command</span><span class="hljs-params">(Barbecuer receiver)</span>&#123;<br>        <span class="hljs-built_in">this</span>.receiver = receiver;<br>    &#125;<br>    <span class="hljs-comment">// 执行命令</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">excuteCommand</span><span class="hljs-params">()</span>;<br>&#125;<br><br><span class="hljs-comment">// 烤羊肉命令类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">BakeMuttonCommand</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Command</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">BakeMuttonCommand</span><span class="hljs-params">(Barbecuer receiver)</span>&#123;<br>        <span class="hljs-built_in">super</span>(receiver);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">excuteCommand</span><span class="hljs-params">()</span> &#123;<br>        receiver.bakeMutton();<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 烤鸡翅命令类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">BakeChickenWingCommand</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Command</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">BakeChickenWingCommand</span><span class="hljs-params">(Barbecuer receiver)</span>&#123;<br>        <span class="hljs-built_in">super</span>(receiver);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">excuteCommand</span><span class="hljs-params">()</span> &#123;<br>        receiver.bakeChickenWing();<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 服务员类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Waiter</span>&#123;<br>    <span class="hljs-keyword">private</span> ArrayList&lt;Command&gt; orders = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span>&lt;Command&gt;();<br><br>    <span class="hljs-comment">// 设置订单</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setOrder</span><span class="hljs-params">(Command command)</span>&#123;<br>        String className= command.getClass().getSimpleName();<br><br>        <span class="hljs-keyword">if</span> (className.equals(<span class="hljs-string">&quot;BakeChickenWingCommand&quot;</span>))&#123;<br>            System.out.println(<span class="hljs-string">&quot;服务员：鸡翅没有了，请点别的烧烤。&quot;</span>);<br>        &#125;<span class="hljs-keyword">else</span> &#123;<br>            <span class="hljs-built_in">this</span>.orders.add(command);<br>            System.out.println(<span class="hljs-string">&quot;增加订单：&quot;</span>+className + <span class="hljs-string">&quot;时间：&quot;</span>+getNowTime());<br>        &#125;<br>    &#125;<br>    <span class="hljs-comment">// 取消订单</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">cancelOrder</span><span class="hljs-params">(Command command)</span>&#123;<br>        <span class="hljs-type">String</span> <span class="hljs-variable">className</span> <span class="hljs-operator">=</span> command.getClass().getSimpleName();<br>        orders.remove(command);<br>        System.out.println(<span class="hljs-string">&quot;取消订单：&quot;</span>+className+<span class="hljs-string">&quot; 时间：&quot;</span> + getNowTime());<br>    &#125;<br>    <span class="hljs-comment">// 通知执行</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">notifyCommand</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-keyword">for</span> (Command command : orders) &#123;<br>            command.excuteCommand();<br>        &#125;<br>    &#125;<br><br>    <span class="hljs-keyword">private</span> String <span class="hljs-title function_">getNowTime</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-type">SimpleDateFormat</span> <span class="hljs-variable">formatter</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SimpleDateFormat</span>(<span class="hljs-string">&quot;HH:mm:ss&quot;</span>);<br>        <span class="hljs-keyword">return</span> formatter.format(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>()).toString();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>优点：</p><ul><li>能较容易地设计一个命令队列</li><li>在需要的情况下，可以较容易地将命令记入日志</li><li>允许接收请求的一方决定是否要否决请求</li><li>可以容易地实现对请求的撤销和重做</li><li>由于加进新的具体命令类不影响其他的类，因此增加新的具体命令类很容易</li><li>命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分隔开</li></ul><h3 id="第-24-章-职责链模式">第 24 章 职责链模式</h3><p><strong>职责链模式（Chain of Responsibility）：使多个对象都有机会处理请求，从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链，并沿着这条链传递该请求，直到有一个对象处理它为止。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230517165824783.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter24;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">ChainOfResponsibilityPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Handler</span> <span class="hljs-variable">h1</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteHandler1</span>();<br>        <span class="hljs-type">Handler</span> <span class="hljs-variable">h2</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteHandler2</span>();<br>        <span class="hljs-type">Handler</span> <span class="hljs-variable">h3</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteHandler3</span>();<br>        h1.setSuccessor(h2);<br>        h2.setSuccessor(h3);<br><br>        <span class="hljs-type">int</span>[] requests = &#123;<span class="hljs-number">2</span>,<span class="hljs-number">5</span>,<span class="hljs-number">14</span>,<span class="hljs-number">22</span>,<span class="hljs-number">18</span>,<span class="hljs-number">3</span>,<span class="hljs-number">27</span>,<span class="hljs-number">20</span>&#125;;<br><br>        <span class="hljs-keyword">for</span> (<span class="hljs-type">int</span> request : requests) &#123;<br>            h1.handleRequest(request);<br>        &#125;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Handler</span>&#123;<br>    <span class="hljs-keyword">protected</span> Handler successor;<br><br>    <span class="hljs-comment">// 设置继任者</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setSuccessor</span><span class="hljs-params">(Handler successor)</span> &#123;<br>        <span class="hljs-built_in">this</span>.successor = successor;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">handleRequest</span><span class="hljs-params">(<span class="hljs-type">int</span> request)</span>;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteHandler1</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Handler</span> &#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">handleRequest</span><span class="hljs-params">(<span class="hljs-type">int</span> request)</span> &#123;<br>        <span class="hljs-keyword">if</span> (request &gt;= <span class="hljs-number">0</span> &amp;&amp; request &lt; <span class="hljs-number">10</span>)&#123;<br>            System.out.println(<span class="hljs-built_in">this</span>.getClass().getSimpleName() + <span class="hljs-string">&quot; 处理请求 &quot;</span>+request);<br>        &#125;<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(successor != <span class="hljs-literal">null</span>)&#123;<br>            successor.handleRequest(request);<br>        &#125;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteHandler2</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Handler</span> &#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">handleRequest</span><span class="hljs-params">(<span class="hljs-type">int</span> request)</span> &#123;<br>        <span class="hljs-keyword">if</span> (request &gt;= <span class="hljs-number">10</span> &amp;&amp; request &lt; <span class="hljs-number">20</span>)&#123;<br>            System.out.println(<span class="hljs-built_in">this</span>.getClass().getSimpleName() + <span class="hljs-string">&quot; 处理请求 &quot;</span>+request);<br>        &#125;<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(successor != <span class="hljs-literal">null</span>)&#123;<br>            successor.handleRequest(request);<br>        &#125;<br>    &#125;<br>&#125;<br><br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteHandler3</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Handler</span> &#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">handleRequest</span><span class="hljs-params">(<span class="hljs-type">int</span> request)</span> &#123;<br>        <span class="hljs-keyword">if</span> (request &gt;= <span class="hljs-number">20</span> &amp;&amp; request &lt; <span class="hljs-number">30</span>)&#123;<br>            System.out.println(<span class="hljs-built_in">this</span>.getClass().getSimpleName() + <span class="hljs-string">&quot; 处理请求 &quot;</span>+request);<br>        &#125;<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(successor != <span class="hljs-literal">null</span>)&#123;<br>            successor.handleRequest(request);<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p><strong>职责链的好处：</strong></p><ul><li>接收者和发送者都没有对方的明确信息，且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接，它们仅需保持一个指向其后继者的引用，而不需保持它所有的候选接收者的引用。</li><li>可以随时地增加或修改处理一个请求的结构。增强了给对象指派职责的灵活性。</li></ul><h3 id="第-25-章-中介者模式">第 25 章 中介者模式</h3><p><strong>中介者模式（Mediator），用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用，从而使其耦合松散，而且可以独立地改变它们之间的交互。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230517171344605.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter25;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">MediatorPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">ConcreteMediator</span> <span class="hljs-variable">m</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteMediator</span>();<br><br>        <span class="hljs-type">ConcreteColleague1</span> <span class="hljs-variable">c1</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteColleague1</span>(m);<br>        <span class="hljs-type">ConcreteColleague2</span> <span class="hljs-variable">c2</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteColleague2</span>(m);<br><br>        m.setColleague1(c1);<br>        m.setColleague2(c2);<br><br>        c1.send(<span class="hljs-string">&quot;吃过饭了吗？&quot;</span>);<br>        c2.send(<span class="hljs-string">&quot;没有呢，你打算请客？&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Colleague</span>&#123;<br>    <span class="hljs-keyword">protected</span> Mediator mediator;<br>    <span class="hljs-comment">// 构造方法，得到中介者对象</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">Colleague</span><span class="hljs-params">(Mediator mediator)</span>&#123;<br>        <span class="hljs-built_in">this</span>.mediator = mediator;<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteColleague1</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Colleague</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">ConcreteColleague1</span><span class="hljs-params">(Mediator mediator)</span>&#123;<br>        <span class="hljs-built_in">super</span>(mediator);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">send</span><span class="hljs-params">(String message)</span> &#123;<br>        <span class="hljs-built_in">this</span>.mediator.send(message,<span class="hljs-built_in">this</span>);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">notify</span><span class="hljs-params">(String message)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;同事1得到信息：&quot;</span>+message);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteColleague2</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Colleague</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">ConcreteColleague2</span><span class="hljs-params">(Mediator mediator)</span>&#123;<br>        <span class="hljs-built_in">super</span>(mediator);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">send</span><span class="hljs-params">(String message)</span> &#123;<br>        <span class="hljs-built_in">this</span>.mediator.send(message,<span class="hljs-built_in">this</span>);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">notify</span><span class="hljs-params">(String message)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;同事2得到信息：&quot;</span>+message);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 中介者类</span><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Mediator</span>&#123;<br>    <span class="hljs-comment">// 定义一个抽象的发送消息方法，得到同事对象和发送消息</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">send</span><span class="hljs-params">(String message,Colleague colleague)</span>;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteMediator</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Mediator</span> &#123;<br><br>    <span class="hljs-keyword">private</span> ConcreteColleague1 colleague1;<br>    <span class="hljs-keyword">private</span> ConcreteColleague2 colleague2;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setColleague1</span><span class="hljs-params">(ConcreteColleague1 value)</span>&#123;<br>        <span class="hljs-built_in">this</span>.colleague1 = value;<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setColleague2</span><span class="hljs-params">(ConcreteColleague2 value)</span>&#123;<br>        <span class="hljs-built_in">this</span>.colleague2 = value;<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">send</span><span class="hljs-params">(String message, Colleague colleague)</span> &#123;<br>        <span class="hljs-keyword">if</span> (colleague == colleague1)&#123;<br>            colleague2.notify(message);<br>        &#125;<span class="hljs-keyword">else</span> &#123;<br>            colleague1.notify(message);<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的场合，以及想定制一个分布在多个类中的行为，而又不想生成太多的子类的场合。</p><h3 id="第-26-章-享元模式">第 26 章 享元模式</h3><p><strong>享元模式（Flyweight），运用共享技术有效地支持大量细粒度的对象。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230518185501261.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter26;<br><br><span class="hljs-keyword">import</span> java.util.Hashtable;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">FlyweightPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">int</span> <span class="hljs-variable">extrinsicstate</span> <span class="hljs-operator">=</span> <span class="hljs-number">22</span>;<br><br>        <span class="hljs-type">FlyweightFactory</span> <span class="hljs-variable">f</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">FlyweightFactory</span>();<br><br>        <span class="hljs-type">Flyweight</span> <span class="hljs-variable">fx</span> <span class="hljs-operator">=</span> f.getFlyweight(<span class="hljs-string">&quot;X&quot;</span>);<br>        fx.operation(--extrinsicstate);<br><br>        <span class="hljs-type">Flyweight</span> <span class="hljs-variable">fy</span> <span class="hljs-operator">=</span> f.getFlyweight(<span class="hljs-string">&quot;Y&quot;</span>);<br>        fy.operation(--extrinsicstate);<br><br>        <span class="hljs-type">Flyweight</span> <span class="hljs-variable">fz</span> <span class="hljs-operator">=</span> f.getFlyweight(<span class="hljs-string">&quot;Z&quot;</span>);<br>        fz.operation(--extrinsicstate);<br><br>        <span class="hljs-type">Flyweight</span> <span class="hljs-variable">uf</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UnsharedConcreteFlyweight</span>();<br><br>        uf.operation(--extrinsicstate);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Flyweight</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">operation</span><span class="hljs-params">(<span class="hljs-type">int</span> extrinsicstate)</span>;<br>&#125;<br><br><span class="hljs-comment">// 需要共享的具体Flyweight子类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteFlyweight</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Flyweight</span>&#123;<br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">operation</span><span class="hljs-params">(<span class="hljs-type">int</span> extrinsicstate)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;具体Flyweight:&quot;</span> + extrinsicstate);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 不需要共享的Flyweight子类</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">UnsharedConcreteFlyweight</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Flyweight</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">operation</span><span class="hljs-params">(<span class="hljs-type">int</span> extrinsicstate)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;不共享的具体Flyweight:&quot;</span> + extrinsicstate);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 享元工厂</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">FlyweightFactory</span>&#123;<br>    <span class="hljs-keyword">private</span> Hashtable&lt;String,Flyweight&gt; flyweights = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Hashtable</span>&lt;String,Flyweight&gt;();<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">FlyweightFactory</span><span class="hljs-params">()</span>&#123;<br>        flyweights.put(<span class="hljs-string">&quot;X&quot;</span>,<span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteFlyweight</span>());<br>        flyweights.put(<span class="hljs-string">&quot;Y&quot;</span>,<span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteFlyweight</span>());<br>        flyweights.put(<span class="hljs-string">&quot;Z&quot;</span>,<span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteFlyweight</span>());<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> Flyweight <span class="hljs-title function_">getFlyweight</span><span class="hljs-params">(String key)</span>&#123;<br>        <span class="hljs-keyword">return</span> flyweights.get(key);<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>如果一个应用程序使用了大量的对象，而大量的这些对象造成了很大的存储开销时就应该考虑使用享元模式；还有就是对象的大多数状态可以是外部状态，如果删除对象的外部状态，那么可以相对较少的共享对象取代很多组对象，此时可以考虑使用享元模式。</p><h3 id="第-27-章-解释器模式">第 27 章 解释器模式</h3><p><strong>解释器模式（interpreter），给定一个语言，定义它的文法的一种表示，并定义一个解释器，这个解释器使用该表示来解释语言中的句子。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230518191404357.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter27;<br><br><span class="hljs-keyword">import</span> java.util.ArrayList;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">InterpreterPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">Context</span> <span class="hljs-variable">context</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Context</span>();<br>        ArrayList&lt;AbstractExpression&gt; list = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span>&lt;AbstractExpression&gt;();<br>        list.add(<span class="hljs-keyword">new</span> <span class="hljs-title class_">TerminalExpression</span>());<br>        list.add(<span class="hljs-keyword">new</span> <span class="hljs-title class_">NonterminalExpression</span>());<br>        list.add(<span class="hljs-keyword">new</span> <span class="hljs-title class_">TerminalExpression</span>());<br>        list.add(<span class="hljs-keyword">new</span> <span class="hljs-title class_">TerminalExpression</span>());<br><br>        <span class="hljs-keyword">for</span> (AbstractExpression exp : list) &#123;<br>            exp.interpret(context);<br>        &#125;<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 抽象表达式</span><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AbstractExpression</span>&#123;<br>    <span class="hljs-comment">// 解释操作</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">interpret</span><span class="hljs-params">(Context context)</span>;<br>&#125;<br><br><span class="hljs-comment">// 终结符表达式</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">TerminalExpression</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">AbstractExpression</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">interpret</span><span class="hljs-params">(Context context)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;终端解释器&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-comment">// 非终结符表达式</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">NonterminalExpression</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">AbstractExpression</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">interpret</span><span class="hljs-params">(Context context)</span> &#123;<br>        System.out.println(<span class="hljs-string">&quot;非终端解释器&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Context</span>&#123;<br>    <span class="hljs-keyword">private</span> String input;<br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getInput</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.input;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setInput</span><span class="hljs-params">(String value)</span>&#123;<br>        <span class="hljs-built_in">this</span>.input = value;<br>    &#125;<br><br>    <span class="hljs-keyword">private</span> String output;<br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">getOutput</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.output;<br>    &#125;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">setOutput</span><span class="hljs-params">(String value)</span>&#123;<br>        <span class="hljs-built_in">this</span>.output = value;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>如果一种特定类型的问题发生的频率足够高，那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。</p><p>这样就可以构建一个解释器，该解释器通过解释这些句子来解决该问题。</p><h3 id="第-28-章-访问者模式">第 28 章 访问者模式</h3><p><strong>访问者模式（Visitor），表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。</strong></p><p><img src="https://cdn.gumengyo.top//image-20230520200148737.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight java"><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.jishuqin.chapter28;<br><br><span class="hljs-keyword">import</span> java.util.ArrayList;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">VisitorPattern</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> &#123;<br>        <span class="hljs-type">ObjectStructure</span> <span class="hljs-variable">o</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ObjectStructure</span>();<br>        o.attach(<span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteElementA</span>());<br>        o.attach(<span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteElementB</span>());<br><br>        <span class="hljs-type">ConcreteVisitor1</span> <span class="hljs-variable">v1</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteVisitor1</span>();<br>        <span class="hljs-type">ConcreteVisitor2</span> <span class="hljs-variable">v2</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ConcreteVisitor2</span>();<br><br>        o.accept(v1);<br>        o.accept(v2);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Visitor</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">visitConcreteElementA</span><span class="hljs-params">(ConcreteElementA concreteElementA)</span>;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">visitConcreteElementB</span><span class="hljs-params">(ConcreteElementB concreteElementB)</span>;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteVisitor1</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Visitor</span> &#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">visitConcreteElementA</span><span class="hljs-params">(ConcreteElementA concreteElementA)</span> &#123;<br>        System.out.println(concreteElementA.getClass().getSimpleName()+<span class="hljs-string">&quot;被&quot;</span>+<span class="hljs-built_in">this</span>.getClass().getSimpleName()+<span class="hljs-string">&quot;访问&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">visitConcreteElementB</span><span class="hljs-params">(ConcreteElementB concreteElementB)</span> &#123;<br>        System.out.println(concreteElementB.getClass().getSimpleName()+<span class="hljs-string">&quot;被&quot;</span>+<span class="hljs-built_in">this</span>.getClass().getSimpleName()+<span class="hljs-string">&quot;访问&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteVisitor2</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Visitor</span> &#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">visitConcreteElementA</span><span class="hljs-params">(ConcreteElementA concreteElementA)</span> &#123;<br>        System.out.println(concreteElementA.getClass().getSimpleName()+<span class="hljs-string">&quot;被&quot;</span>+<span class="hljs-built_in">this</span>.getClass().getSimpleName()+<span class="hljs-string">&quot;访问&quot;</span>);<br>    &#125;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">visitConcreteElementB</span><span class="hljs-params">(ConcreteElementB concreteElementB)</span> &#123;<br>        System.out.println(concreteElementB.getClass().getSimpleName()+<span class="hljs-string">&quot;被&quot;</span>+<span class="hljs-built_in">this</span>.getClass().getSimpleName()+<span class="hljs-string">&quot;访问&quot;</span>);<br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Element</span>&#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">accept</span><span class="hljs-params">(Visitor visitor)</span>;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteElementA</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Element</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">accept</span><span class="hljs-params">(Visitor visitor)</span> &#123;<br>        visitor.visitConcreteElementA(<span class="hljs-built_in">this</span>);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">operationA</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-comment">// 其他相关操作</span><br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ConcreteElementB</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">Element</span>&#123;<br><br>    <span class="hljs-meta">@Override</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">accept</span><span class="hljs-params">(Visitor visitor)</span> &#123;<br>        visitor.visitConcreteElementB(<span class="hljs-built_in">this</span>);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">operationA</span><span class="hljs-params">()</span>&#123;<br>        <span class="hljs-comment">// 其他相关操作</span><br>    &#125;<br>&#125;<br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ObjectStructure</span>&#123;<br>    <span class="hljs-keyword">private</span> ArrayList&lt;Element&gt; elements = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span>&lt;Element&gt;();<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">attach</span><span class="hljs-params">(Element element)</span>&#123;<br>        elements.add(element);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">detach</span><span class="hljs-params">(Element element)</span>&#123;<br>        elements.remove(element);<br>    &#125;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">accept</span><span class="hljs-params">(Visitor visitor)</span>&#123;<br>        <span class="hljs-keyword">for</span> (Element element : elements) &#123;<br>            element.accept(visitor);<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure><p>访问者模式的目的是要把处理从数据结构分离出来，有比较稳定的数据结构，又有易于变化的算法的话，使用访问者模式就是比较合适的，因为访问者模式使得算法操作的增加变得容易。</p><p>访问者模式的优点就是增加新的操作很容易，因为增加新的操作就意味着增加一个新的访问者。</p><p>访问者模式将有关的行为集中到一个访问者对象中。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;大话设计模式&quot;&gt;大话设计模式&lt;/h2&gt;
&lt;p class=&quot;note note-primary&quot;&gt;此文为我学习大话设计模式时的笔记，代码样例也是书里的。这本书对学习理解设计模式还是挺有帮助，推荐大家可以看看~&lt;/p&gt;
&lt;h3 id=&quot;第-0-章-面向对象基础&quot;&gt;第</summary>
      
    
    
    
    <category term="学习笔记" scheme="https://blog.jishuqin.cn/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="设计模式" scheme="https://blog.jishuqin.cn/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/"/>
    
  </entry>
  
  <entry>
    <title>Docker 配置 redis 集群3主3从</title>
    <link href="https://blog.jishuqin.cn/posts/dcba4321/"/>
    <id>https://blog.jishuqin.cn/posts/dcba4321/</id>
    <published>2023-04-20T15:33:00.000Z</published>
    <updated>2025-09-03T08:59:30.028Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Docker-配置-redis-集群3主3从">Docker 配置 redis 集群3主3从</h2><p><img src="https://cdn.gumengyo.top//202304201540834.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="1-启动docker服务">1. 启动docker服务</h3><p class="note note-warning">注意开放端口，或者关闭防火墙，否则从机连接不上主机。</p><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs crmsh">systemctl <span class="hljs-literal">start</span> docker<br></code></pre></td></tr></table></figure><h3 id="2-创建6个docker容器redis实例">2. 创建6个docker容器redis实例</h3><h4 id="1）创建实例-redis-node-1">1）创建实例 redis-node-1</h4><figure class="highlight jboss-cli"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs jboss-cli">docker run -d <span class="hljs-params">--name</span> redis-node-1 <span class="hljs-params">--net</span> host <span class="hljs-params">--privileged=true</span> -v <span class="hljs-string">/data/redis/share/redis-node-1</span>:<span class="hljs-string">/data</span> redis<span class="hljs-function">:6.0.8</span> <span class="hljs-params">--cluster-enabled</span> yes <span class="hljs-params">--appendonly</span> yes <span class="hljs-params">--port</span> 6381<br></code></pre></td></tr></table></figure><h4 id="2）创建实例-redis-node-2">2）创建实例 redis-node-2</h4><figure class="highlight jboss-cli"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs jboss-cli">docker run -d <span class="hljs-params">--name</span> redis-node-2 <span class="hljs-params">--net</span> host <span class="hljs-params">--privileged=true</span> -v <span class="hljs-string">/data/redis/share/redis-node-2</span>:<span class="hljs-string">/data</span> redis<span class="hljs-function">:6.0.8</span> <span class="hljs-params">--cluster-enabled</span> yes <span class="hljs-params">--appendonly</span> yes <span class="hljs-params">--port</span> 6382<br></code></pre></td></tr></table></figure><h4 id="3）创建实例-redis-node-3">3）创建实例 redis-node-3</h4><figure class="highlight jboss-cli"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs jboss-cli">docker run -d <span class="hljs-params">--name</span> redis-node-3 <span class="hljs-params">--net</span> host <span class="hljs-params">--privileged=true</span> -v <span class="hljs-string">/data/redis/share/redis-node-3</span>:<span class="hljs-string">/data</span> redis<span class="hljs-function">:6.0.8</span> <span class="hljs-params">--cluster-enabled</span> yes <span class="hljs-params">--appendonly</span> yes <span class="hljs-params">--port</span> 6383 <br></code></pre></td></tr></table></figure><h4 id="4）创建实例-redis-node-4">4）创建实例 redis-node-4</h4><figure class="highlight jboss-cli"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs jboss-cli">docker run -d <span class="hljs-params">--name</span> redis-node-4 <span class="hljs-params">--net</span> host <span class="hljs-params">--privileged=true</span> -v <span class="hljs-string">/data/redis/share/redis-node-4</span>:<span class="hljs-string">/data</span> redis<span class="hljs-function">:6.0.8</span> <span class="hljs-params">--cluster-enabled</span> yes <span class="hljs-params">--appendonly</span> yes <span class="hljs-params">--port</span> 6384<br></code></pre></td></tr></table></figure><h4 id="5）创建实例-redis-node-4">5）创建实例 redis-node-4</h4><figure class="highlight jboss-cli"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs jboss-cli">docker run -d <span class="hljs-params">--name</span> redis-node-5 <span class="hljs-params">--net</span> host <span class="hljs-params">--privileged=true</span> -v <span class="hljs-string">/data/redis/share/redis-node-5</span>:<span class="hljs-string">/data</span> redis<span class="hljs-function">:6.0.8</span> <span class="hljs-params">--cluster-enabled</span> yes <span class="hljs-params">--appendonly</span> yes <span class="hljs-params">--port</span> 6385<br></code></pre></td></tr></table></figure><h4 id="6）创建实例-redis-node-6">6）创建实例 redis-node-6</h4><figure class="highlight jboss-cli"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs jboss-cli">docker run -d <span class="hljs-params">--name</span> redis-node-6 <span class="hljs-params">--net</span> host <span class="hljs-params">--privileged=true</span> -v <span class="hljs-string">/data/redis/share/redis-node-6</span>:<span class="hljs-string">/data</span> redis<span class="hljs-function">:6.0.8</span> <span class="hljs-params">--cluster-enabled</span> yes <span class="hljs-params">--appendonly</span> yes <span class="hljs-params">--port</span> 6386<br></code></pre></td></tr></table></figure><p>命令解释：</p><ul><li><code>docker run</code> ：创建并运行docker容器实例</li><li><code>--name redis-node-6</code>：容器名字</li><li><code>--net host</code> ：使用宿主机的IP和端口，默认</li><li><code>--privileged=true</code>：获取宿主机root用户权限</li><li><code>-v /data/redis/share/redis-node-6:/data</code>：容器卷，宿主机地址:dockerp内部地址</li><li><code>redis:6.0.8</code>：redis镜像和版本号</li><li><code>--cluster-enabled ye</code>：开启redis集群</li><li><code>--appendonly yes</code>：开启持久化</li><li><code>--port 6386</code>：redis端口号</li></ul><p class="note note-success">运行成功，效果如下</p><p><img src="https://cdn.gumengyo.top//image-20230420160742483.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="3-进入容器构建集群关系">3. 进入容器构建集群关系</h3><p>进入容器 redis-noe-1</p><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs crmsh">docker exec -it redis-<span class="hljs-keyword">node</span><span class="hljs-title">-1</span> /bin/bash<br></code></pre></td></tr></table></figure><p class="note note-warning">注意：进入docker容器后才能执行一下命令，且注意自己的真实IP地址</p><p><strong>构建主从关系</strong></p><p><code>--cluster-replicas 1</code> 表示为每个master创建一个slave节点</p><figure class="highlight dns"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs dns">redis-cli --cluster create <span class="hljs-number">192.168.111.147</span>:<span class="hljs-number">6381 192.168</span>.<span class="hljs-number">111.147:6382</span> <span class="hljs-number">192.168.111.147</span>:<span class="hljs-number">6383 192.168</span>.<span class="hljs-number">111.147:6384</span> <span class="hljs-number">192.168.111.147</span>:<span class="hljs-number">6385 192.168</span>.<span class="hljs-number">111.147:6386</span> --cluster-replicas <span class="hljs-number">1</span><br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230420161646479.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top//image-20230420161721416.png" srcset="/img/loading.gif" lazyload alt=""></p><p><img src="https://cdn.gumengyo.top/s0yfnhqj.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="4-查看集群状态">4. 查看集群状态</h3><p>链接进入6381作为切入点，查看节点状态</p><figure class="highlight pgsql"><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 pgsql">redis-cli -p <span class="hljs-number">6381</span><br><br><span class="hljs-keyword">cluster</span> <span class="hljs-keyword">info</span><br><br><span class="hljs-keyword">cluster</span> nodes<br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230420162502394.png" srcset="/img/loading.gif" lazyload alt=""></p><p class="note note-success">若集群状态跟上图一样，则说明3主3从集群搭建成功啦~👌</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Docker-配置-redis-集群3主3从&quot;&gt;Docker 配置 redis 集群3主3从&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.gumengyo.top//202304201540834.png&quot; srcset=&quot;/img/loading</summary>
      
    
    
    
    <category term="服务配置" scheme="https://blog.jishuqin.cn/categories/%E6%9C%8D%E5%8A%A1%E9%85%8D%E7%BD%AE/"/>
    
    
    <category term="Docker" scheme="https://blog.jishuqin.cn/tags/Docker/"/>
    
    <category term="Redis" scheme="https://blog.jishuqin.cn/tags/Redis/"/>
    
  </entry>
  
  <entry>
    <title>Docker 安装 mysql 主从复制</title>
    <link href="https://blog.jishuqin.cn/posts/ff001122/"/>
    <id>https://blog.jishuqin.cn/posts/ff001122/</id>
    <published>2023-04-19T20:53:00.000Z</published>
    <updated>2025-09-03T08:59:30.028Z</updated>
    
    <content type="html"><![CDATA[<h2 id="安装-mysql-主从复制">安装 mysql 主从复制</h2><h3 id="1-新建主服务容器实例-3307">1. 新建主服务容器实例 3307</h3><figure class="highlight groovy"><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 groovy">docker run -p <span class="hljs-number">3307</span>:<span class="hljs-number">3306</span> --name mysql-master \<br>-v <span class="hljs-regexp">/mydata/</span>mysql-master<span class="hljs-regexp">/log:/</span><span class="hljs-keyword">var</span><span class="hljs-regexp">/log/</span>mysql \<br>-v <span class="hljs-regexp">/mydata/</span>mysql-master<span class="hljs-regexp">/data:/</span><span class="hljs-keyword">var</span><span class="hljs-regexp">/lib/</span>mysql \<br>-v <span class="hljs-regexp">/mydata/</span>mysql-master<span class="hljs-regexp">/conf:/</span>etc/mysql \<br>-e MYSQL_ROOT_PASSWORD=root  \<br>-d <span class="hljs-attr">mysql:</span><span class="hljs-number">5.7</span><br></code></pre></td></tr></table></figure><h3 id="2-新建-my-cnf-文件">2. 新建 my.cnf 文件</h3><p>进入/mydata/mysql–master/conf目录下新建 my.cnf，粘贴以下内容</p><figure class="highlight ini"><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 ini"><span class="hljs-section">[mysqld]</span><br><span class="hljs-comment">## 设置server_id，同一局域网中需要唯一</span><br><span class="hljs-attr">server_id</span>=<span class="hljs-number">101</span> <br><span class="hljs-comment">## 指定不需要同步的数据库名称</span><br><span class="hljs-attr">binlog-ignore-db</span>=mysql  <br><span class="hljs-comment">## 开启二进制日志功能</span><br><span class="hljs-attr">log-bin</span>=mall-mysql-bin  <br><span class="hljs-comment">## 设置二进制日志使用内存大小（事务）</span><br><span class="hljs-attr">binlog_cache_size</span>=<span class="hljs-number">1</span>M  <br><span class="hljs-comment">## 设置使用的二进制日志格式（mixed,statement,row）</span><br><span class="hljs-attr">binlog_format</span>=mixed  <br><span class="hljs-comment">## 二进制日志过期清理时间。默认值为0，表示不自动清理。</span><br><span class="hljs-attr">expire_logs_days</span>=<span class="hljs-number">7</span>  <br><span class="hljs-comment">## 跳过主从复制中遇到的所有错误或指定类型的错误，避免slave端复制中断。</span><br><span class="hljs-comment">## 如：1062错误是指一些主键重复，1032错误是因为主从数据库数据不一致</span><br><span class="hljs-attr">slave_skip_errors</span>=<span class="hljs-number">1062</span><br></code></pre></td></tr></table></figure><h3 id="3-修改好配置后重启-master-实例">3. 修改好配置后重启 master 实例</h3><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs crmsh">docker restart mysql-<span class="hljs-literal">master</span><br></code></pre></td></tr></table></figure><h3 id="4-进入mysql-master-容器">4. 进入mysql-master 容器</h3><figure class="highlight crmsh"><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 crmsh">docker exec -it mysql-<span class="hljs-keyword">master</span> <span class="hljs-title">/bin</span>/bash<br>mysql -uroot -proot<br></code></pre></td></tr></table></figure><h3 id="5-master-容器实例内创建数据同步用户">5. master 容器实例内创建数据同步用户</h3><figure class="highlight pgsql"><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 pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">USER</span> <span class="hljs-string">&#x27;slave&#x27;</span>@<span class="hljs-string">&#x27;%&#x27;</span> IDENTIFIED <span class="hljs-keyword">BY</span> <span class="hljs-string">&#x27;123456&#x27;</span>;<br><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">REPLICATION</span> SLAVE,<span class="hljs-keyword">REPLICATION</span> CLIENT <span class="hljs-keyword">ON</span> *.* <span class="hljs-keyword">TO</span> <span class="hljs-string">&#x27;slave&#x27;</span>@<span class="hljs-string">&#x27;%&#x27;</span>;<br></code></pre></td></tr></table></figure><h3 id="6-查看同步用户权限">6. 查看同步用户权限</h3><p>通过指令&quot;<strong>select user,host from user;</strong>&quot;查看备份账号IP访问权限是否为’%'，通过&quot;<strong>show grants for slave</strong>&quot;查看复制账户是否拥有REPLICATION CLIENT、REPLICATION SLAVE、SUPER、RELOAD权限；</p><figure class="highlight sql"><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 sql">use mysql;<br><br><span class="hljs-keyword">select</span> <span class="hljs-keyword">user</span>,host <span class="hljs-keyword">from</span> <span class="hljs-keyword">user</span>;<br><br><span class="hljs-keyword">show</span> grants <span class="hljs-keyword">for</span> slave;<br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230416232437814.png" srcset="/img/loading.gif" lazyload alt=""></p><p>如果没有的话使用命令授权</p><figure class="highlight pgsql"><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 pgsql"><span class="hljs-keyword">grant</span> <span class="hljs-keyword">REPLICATION</span> CLIENT <span class="hljs-keyword">ON</span> *.* <span class="hljs-keyword">TO</span> slave;<br><span class="hljs-keyword">grant</span> <span class="hljs-keyword">REPLICATION</span> SLAVE <span class="hljs-keyword">ON</span> *.* <span class="hljs-keyword">TO</span> slave;<br><span class="hljs-keyword">grant</span> SUPER <span class="hljs-keyword">ON</span> *.* <span class="hljs-keyword">TO</span> slave;<br><span class="hljs-keyword">grant</span> reload <span class="hljs-keyword">on</span> *.* <span class="hljs-keyword">to</span> slave;<br>FLUSH <span class="hljs-keyword">PRIVILEGES</span>;<br></code></pre></td></tr></table></figure><h3 id="7-新建从服务容器实例-3308">7. 新建从服务容器实例 3308</h3><figure class="highlight groovy"><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 groovy">docker run -p <span class="hljs-number">3308</span>:<span class="hljs-number">3306</span> --name mysql-slave \<br>-v <span class="hljs-regexp">/mydata/</span>mysql-slave<span class="hljs-regexp">/log:/</span><span class="hljs-keyword">var</span><span class="hljs-regexp">/log/</span>mysql \<br>-v <span class="hljs-regexp">/mydata/</span>mysql-slave<span class="hljs-regexp">/data:/</span><span class="hljs-keyword">var</span><span class="hljs-regexp">/lib/</span>mysql \<br>-v <span class="hljs-regexp">/mydata/</span>mysql-slave<span class="hljs-regexp">/conf:/</span>etc/mysql \<br>-e MYSQL_ROOT_PASSWORD=root  \<br>-d <span class="hljs-attr">mysql:</span><span class="hljs-number">5.7</span><br></code></pre></td></tr></table></figure><h3 id="8-新建-my-cnf-文件">8. 新建 my.cnf 文件</h3><p>进入/mydata/mysql-slave/conf目录下新建my.cnf</p><figure class="highlight ini"><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 ini"><span class="hljs-section">[mysqld]</span><br><span class="hljs-comment">## 设置server_id，同一局域网中需要唯一</span><br><span class="hljs-attr">server_id</span>=<span class="hljs-number">102</span><br><span class="hljs-comment">## 指定不需要同步的数据库名称</span><br><span class="hljs-attr">binlog-ignore-db</span>=mysql  <br><span class="hljs-comment">## 开启二进制日志功能，以备Slave作为其它数据库实例的Master时使用</span><br><span class="hljs-attr">log-bin</span>=mall-mysql-slave1-bin  <br><span class="hljs-comment">## 设置二进制日志使用内存大小（事务）</span><br><span class="hljs-attr">binlog_cache_size</span>=<span class="hljs-number">1</span>M  <br><span class="hljs-comment">## 设置使用的二进制日志格式（mixed,statement,row）</span><br><span class="hljs-attr">binlog_format</span>=mixed  <br><span class="hljs-comment">## 二进制日志过期清理时间。默认值为0，表示不自动清理。</span><br><span class="hljs-attr">expire_logs_days</span>=<span class="hljs-number">7</span>  <br><span class="hljs-comment">## 跳过主从复制中遇到的所有错误或指定类型的错误，避免slave端复制中断。</span><br><span class="hljs-comment">## 如：1062错误是指一些主键重复，1032错误是因为主从数据库数据不一致</span><br><span class="hljs-attr">slave_skip_errors</span>=<span class="hljs-number">1062</span>  <br><span class="hljs-comment">## relay_log配置中继日志</span><br><span class="hljs-attr">relay_log</span>=mall-mysql-relay-bin  <br><span class="hljs-comment">## log_slave_updates表示slave将复制事件写进自己的二进制日志</span><br><span class="hljs-attr">log_slave_updates</span>=<span class="hljs-number">1</span>  <br><span class="hljs-comment">## slave设置为只读（具有super权限的用户除外）</span><br><span class="hljs-attr">read_only</span>=<span class="hljs-number">1</span><br></code></pre></td></tr></table></figure><h3 id="9-修改完配置后重启slave实例">9. 修改完配置后重启slave实例</h3><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs crmsh">docker restart mysql-<span class="hljs-literal">slave</span><br></code></pre></td></tr></table></figure><h3 id="10-在主数据库中查看主从同步状态">10. 在主数据库中查看主从同步状态</h3><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs crmsh">show <span class="hljs-keyword">master</span> <span class="hljs-title">status</span>;<br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230416233143501.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="11-进入mysql–slave容器">11. 进入mysql–slave容器</h3><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">docker <span class="hljs-built_in">exec</span> -it mysql-slave /bin/bash<br><br>mysql -uroot -proot<br></code></pre></td></tr></table></figure><h3 id="12-在从数据库中配置主从复制">12. 在从数据库中配置主从复制</h3><p class="note note-warning">注意开放端口，或者关闭防火墙，否则从机连接不上主机。</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs routeros">change master <span class="hljs-keyword">to</span> <span class="hljs-attribute">master_host</span>=<span class="hljs-string">&#x27;宿主机ip&#x27;</span>, <span class="hljs-attribute">master_user</span>=<span class="hljs-string">&#x27;slave&#x27;</span>, <span class="hljs-attribute">master_password</span>=<span class="hljs-string">&#x27;123456&#x27;</span>, <span class="hljs-attribute">master_port</span>=3307, <span class="hljs-attribute">master_log_file</span>=<span class="hljs-string">&#x27;mall-mysql-bin.000001&#x27;</span>, <span class="hljs-attribute">master_log_pos</span>=617, <span class="hljs-attribute">master_connect_retry</span>=30;<br></code></pre></td></tr></table></figure><p>参数说明：</p><ul><li>master_host：主数据库的IP地址；</li><li>master_port：主数据库的运行端口；</li><li>master_user：在主数据库创建的用于同步数据的用户账号；</li><li>master_password：在主数据库创建的用于同步数据的用户密码；</li><li>master_log_file：指定从数据库要复制数据的日志文件，通过查看主数据的状态，获取File参数；</li><li>master_log_pos：指定从数据库从哪个位置开始复制数据，通过查看主数据的状态，获取Position参数；</li><li>master_connect_retry：连接失败重试的时间间隔，单位为秒。</li></ul><h3 id="13-在从数据库中开启主从同步">13. 在从数据库中开启主从同步</h3><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs crmsh"><span class="hljs-literal">start</span> <span class="hljs-literal">slave</span>;<br></code></pre></td></tr></table></figure><h3 id="14-查看从数据库主从同步状态">14. 查看从数据库主从同步状态</h3><figure class="highlight maxima"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs maxima"><span class="hljs-built_in">show</span> slave <span class="hljs-built_in">status</span> \G;<br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230416233720733.png" srcset="/img/loading.gif" lazyload alt=""></p><p><code>Slave_IO_Running</code>和<code>Slave_SQL_Running</code>状态为Yes则配置成功。</p><h3 id="15-主从复制测试">15. 主从复制测试</h3><p>主机新建库-使用库-新建表-插入数据</p><p><img src="https://cdn.gumengyo.top//image-20230416234054073.png" srcset="/img/loading.gif" lazyload alt=""></p><p>从机使用库-查看记录</p><p><img src="https://cdn.gumengyo.top//image-20230416234203024.png" srcset="/img/loading.gif" lazyload alt=""></p><p class="note note-success">主机写入数据，从机能查询到数据，则说明主从复制搭建成功~👌</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;安装-mysql-主从复制&quot;&gt;安装 mysql 主从复制&lt;/h2&gt;
&lt;h3 id=&quot;1-新建主服务容器实例-3307&quot;&gt;1. 新建主服务容器实例 3307&lt;/h3&gt;
&lt;figure class=&quot;highlight groovy&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td c</summary>
      
    
    
    
    <category term="服务配置" scheme="https://blog.jishuqin.cn/categories/%E6%9C%8D%E5%8A%A1%E9%85%8D%E7%BD%AE/"/>
    
    
    <category term="Docker" scheme="https://blog.jishuqin.cn/tags/Docker/"/>
    
    <category term="Mysql" scheme="https://blog.jishuqin.cn/tags/Mysql/"/>
    
  </entry>
  
  <entry>
    <title>Docker 基础篇笔记</title>
    <link href="https://blog.jishuqin.cn/posts/3f5a7c9b/"/>
    <id>https://blog.jishuqin.cn/posts/3f5a7c9b/</id>
    <published>2023-04-16T00:16:01.000Z</published>
    <updated>2025-09-03T08:59:30.028Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Docker-基础篇">Docker 基础篇</h2><p>尚硅谷Docker教程：<a href="https://www.bilibili.com/video/BV1gr4y1U7CY/">https://www.bilibili.com/video/BV1gr4y1U7CY/</a></p><p>docker 官网：<a href="http://www.docker.com">http://www.docker.com</a></p><p>Docker Hub 官网：<a href="https://hub.docker.com/">https://hub.docker.com/</a></p><h3 id="前言">前言</h3><h4 id="Docker简介">Docker简介</h4><p><strong>Docker是基于Go语言实现的云开源项目。</strong></p><p>Docker的主要目标是“Build，Ship and Run Any App,Anywhere”，也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理，使用户的APP（可以是一个WEB应用或数据库应用等等）及其运行环境能够做到“一次镜像，处处运行”。</p><h4 id="整体架构及底层通信原理简述">整体架构及底层通信原理简述</h4><p>Docker 是一个 C/S 模式的架构，后端是一个松耦合架构，众多模块各司其职。</p><p><img src="https://cdn.gumengyo.top//202304132205266.png" srcset="/img/loading.gif" lazyload alt=""></p><img src="https://cdn.gumengyo.top//202304132206500.png" srcset="/img/loading.gif" lazyload style="zoom:80%;" /><h3 id="一、初次启动测试">一、初次启动测试</h3><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs routeros">docker <span class="hljs-built_in">run</span> hello-world<br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//202304112210801.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="二、Docker-常用命令">二、Docker 常用命令</h3><h4 id="1-帮助启动类命令">1. 帮助启动类命令</h4><p>启动docker：<code>systemctl start docker</code><br>停l止docker：<code>systemctl stop docker</code><br>重启docker：<code>systemctl restart docker</code><br>查看docker&gt;状态：<code>systemctl status docker</code><br>开机启动：<code>systemctl enable docker</code><br>查看docker概要信息：<code>docker info</code><br>查看docker总体帮助文档：<code>docker-help</code><br>查看docker命令帮助文档：<code>docker具体命令-help</code></p><h4 id="2-镜像命令">2. 镜像命令</h4><p>列出本地主机上的镜像：<code>docker imags</code></p><ul><li>-a：列出本地所有的镜像（含历史映像层）</li><li>-q：只显示镜像ID</li></ul><p>查找镜像：<code>docker search 镜像名字</code></p><p>拉取镜像：<code>docker pull 镜像名[TAG]</code></p><ul><li>TAG为空则默认为latest</li></ul><p>查看镜像/容器/数据卷 所占用的空间：<code>docker system df</code></p><p>删除镜像：<code>docker rmi 镜像ID</code></p><ul><li>删除单个：<code>docker rmi -f 镜像ID</code></li><li>删除多个：<code>docker rmi-f 镜像名1:TAG 镜像名2:TAG</code></li><li><span style="color:red">删除全部</span>：<code>docker rmi-f $(docker images -qa)</code></li></ul><p><strong>面试题</strong>：仓库名、标签都是<none>的镜像，俗称虚悬镜像dangling image</p><h4 id="3-容器命令">3. 容器命令</h4><p>新建启动容器：<code>dokcer run [OPTIONS] IMAGE [COMMAND] [ARG...]</code></p><p>OPTIONS说明（常用）：有些是一个减号，有些是两个减号</p><p>–name=“容器新名字”    为容器指定一个名称；</p><p>-d: 后台运行容器并返回容器ID，也即启动守护式容器(后台运行)；</p><p style="color:red">-i：以交互模式运行容器，通常与 -t 同时使用；</p><p style="color:red">-t：为容器重新分配一个伪输入终端，通常与 -i 同时使用；</p><p>也即启动交互式容器(前台有伪终端，等待交互)；</p><p>-P: 随机端口映射，大写P</p><p style="color:red">-p: 指定端口映射，小写p</p><p><img src="https://cdn.gumengyo.top//202304112320335.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight applescript"><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 applescript"><span class="hljs-comment">#使用镜像centos:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。</span><br><br>docker <span class="hljs-built_in">run</span> -<span class="hljs-keyword">it</span> centos /bin/bash <br></code></pre></td></tr></table></figure><p>参数说明：</p><ul><li><p>-i: 交互式操作。</p></li><li><p>-t: 终端。</p></li><li><p>centos : centos 镜像。</p></li><li><p>/bin/bash：放在镜像名后的是命令，这里我们希望有个交互式 Shell，因此用的是 /bin/bash。</p></li><li><p>要退出终端，直接输入 exit:</p></li></ul><p>列出当前所有正在运行的容器：<code>docker ps [OPTIONS]</code></p><p>OPTIONS说明（常用）：</p><ul><li><p>-a :列出当前所有正在运行的容器+历史上运行过的</p></li><li><p>-l :显示最近创建的容器。</p></li><li><p>-n：显示最近n个创建的容器。</p></li><li><p>-q :静默模式，只显示容器编号。</p></li></ul><p><strong>退出容器</strong></p><ul><li><code>exit</code>：run进去容器，exit退出，容器停止</li><li><code>ctrl+p+q</code>：run进去容器，ctrl+p+q退出，容器不停止</li></ul><p>启动已经停止运行的容器：docker start 容器 ID 或者容器名<br>重启容器：docker restart 容器 ID 或者容器名<br>停止容器：docker stop 容器 ID 或者容器名<br>强制停止容器：docker kil 训容器ID或容器名<br>删除已停止容器：docker rm容器 ID</p><hr><p><strong>重要</strong></p><p>查看容器日志：<code>docker logs 容器ID</code></p><p>查看容器内运行的进程：<code>docker top 容器ID</code></p><p>查看容器内部细节：<code>docker inspect 容器ID</code></p><p>从容器内拷贝文件到主机上：<code>docker cp容器D:容器内路径目的主机路径</code></p><p>导出容器：<code>docker export 容器ID &gt; 文件名.tar</code></p><p>导入容器：<code>docker import - 镜像用户/镜像名:镜像版本号</code></p><p>提交容器副本使之成为一个新的镜像：</p><p><code>docker commit -m =&quot;提交的描述信息&quot; -a=&quot;作者&quot; 容器ID 要创建的目标镜像名:[标签名]</code></p><h3 id="三、docker镜像">三、docker镜像</h3><h4 id="1-镜像">1. 镜像</h4><p>镜像是一种轻量级、可执行的独立软件包，它包含运行某个软件所需的所有内容，我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等)，这个打包好的运行环境就是image镜像文件。</p><p>只有通过这个镜像文件才能生成Docker容器实例(类似Java中new出来一个对象)。</p><h4 id="2-联合文件系统">2. 联合文件系统</h4><p>UnionFS（联合文件系统）：Union文件系统（UnionFS）是一种分层、轻量级并且高性能的文件系统，它支持<strong>对文件系统的修改作为一次提交来一层层的叠加</strong>，同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承，基于基础镜像（没有父镜像），可以制作各种具体的应用镜像。</p><p>特性：一次同时加载多个文件系统，但从外面看起来，只能看到一个文件系统，联合加载会把各层文件系统叠加起来，这样最终的文件系统会包含所有底层的文件和目录</p><p>bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统，在Docker镜像的最底层是引导文件系统bootfs。这一层与我们典型的Linux/Unix系统是一样的，包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了，此时内存的使用权已由bootfs转交给内核，此时系统也会卸载bootfs。</p><p>rootfs (root file system) ，在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版，比如Ubuntu，Centos等等。</p><img src="https://cdn.gumengyo.top//202304132155002.png" srcset="/img/loading.gif" lazyload style="zoom: 80%;" /><p style="color:red">Docker镜像层都是只读的，容器层是可写的</p>当容器启动时，一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”，“容器层”之下的都叫“镜像层”。<p>所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有<strong>容器层</strong>是<strong>可写</strong>的，容器层下面的所有<strong>镜像层</strong>都是<strong>只读</strong>的。</p><img src="https://cdn.gumengyo.top//202304132202774.png" srcset="/img/loading.gif" lazyload style="zoom:80%;" /><h4 id="3-总结">3. 总结</h4><p>Docker中的镜像分层，<strong>支持通过扩展现有镜像，创建新的镜像</strong>。类似Java继承于一个Base基础类，自己再按需扩展。</p><p>新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件，就在现有镜像的基础上增加一层</p><p><img src="https://cdn.gumengyo.top//202304132234370.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="四、镜像发布到阿里云">四、镜像发布到阿里云</h3><h4 id="1-流程">1. 流程</h4><p><img src="https://cdn.gumengyo.top//202304132236033.png" srcset="/img/loading.gif" lazyload alt=""></p><h4 id="2-创建仓库镜像">2. 创建仓库镜像</h4><p>阿里云开发者平台：<a href="https://promotion.aliyun.com/ntms/act/kubernetes.html">https://promotion.aliyun.com/ntms/act/kubernetes.html</a></p><h5 id="2-1-进入容器镜像服务">2.1 进入容器镜像服务</h5><img src="https://cdn.gumengyo.top//202304132305864.png" srcset="/img/loading.gif" lazyload style="zoom:80%;" /><h5 id="2-2-选择个人实例">2.2 选择个人实例</h5><img src="https://cdn.gumengyo.top//202304132305901.png" srcset="/img/loading.gif" lazyload style="zoom:80%;" /><h5 id="2-3-创建命名空间">2.3 创建命名空间</h5> <img src="https://cdn.gumengyo.top//202304132307008.png" srcset="/img/loading.gif" lazyload style="zoom:80%;" /><p><img src="https://cdn.gumengyo.top//202304132308044.png" srcset="/img/loading.gif" lazyload alt=""></p><h5 id="2-4-创建镜像仓库">2.4 创建镜像仓库</h5><img src="https://cdn.gumengyo.top//202304132312802.png" srcset="/img/loading.gif" lazyload style="zoom: 67%;" /><img src="https://cdn.gumengyo.top//image-20230413231301774.png" srcset="/img/loading.gif" lazyload alt="image-20230413231301774" style="zoom: 67%;" /><h4 id="3-操作">3. 操作</h4><h5 id="3-1-登录阿里云Docker-Registry">3.1 登录阿里云Docker Registry</h5><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs stylus">docker login <span class="hljs-attr">--username</span>=xxxx registry<span class="hljs-selector-class">.cn-heyuan</span><span class="hljs-selector-class">.aliyuncs</span>.com<br></code></pre></td></tr></table></figure><p>用于登录的用户名为阿里云账号全名，密码为开通服务时设置的密码。</p><p>您可以在访问凭证页面修改凭证密码。</p><p><img src="https://cdn.gumengyo.top//202304132346160.png" srcset="/img/loading.gif" lazyload alt=""></p><h5 id="3-2-将镜像推送到Registry">3.2 将镜像推送到Registry</h5><figure class="highlight stylus"><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 stylus">docker tag <span class="hljs-selector-attr">[ImageId]</span> registry<span class="hljs-selector-class">.cn-heyuan</span><span class="hljs-selector-class">.aliyuncs</span>.com/gumengspace/myubuntu:<span class="hljs-selector-attr">[镜像版本号]</span><br>docker push registry<span class="hljs-selector-class">.cn-heyuan</span><span class="hljs-selector-class">.aliyuncs</span>.com/gumengspace/myubuntu:<span class="hljs-selector-attr">[镜像版本号]</span><br></code></pre></td></tr></table></figure><p>请根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数。</p><p><img src="https://cdn.gumengyo.top//202304132346040.png" srcset="/img/loading.gif" lazyload alt=""></p><h5 id="3-3-选择合适的镜像仓库地址">3.3 选择合适的镜像仓库地址</h5><p>从ECS推送镜像时，可以选择使用镜像仓库内网地址。推送速度将得到提升并且将不会损耗您的公网流量。</p><p>如果您使用的机器位于VPC网络，请使用 <a href="http://registry-vpc.cn-heyuan.aliyuncs.com">registry-vpc.cn-heyuan.aliyuncs.com</a> 作为Registry的域名登录。</p><h5 id="3-4-从Registry中拉取镜像">3.4 从Registry中拉取镜像</h5><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs stylus">docker pull registry<span class="hljs-selector-class">.cn-heyuan</span><span class="hljs-selector-class">.aliyuncs</span>.com/gumengspace/myubuntu:<span class="hljs-selector-attr">[镜像版本号]</span><br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//202304132353891.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="五、镜像发布到私有库">五、镜像发布到私有库</h3><h4 id="1-下载-Docker-Registry">1. 下载 Docker Registry</h4><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ebnf"><span class="hljs-attribute">docker pull registry</span> <br></code></pre></td></tr></table></figure><h4 id="2-运行-Docker-Registry">2. 运行 Docker Registry</h4><figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs elixir">docker run -d -p <span class="hljs-number">5000</span><span class="hljs-symbol">:</span><span class="hljs-number">5000</span> -v /zzyyuse/myregistry/<span class="hljs-symbol">:/tmp/registry</span> --privileged=<span class="hljs-literal">true</span> registry<br></code></pre></td></tr></table></figure><p>默认情况，仓库被创建在容器的/var/lib/registry目录下，建议自行用容器卷映射，方便于宿主机联调</p><h4 id="3-将镜像修改成符合私服规范的Tag">3. 将镜像修改成符合私服规范的Tag</h4><figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ruby">docker tag 镜像<span class="hljs-symbol">:Tag</span> <span class="hljs-title class_">Host</span><span class="hljs-symbol">:Port/Repository</span><span class="hljs-symbol">:Tag</span><br></code></pre></td></tr></table></figure><h4 id="4-修改配置文件使其支持http">4. 修改配置文件使其支持http</h4><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">vim <span class="hljs-regexp">/etc/</span>docker/daemon.json<br></code></pre></td></tr></table></figure><p>添加以下内容，前面有内容记得在前面加逗号：</p><p class="note note-primary">  "insecure-registries": ["192.168.111.162:5000"]</p><h4 id="5-将镜像推送到私服仓库">5. 将镜像推送到私服仓库</h4><figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ruby">docker push <span class="hljs-title class_">Host</span><span class="hljs-symbol">:Port/Repository</span><span class="hljs-symbol">:Tag</span><br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230414220410835.png" srcset="/img/loading.gif" lazyload alt=""></p><h4 id="6-curl-验证私服库上有什么镜像">6. curl 验证私服库上有什么镜像</h4><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk">curl -XGET http:<span class="hljs-regexp">//</span>Host:Port<span class="hljs-regexp">/v2/</span>_catalog<br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230414221048455.png" srcset="/img/loading.gif" lazyload alt=""></p><h4 id="7-拉取私服库的镜像到本地">7. 拉取私服库的镜像到本地</h4><figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ruby">docker pull <span class="hljs-title class_">Host</span><span class="hljs-symbol">:Port/Repository</span><span class="hljs-symbol">:Tag</span><br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230414221240641.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="六、Docker容器数据卷">六、Docker容器数据卷</h3><p>Docker挂载主机目录访问如果出现cannot open directory .: Permission denied</p><p>解决办法：在挂载目录后多加一个–privileged=true 参数即可</p><h4 id="1-是什么">1. 是什么</h4><p>卷就是目录或文件，存在于一个或多个容器中，由docker挂载到容器，但不属于联合文件系统，因此能够绕过Union File System提供一些用于持续存储或共享数据的特性：</p><p>卷的设计目的就是数据的持久化，完全独立于容器的生存周期，因此Docker不会在容器删除时删除其挂载的数据卷</p><h4 id="2-运行一个带有容器卷存储功能的容器实例">2. 运行一个带有容器卷存储功能的容器实例</h4><p>默认是rw，读写都可以</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs routeros">docker <span class="hljs-built_in">run</span> -it <span class="hljs-attribute">--privileged</span>=<span class="hljs-literal">true</span> -v/宿主机绝对路径目录:/容器内目录 镜像名<br></code></pre></td></tr></table></figure><p>只读:</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs routeros">docker <span class="hljs-built_in">run</span> -it <span class="hljs-attribute">--privileged</span>=<span class="hljs-literal">true</span> -v/宿主机绝对路径目录:/容器内目录:ro 镜像名<br></code></pre></td></tr></table></figure><h4 id="3-能干嘛">3. 能干嘛</h4><p><code>*</code>将运用与运行的环境打包镜像，run 后形成容器实例运行 ，但是我们对数据的要求希望是持久化的</p><p>Docker容器产生的数据，如果不备份，那么当容器实例删除后，容器内的数据自然也就没有了。</p><p>为了能保存数据在 docker 中我们使用卷。</p><p>特点：</p><ol><li><p>数据卷可在容器之间共享或重用数据</p></li><li><p>卷中的更改可以直接实时生效，爽</p></li><li><p>数据卷中的更改不会包含在镜像的更新中</p></li><li><p>数据卷的生命周期一直持续到没有容器使用它为止</p></li></ol><h4 id="4-卷的继承和共享">4. 卷的继承和共享</h4><p>容器1 完成和宿主机的映射</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs dockerfile">docker <span class="hljs-keyword">run</span><span class="language-bash"> -it  --privileged=<span class="hljs-literal">true</span> -v /mydocker/u:/tmp --name u1 ubuntu</span><br></code></pre></td></tr></table></figure><p>容器2 继承容器1的卷规则</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs routeros">docker <span class="hljs-built_in">run</span> -it <span class="hljs-attribute">--privileged</span>=<span class="hljs-literal">true</span> --volumes-from u1 --name u2 ubuntu<br></code></pre></td></tr></table></figure><h3 id="七、Docker-常规安装">七、Docker 常规安装</h3><h4 id="1-总体步骤">1. 总体步骤</h4><p>搜索镜像、拉取镜像、查看镜像、启动镜像、停止容器、移除容器</p><h4 id="2-安装tomcat">2. 安装tomcat</h4><p><strong>最新版</strong></p><figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs 1c">docker pull tomcat <span class="hljs-comment">// 拉取tomcat镜像</span><br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230415214301212.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs 1c">docker images <span class="hljs-comment">// 查看是否拉取到tomcat</span><br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230415214552684.png" srcset="/img/loading.gif" lazyload alt=""></p><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">docker</span> run -it -p <span class="hljs-number">8080</span>:<span class="hljs-number">8080</span> tomcat<br></code></pre></td></tr></table></figure><p>查看是否成功启动tomcat</p><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ebnf"><span class="hljs-attribute">docker ps</span><br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230415215040110.png" srcset="/img/loading.gif" lazyload alt=""></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">docker <span class="hljs-built_in">exec</span> -it 1ec9149b1335 /bin/bash <br></code></pre></td></tr></table></figure><p>查看webapps文件夹是否为空，删除空目录，修改 webapp.dist 文件夹名</p><p><img src="https://cdn.gumengyo.top//image-20230415215622241.png" srcset="/img/loading.gif" lazyload alt=""></p><p><strong>免修改版</strong></p><figure class="highlight apache"><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 apache"><span class="hljs-attribute">docker</span> pull billygoo/tomcat8-jdk8<br><br><span class="hljs-attribute">docker</span> run -d -p <span class="hljs-number">8080</span>:<span class="hljs-number">8080</span> --name mytomcat8 billygoo/tomcat8-jdk8<br></code></pre></td></tr></table></figure><h4 id="3-安装-mysql">3. 安装 mysql</h4><p>拉取 mysql 5.7镜像</p><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">docker</span> pull mysql:<span class="hljs-number">5</span>.<span class="hljs-number">7</span><br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230415221142041.png" srcset="/img/loading.gif" lazyload alt=""></p><p>新建 mysql 容器实例</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs groovy">docker run -d -p <span class="hljs-number">3306</span>:<span class="hljs-number">3306</span> --privileged=<span class="hljs-literal">true</span> -v <span class="hljs-regexp">/gmuse/</span>mysql<span class="hljs-regexp">/log:/</span><span class="hljs-keyword">var</span><span class="hljs-regexp">/log/</span>mysql -v <span class="hljs-regexp">/gmuse/</span>mysql<span class="hljs-regexp">/data:/</span><span class="hljs-keyword">var</span><span class="hljs-regexp">/lib/</span>mysql -v <span class="hljs-regexp">/gmuse/</span>mysql<span class="hljs-regexp">/conf:/</span>etc<span class="hljs-regexp">/mysql/</span>conf.d -e MYSQL_ROOT_PASSWORD=<span class="hljs-number">123456</span>  --name mysql <span class="hljs-attr">mysql:</span><span class="hljs-number">5.7</span><br></code></pre></td></tr></table></figure><p class="note note-warning">按照以下配置，修改默认字符集编码，否则会中文乱码，并且把 mysql 容器实例数据持久化。</p><p>新建my.cnf</p><figure class="highlight vim"><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 vim"><span class="hljs-keyword">cd</span> /gmuse/mysql/<span class="hljs-keyword">conf</span>/<br><br><span class="hljs-keyword">vim</span> my.<span class="hljs-keyword">cnf</span><br></code></pre></td></tr></table></figure><p>粘贴以下内容到<code>my.cnf</code></p><blockquote><p>[client]</p><p>default_character_set=utf8</p><p>[mysqld]</p><p>collation_server = utf8_general_ci</p><p>character_set_server = utf8</p></blockquote><p>重启 mysql 容器实例</p><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ebnf"><span class="hljs-attribute">docker restart mysql</span><br></code></pre></td></tr></table></figure><p>进入 mysql</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">docker <span class="hljs-built_in">exec</span> -it mysql /bin/bash<br><br>mysql -uroot -p<br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230415230356945.png" srcset="/img/loading.gif" lazyload alt=""></p><p>查看字符集，是否设置成utf8</p><figure class="highlight gams"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs gams">SHOW <span class="hljs-keyword">VARIABLES</span> LIKE <span class="hljs-comment">&#x27;character%&#x27;</span>;<br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230415230443168.png" srcset="/img/loading.gif" lazyload alt=""></p><h4 id="4-安装-redis">4. 安装 redis</h4><p>拉取 redis 6.0.8 镜像</p><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">docker</span> pull redis:<span class="hljs-number">6</span>.<span class="hljs-number">0</span>.<span class="hljs-number">8</span><br></code></pre></td></tr></table></figure><p><img src="https://cdn.gumengyo.top//image-20230415230905589.png" srcset="/img/loading.gif" lazyload alt=""></p><p>将下面redis.conf 下载之后放到 /app/redis/</p><p><a href="https://gumeng.jishuqin.cn/s/ezi5">https://gumeng.jishuqin.cn/s/ezi5</a></p><p><img src="https://cdn.gumengyo.top//image-20230416001143964.png" srcset="/img/loading.gif" lazyload alt="image-20230416001143964"></p><p>运行 redis 容器实例</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs dockerfile">docker <span class="hljs-keyword">run</span><span class="language-bash">  -p 6379:6379 --name myr3 --privileged=<span class="hljs-literal">true</span> -v /app/redis/redis.conf:/etc/redis/redis.conf -v /app/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf</span><br></code></pre></td></tr></table></figure><p>连接测试</p><figure class="highlight avrasm"><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 avrasm">docker exec -it myr3 /bin/bash<br><br>redis-<span class="hljs-keyword">cli</span><br><br><span class="hljs-built_in">ping</span><br></code></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Docker-基础篇&quot;&gt;Docker 基础篇&lt;/h2&gt;
&lt;p&gt;尚硅谷Docker教程：&lt;a href=&quot;https://www.bilibili.com/video/BV1gr4y1U7CY/&quot;&gt;https://www.bilibili.com/video/BV1</summary>
      
    
    
    
    <category term="学习笔记" scheme="https://blog.jishuqin.cn/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="Docker" scheme="https://blog.jishuqin.cn/tags/Docker/"/>
    
  </entry>
  
  <entry>
    <title>Fliud LeanCloud统计访问数据</title>
    <link href="https://blog.jishuqin.cn/posts/abcd1234/"/>
    <id>https://blog.jishuqin.cn/posts/abcd1234/</id>
    <published>2023-04-09T13:59:11.000Z</published>
    <updated>2025-09-03T08:59:30.028Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Fluid主题配置-LeanCloud-统计访问数据">Fluid主题配置 LeanCloud 统计访问数据</h2><h3 id="1-创建LeanCloud实例">1.创建LeanCloud实例</h3><p><span class="label label-primary">LeanCloud官网</span>：<a href="https://console.leancloud.cn/">https://console.leancloud.cn/</a></p><ol><li><p>进入官网，注册一个账号</p></li><li><p>登录LeanCloud 系统点击左上角创建应用</p></li></ol><img src="https://cdn.gumengyo.top//202304091408027.png" srcset="/img/loading.gif" lazyload style="zoom:50%;" /><ol start="3"><li>选择开发板创建应用即可</li></ol><p><img src="https://cdn.gumengyo.top//202304091409165.png" srcset="/img/loading.gif" lazyload alt=""></p><ol start="3"><li><p>创建应用成功后，打开应用设置-&gt;应用凭证</p><p><img src="https://cdn.gumengyo.top//202304091429140.png" srcset="/img/loading.gif" lazyload alt=""></p><p>保存 <code>AppID</code>、<code>AppKey</code>、<code>REST API</code></p></li></ol><h3 id="2-配置-config-fluid-yml文件">2.配置_config.fluid.yml文件</h3><ol><li>在<code>_config.fluid.yml</code>文件查找关键字：<code>web_analytics</code></li></ol><p class="note note-primary">开启网页访问统计功能</p><p><img src="https://cdn.gumengyo.top//202304091420333.png" srcset="/img/loading.gif" lazyload alt=""></p><ol start="2"><li>在<code>_config.fluid.yml</code>文件查找关键字：<code>leancloud</code></li></ol><p class="note note-primary">配置 leancloud 数据，将上面的 AppID、AppKey、REST API 填入对应位置</p><p><img src="https://cdn.gumengyo.top//202304091433105.png" srcset="/img/loading.gif" lazyload alt=""></p><ol start="3"><li>在<code>_config.fluid.yml</code>文件查找关键字：<code>views</code></li></ol><p class="note note-primary">开启浏览量计数</p><p><img src="https://cdn.gumengyo.top//202304091434384.png" srcset="/img/loading.gif" lazyload alt=""></p><ol start="4"><li>在<code>_config.fluid.yml</code>文件查找关键字：<code> leancloud</code></li></ol><p class="note note-primary">设置 PV、UV 统计数</p><p><img src="https://cdn.gumengyo.top//202304091436278.png" srcset="/img/loading.gif" lazyload alt=""></p><ol start="5"><li>重新部署 Hexo</li></ol><figure class="highlight nginx"><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 nginx"><span class="hljs-comment"># 清除缓存</span><br><span class="hljs-attribute">hexo</span> clean<br><br><span class="hljs-comment"># 生成静态资源</span><br>hexo g<br><br><span class="hljs-comment"># 部署</span><br>hexo d<br></code></pre></td></tr></table></figure><p><code>hexo g</code> 是 <code>hexo generate</code> 的简写；<code>hexo d</code> 是 <code>hexo deploy</code> 的简写。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Fluid主题配置-LeanCloud-统计访问数据&quot;&gt;Fluid主题配置 LeanCloud 统计访问数据&lt;/h2&gt;
&lt;h3 id=&quot;1-创建LeanCloud实例&quot;&gt;1.创建LeanCloud实例&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;label labe</summary>
      
    
    
    
    <category term="博客配置" scheme="https://blog.jishuqin.cn/categories/%E5%8D%9A%E5%AE%A2%E9%85%8D%E7%BD%AE/"/>
    
    
    <category term="Fluid" scheme="https://blog.jishuqin.cn/tags/Fluid/"/>
    
  </entry>
  
  <entry>
    <title>Redis数据结构及常见命令</title>
    <link href="https://blog.jishuqin.cn/posts/fa9b8c7d/"/>
    <id>https://blog.jishuqin.cn/posts/fa9b8c7d/</id>
    <published>2023-04-07T08:55:17.000Z</published>
    <updated>2025-09-03T08:59:30.029Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Redis数据结构及常见命令">Redis数据结构及常见命令</h2><h3 id="1-数据结构">1.数据结构</h3><p>Redis是一个key-value的数据库，key一般是String类型，不过value的类型多种多样：</p><p><img src="https://cdn.gumengyo.top//202304062339082.png" srcset="/img/loading.gif" lazyload alt=""></p><p>官网各种命令查询 <a href="https://redis.io/commands">https://redis.io/commands</a> ，也可以使用<code>help</code>命令来帮助查看命令</p><h3 id="2-通用命令">2.通用命令</h3><table><thead><tr><th>命令名</th><th>作用</th></tr></thead><tbody><tr><td><code>keys*</code></td><td>查看当前库所有的key</td></tr><tr><td><code>exists key</code></td><td>判断某个key是否存在</td></tr><tr><td><code>type key</code></td><td>查看你的key是什么类型</td></tr><tr><td><code>del key</code></td><td>删除指定的key数据</td></tr><tr><td><code>unlink key</code></td><td>非阻塞删除，仅仅将keyS从keyspace元数据中删除，<br>真正的删除会在后续异步中操作。</td></tr><tr><td><code>ttl key</code></td><td>查看还有多少秒过期，-1表示永不过期，-2表示已过期</td></tr><tr><td><code>expire key 秒钟</code></td><td>为给定的key设置过期时间</td></tr><tr><td><code>move key dbindex [0-15]</code></td><td>将当前数据库的key移动到给定的数据库db当中</td></tr><tr><td><code>select dbindex</code></td><td>切换数据库[0-15]，默认为0</td></tr><tr><td><code>dbsize</code></td><td>查看当前数据库key的数量</td></tr><tr><td><span class="label label-danger">flushdb</span></td><td>清空当前库</td></tr><tr><td><span class="label label-danger">flushall</span></td><td>通杀全部库</td></tr></tbody></table><h3 id="3-String命令">3.String命令</h3><p class="note note-primary">String类型，也就是字符串类型，是Redis中最简单的存储类型。</p><p>String的常见命令有：</p><ul><li><code>SET</code>：添加或者修改已经存在的一个String类型的键值对</li><li><code>GET</code>：根据key获取String类型的value</li><li><code>MSET</code>：批量添加多个String类型的键值对</li><li><code>MGET</code>：根据多个key获取多个String类型的value</li><li><code>INCR</code>：让一个整型的key自增1</li><li><code>INCRBY</code>:让一个整型的key自增并指定步长，例如：incrby num 2 让num值自增2</li><li><code>INCRBYFLOAT</code>：让一个浮点类型的数字自增并指定步长</li><li><code>SETNX</code>：添加一个String类型的键值对，前提是这个key不存在，否则不执行</li><li><code>SETEX</code>：添加一个String类型的键值对，并且指定有效期</li></ul><p><strong>贴心小提示</strong>：以上命令除了INCRBYFLOAT 都是常用命令</p><h3 id="4-Hash命令">4.Hash命令</h3><p class="note note-primary">Hash类型，也叫散列，其value是一个无序字典，类似于Java中的HashMap结构。</p><p>String结构是将对象序列化为JSON字符串后存储，当需要修改对象某个字段时很不方便：</p><p><img src="https://cdn.gumengyo.top//1652941995945.png" srcset="/img/loading.gif" lazyload alt=""></p><p>使用Hash结构可以将对象中的每个字段独立存储，可以针对单个字段做CRUD：</p><p><img src="https://cdn.gumengyo.top//1652942027719.png" srcset="/img/loading.gif" lazyload alt=""></p><p><strong>Hash类型的常见命令</strong></p><ul><li><p><code>HSET key field value</code>：添加或者修改hash类型key的field的值</p></li><li><p><code>HGET key field</code>：获取一个hash类型key的field的值</p></li><li><p><code>HMSET</code>：批量添加多个hash类型key的field的值</p></li><li><p><code>HMGET</code>：批量获取多个hash类型key的field的值</p></li><li><p><code>HGETALL</code>：获取一个hash类型的key中的所有的field和value</p></li><li><p><code>HKEYS</code>：获取一个hash类型的key中的所有的field</p></li><li><p><code>HINCRBY</code>：让一个hash类型key的字段值自增并指定步长</p></li><li><p><code>HSETNX</code>：添加一个hash类型的key的field值，前提是这个field不存在，否则不执行</p></li></ul><p><strong>贴心小提示</strong>：哈希结构也是我们以后实际开发中常用的命令哟</p><h3 id="5-List命令">5.List命令</h3><p class="note note-primary">Redis中的List类型与Java中的LinkedList类似，可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。</p><p>特征也与LinkedList类似：</p><ul><li>有序</li><li>元素可以重复</li><li>插入和删除快</li><li>查询速度一般</li></ul><p>常用来存储一个有序数据，例如：朋友圈点赞列表，评论列表等。</p><p><strong>List的常见命令有：</strong></p><ul><li><code>LPUSH key element ... </code>：向列表左侧插入一个或多个元素</li><li><code>LPOP key</code>：移除并返回列表左侧的第一个元素，没有则返回nil</li><li><code>RPUSH key element ...</code>：向列表右侧插入一个或多个元素</li><li><code>RPOP key</code>：移除并返回列表右侧的第一个元素</li><li><code>LRANGE key star end</code>：返回一段角标范围内的所有元素</li><li><code>BLPOP和BRPOP</code>：与LPOP和RPOP类似，只不过在没有元素时等待指定时间，而不是直接返回nil</li></ul><p><img src="https://cdn.gumengyo.top//1652943604992.png" srcset="/img/loading.gif" lazyload alt=""></p><h3 id="6-Set命令">6.Set命令</h3><p class="note note-primary">Redis的Set结构与Java中的HashSet类似，可以看做是一个value为null的HashMap。</p><p>因为也是一个hash表，因此具备与HashSet类似的特征：</p><ul><li>无序</li><li>元素不可重复</li><li>查找快</li><li>支持交集.并集.差集等功能</li></ul><p><strong>Set类型的常见命令</strong></p><ul><li><code>SADD key member ... </code>：向set中添加一个或多个元素</li><li><code>SREM key member ...</code> : 移除set中的指定元素</li><li><code>SCARD key</code>： 返回set中元素的个数</li><li><code>SISMEMBER key member</code>：判断一个元素是否存在于set中</li><li><code>SMEMBERS</code>：获取set中的所有元素</li><li><code>SINTER key1 key2 ...</code> ：求key1与key2的交集</li><li><code>SDIFF key1 key2 ...</code> ：求key1与key2的差集</li><li><code>SUNION key1 key2 ...</code>：求key1和key2的并集</li></ul><h3 id="7-SortedSet类型">7.SortedSet类型</h3><p class="note note-primary">Redis的SortedSet是一个可排序的set集合，与Java中的TreeSet有些类似，但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性，可以基于score属性对元素排序，底层的实现是一个跳表（SkipList）加 hash表。</p><p>SortedSet具备下列特性：</p><ul><li>可排序</li><li>元素不重复</li><li>查询速度快</li></ul><p>因为SortedSet的可排序特性，经常被用来实现排行榜这样的功能。</p><p>SortedSet的常见命令有：</p><ul><li><code>ZADD key score member</code>：添加一个或多个元素到sorted set ，如果已经存在则更新其score值</li><li><code>ZREM key member</code>：删除sorted set中的一个指定元素</li><li><code>ZSCORE key member</code> : 获取sorted set中的指定元素的score值</li><li><code>ZRANK key member</code>：获取sorted set 中的指定元素的排名</li><li><code>ZCARD key</code>：获取sorted set中的元素个数</li><li><code>ZCOUNT key min max</code>：统计score值在给定范围内的所有元素的个数</li><li><code>ZINCRBY key increment member</code>：让sorted set中的指定元素自增，步长为指定的increment值</li><li><code>ZRANGE key min max</code>：按照score排序后，获取指定排名范围内的元素</li><li><code>ZRANGEBYSCORE key min max</code>：按照score排序后，获取指定score范围内的元素</li><li><code>ZDIFF.ZINTER.ZUNION</code>：求差集.交集.并集</li></ul><p>注意：所有的排名默认都是升序，如果要降序则在命令的Z后面添加REV即可，例如：</p><ul><li><strong>升序</strong>获取sorted set 中的指定元素的排名：ZRANK key member</li><li><strong>降序</strong>获取sorted set 中的指定元素的排名：ZREVRANK key memeber</li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Redis数据结构及常见命令&quot;&gt;Redis数据结构及常见命令&lt;/h2&gt;
&lt;h3 id=&quot;1-数据结构&quot;&gt;1.数据结构&lt;/h3&gt;
&lt;p&gt;Redis是一个key-value的数据库，key一般是String类型，不过value的类型多种多样：&lt;/p&gt;
&lt;p&gt;&lt;img </summary>
      
    
    
    
    <category term="学习笔记" scheme="https://blog.jishuqin.cn/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="Redis" scheme="https://blog.jishuqin.cn/tags/Redis/"/>
    
  </entry>
  
  <entry>
    <title>Redis消息队列</title>
    <link href="https://blog.jishuqin.cn/posts/5e6f7a8b/"/>
    <id>https://blog.jishuqin.cn/posts/5e6f7a8b/</id>
    <published>2023-04-05T12:49:00.000Z</published>
    <updated>2025-09-03T08:59:30.029Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Redis消息队列">Redis消息队列</h2><h3 id="1-认识消息队列">1.认识消息队列</h3><p><strong>消息队列</strong>（<strong>M</strong>essage <strong>Q</strong>ueue），字面意思就是存放消息的队列。</p><p>最简单的消息队列模型包括3个角色：</p><ul><li><p>消息队列：存储和管理消息，也被称为消息代理（Message Broker）</p></li><li><p>生产者：发送消息到消息队列</p></li><li><p>消费者：从消息队列获取消息并处理消息</p></li></ul><p><img src="https://cdn.gumengyo.top//202304051317741.png" srcset="/img/loading.gif" lazyload alt=""></p><p>Redis提供了三种不同的方式来实现消息队列：</p><ul><li><p>list结构：基于List结构模拟消息队列</p></li><li><p>PubSub：基本的点对点消息模型</p></li><li><p>Stream：比较完善的消息队列模型</p></li></ul><h3 id="2-基于List实现消息队列">2.基于List实现消息队列</h3><p>Redis的list数据结构是一个双向链表，很容易模拟出队列效果。</p><p>队列是入口和出口不在一边，因此我们可以利用：LPUSH 结合 RPOP、或者 RPUSH 结合 LPOP来实现。</p><p>不过要注意的是，当队列中没有消息时RPOP或LPOP操作会返回null，并不像JVM的阻塞队列那样会阻塞并等待消息。因此这里应该使用<strong>BRPOP</strong>或者<strong>BLPOP</strong>来实现阻塞效果。</p><p>命令：</p><p><code>LPUSH key value1 [value2]</code>将一个或多个值插入到列表头部。</p><p><code> RPOP key</code>移出并获取列表的最后一个元素，如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。</p><p><code>BRPOP key1 [key2] timeout</code>：移除并获取列表最后一个元素。</p><p><code>RPUSH key value1 [value2]</code>：在列表中添加一个或多个值。</p><p><code> BLPOP key1 [key2] timeout</code>：移出并获取列表的第一个元素，如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。</p><p><img src="https://cdn.gumengyo.top//1653575176451.png" srcset="/img/loading.gif" lazyload alt=""></p><p>优点：</p><ul><li><p>利用Redis存储，不受限于JVM内存上限</p></li><li><p>基于Redis的持久化机制，数据安全性有保证</p></li><li><p>可以满足消息有序性</p></li></ul><p>缺点：</p><ul><li><p>无法避免消息丢失</p></li><li><p>只支持单消费者</p></li></ul><h3 id="3-基于PubSub的消息队列">3.基于PubSub的消息队列</h3><p><strong>PubSub（发布订阅）</strong> 是Redis2.0版本引入的消息传递模型。顾名思义，消费者可以订阅一个或多个channel，生产者向对应channel发送消息后，所有订阅者都能收到相关消息。</p><p>命令：</p><p><code>SUBSCRIBE channel [channel]</code>：订阅一个或多个频道<br><code>PUBLISH channel msg</code> ：向一个频道发送消息<br><code>PSUBSCRIBE pattern[pattern]</code>：订阅与pattern格式匹配的所有频道</p><p><img src="https://cdn.gumengyo.top/1653575506373.png" srcset="/img/loading.gif" lazyload alt=""></p><p>优点：</p><ul><li>采用发布订阅模型，支持多生产、多消费</li></ul><p>缺点：</p><ul><li>不支持数据持久化</li><li>无法避免消息丢失</li><li>消息堆积有上限，超出时数据丢失</li></ul><h3 id="4-基于Stream的消息队列">4.基于Stream的消息队列</h3><p>Stream 是 Redis 5.0 引入的一种新数据类型，可以实现一个功能非常完善的消息队列。</p><p>它支持消息的持久化、支持自动生成全局唯一ID、支持ack确认消息的模式、支持消费组模式等，让消息队列更加的稳定和可靠。</p><h5 id="Stream结构">Stream结构</h5><p><img src="https://cdn.gumengyo.top//202304051338733.png" srcset="/img/loading.gif" lazyload alt=""></p><table><thead><tr><th>名称</th><th style="text-align:left">含义</th></tr></thead><tbody><tr><td>Message Content</td><td style="text-align:left">消息内容</td></tr><tr><td>Consumer group</td><td style="text-align:left">消费组，通过XGROUP CREATE 命令创建，同一个消费组可以有多个消费者</td></tr><tr><td>Consumer</td><td style="text-align:left">游标，每个消费组会有个游标 last_delivered_id，任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。</td></tr><tr><td>Consumer</td><td style="text-align:left">消费者，消费组中的消费者</td></tr><tr><td>Pending_ids</td><td style="text-align:left">消费者，消费组中的消费者</td></tr></tbody></table><h5 id="队列相关指令">队列相关指令</h5><table><thead><tr><th>指令名称</th><th>指令作用</th></tr></thead><tbody><tr><td>XADD</td><td>添加消息到队列末尾</td></tr><tr><td>XTRIM</td><td>限制Stream的长度,如果已经超长会进行截取</td></tr><tr><td>XDEL</td><td>删除消息</td></tr><tr><td>XLEN</td><td>获取Stream中的消息长度</td></tr><tr><td>XRANGE</td><td>获取消息列表(可指定范围),忽略删除的信息</td></tr><tr><td>XREVRANGE</td><td>和XRANGE相比区别在于反向获取,ID从大到小</td></tr><tr><td>XREAD</td><td>获取消息(阻塞/非阻塞),返回大于指定ID的消息</td></tr></tbody></table><p>STREAM类型消息队列的XREAD命令特点：</p><ul><li>消息可回溯</li><li>一个消息可以被多个消费者读取</li><li>可以阻塞读取</li><li>有消息漏读的风险</li></ul><h5 id="消费组相关指令">消费组相关指令</h5><table><thead><tr><th>指令名称</th><th>指令作用</th></tr></thead><tbody><tr><td>XGROUP CREATE</td><td>创建消费者组</td></tr><tr><td>XREADGROUP GROUP</td><td>读取消费者组中的消息</td></tr><tr><td>XACK</td><td>ack消息，消息被标记为&quot;已处理</td></tr><tr><td>XGROUP SETID</td><td>设置消费者组最后递送消息的D</td></tr><tr><td>XGROUP DELCONSUMER</td><td>删除消费者组</td></tr><tr><td>XPENDING</td><td>打印待处理消息的详细信息</td></tr><tr><td>XCLAIM</td><td>转移消息的归属权（长期未被处理/无法处理的消息，转交给其他消费者组进行处理）</td></tr><tr><td>XINFO</td><td>打印Stream\Consumer八Group的详细信息</td></tr><tr><td>XINFO GROUPS</td><td>打印消费者组的详细信息</td></tr><tr><td>XINFO STREAM</td><td>打印Streaml的详细信息</td></tr></tbody></table><p>STREAM类型消息队列的XREADGROUP命令特点：</p><ul><li>消息可回溯</li><li>可以多消费者争抢消息，加快消费速度</li><li>可以阻塞读取</li><li>没有消息漏读的风险</li><li>有消息确认机制，保证消息至少被消费一次</li></ul><h5 id="四个特殊符号">四个特殊符号</h5><ol><li><p><code>- +</code> ：最小和最大可能出现的id。</p></li><li><p><code>$</code> ：$表示只消费新的消息，当前流中最大的d,可用于将要到来的信息。</p></li><li><p><code>&gt;</code> ：用于XREADGROUP命令，表示迄今还没有发送给组中使用者的信息，会更新消费者组的最后ID。</p></li><li><p><code>*</code> ：用于XADD命令中，让系统自动生成id。</p></li></ol><hr><h4 id="对比">对比:</h4><p><img src="https://cdn.gumengyo.top//202304051356489.png" srcset="/img/loading.gif" lazyload alt=""></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Redis消息队列&quot;&gt;Redis消息队列&lt;/h2&gt;
&lt;h3 id=&quot;1-认识消息队列&quot;&gt;1.认识消息队列&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;消息队列&lt;/strong&gt;（&lt;strong&gt;M&lt;/strong&gt;essage &lt;strong&gt;Q&lt;/strong&gt;ueue），</summary>
      
    
    
    
    <category term="学习笔记" scheme="https://blog.jishuqin.cn/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="Redis" scheme="https://blog.jishuqin.cn/tags/Redis/"/>
    
  </entry>
  
  <entry>
    <title>Fluid主题添加音乐功能</title>
    <link href="https://blog.jishuqin.cn/posts/eeaa9988/"/>
    <id>https://blog.jishuqin.cn/posts/eeaa9988/</id>
    <published>2023-03-05T14:07:00.000Z</published>
    <updated>2025-09-03T08:59:30.029Z</updated>
    
    <content type="html"><![CDATA[<p class="note note-success">    本文大部分配置参考林慕凡的博文，感谢作者的详细讲解。<br>    作者：林慕凡<br>    原文地址：<a href="https://blog.csdn.net/weixin_43471926/article/details/109798928?spm=1001.2014.3001.5502" target="_blank">https://blog.csdn.net/weixin_43471926/article/details/109798928?spm=1001.2014.3001.5502</a></p><p><strong>效果预览：</strong> <a href="https://blog.jishuqin.cn/playlist/">https://blog.jishuqin.cn/playlist/</a></p><img src="https://cdn.gumengyo.top//202303051412252.png" srcset="/img/loading.gif" lazyload style="zoom:50%;" /><h2 id="一、安装插件">一、安装插件</h2><p>执行命令，为Hexo安装hexo-tag-aplayer插件。</p><figure class="highlight ada"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ada">npm install <span class="hljs-comment">--save hexo-tag-aplayer</span><br></code></pre></td></tr></table></figure><h2 id="二、添加配置">二、添加配置</h2><p>安装好插件之后，在主题配置文件<span class="label label-primary">_config.fluid.yml </span>中的 custom 添加下面 js 和 css 依赖。</p><p class="note note-warning">注意：cdn.jsdelivr.net 域名有时会被墙，最好把文件部到自己的OSS，或者保存到博客的js、css目录下。</p><figure class="highlight awk"><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 awk">custom_js:<br>  - <span class="hljs-regexp">//</span>cdn.jsdelivr.net<span class="hljs-regexp">/npm/</span>aplayer<span class="hljs-regexp">/dist/</span>APlayer.min.js  <span class="hljs-comment">#/APlayer#/APlayer依赖</span><br>  - <span class="hljs-regexp">//</span>cdn.jsdelivr.net<span class="hljs-regexp">/gh/m</span>etowolf<span class="hljs-regexp">/MetingJS@1.2/</span>dist<span class="hljs-regexp">/Meting.min.js  #/</span>APlayer依赖<br>custom_css:<br>  - <span class="hljs-regexp">//</span>cdn.jsdelivr.net<span class="hljs-regexp">/npm/</span>aplayer<span class="hljs-regexp">/dist/</span>APlayer.min.css   <span class="hljs-comment">#/APlayer依赖</span><br><br></code></pre></td></tr></table></figure><p>添加完成后在hexo根目录下的配置文件<span class="label label-primary">_config.yml </span>中添加以下配置。</p><figure class="highlight yaml"><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 yaml"><span class="hljs-comment"># aplayer</span><br><span class="hljs-attr">aplayer:</span>  <br>  <span class="hljs-attr">meting:</span> <span class="hljs-literal">true</span>  <br>  <span class="hljs-attr">asset_inject:</span> <span class="hljs-literal">false</span><br></code></pre></td></tr></table></figure><h2 id="三、创建音乐页面">三、创建音乐页面</h2><figure class="highlight haxe"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs haxe">hexo <span class="hljs-keyword">new</span> <span class="hljs-type">page</span> playlist<br></code></pre></td></tr></table></figure><ol><li>打开 /根目录/source/playlist/index.md编辑页面，参考 hexo-tag-aplayer <a href="https://github.com/MoePlayer/hexo-tag-aplayer/blob/master/docs/README-zh_cn.md">官方文档</a>书写。</li></ol><p class="note note-info">复制歌单的链接，然后复制歌单的id，例如：https://music.163.com/#/playlist?id=8158874729&userid=499215828，这个歌单的id就是8158874729，而且是网易云的歌单，参考下面例子。</p><figure class="highlight twig"><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 twig"><span class="language-xml"><span class="hljs-comment">&lt;!-- 简单示例 (id, server, type)  --&gt;</span></span><br><span class="language-xml"></span><span class="hljs-template-tag">&#123;%</span> <span class="hljs-name">meting</span> <span class="hljs-string">&quot;8158874729&quot;</span> <span class="hljs-string">&quot;netease&quot;</span> <span class="hljs-string">&quot;playlist&quot;</span> <span class="hljs-template-tag">%&#125;</span><span class="language-xml"></span><br><span class="language-xml"></span><br><span class="language-xml"><span class="hljs-comment">&lt;!-- 进阶示例 --&gt;</span></span><br><span class="language-xml"></span><span class="hljs-template-tag">&#123;%</span> <span class="hljs-name">meting</span> <span class="hljs-string">&quot;8158874729&quot;</span> <span class="hljs-string">&quot;netease&quot;</span> <span class="hljs-string">&quot;playlist&quot;</span> <span class="hljs-string">&quot;autoplay&quot;</span> <span class="hljs-string">&quot;mutex:false&quot;</span> <span class="hljs-string">&quot;listmaxheight:340px&quot;</span> <span class="hljs-string">&quot;preload:auto&quot;</span> <span class="hljs-string">&quot;theme:#3F51B5&quot;</span><span class="hljs-string">&quot;order:random&quot;</span><span class="hljs-template-tag">%&#125;</span><br></code></pre></td></tr></table></figure><ol start="2"><li>下面是有关<span class="label label-info">meting</span>的部分选项配置，具体可参看<a href="https://github.com/MoePlayer/hexo-tag-aplayer/blob/master/docs/README-zh_cn.md">官方文档</a>。</li></ol><table><thead><tr><th style="text-align:center">选项</th><th style="text-align:center">默认值</th><th style="text-align:center">描述</th></tr></thead><tbody><tr><td style="text-align:center">id</td><td style="text-align:center"><strong>必须值</strong></td><td style="text-align:center">歌曲 id / 播放列表 id / 相册 id / 搜索关键字</td></tr><tr><td style="text-align:center">server</td><td style="text-align:center"><strong>必须值</strong></td><td style="text-align:center">音乐平台: <code>netease</code>, <code>tencent</code>, <code>kugou</code>, <code>xiami</code>, <code>baidu</code></td></tr><tr><td style="text-align:center">type</td><td style="text-align:center"><strong>必须值</strong></td><td style="text-align:center"><code>song</code>,<code>playlist</code>, <code>album</code>, <code>search</code>, <code>artist</code></td></tr></tbody></table><ol start="3"><li><p>添加音乐页面到导航菜单内。</p><figure class="highlight css"><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 css"><span class="hljs-selector-tag">menu</span>:<br>  - &#123; key: <span class="hljs-string">&quot;音乐&quot;</span>, link: <span class="hljs-string">&quot;/playlist/&quot;</span>, icon: <span class="hljs-string">&quot;iconfont icon-music&quot;</span> &#125;<br></code></pre></td></tr></table></figure></li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;p class=&quot;note note-success&quot;&gt;
    本文大部分配置参考林慕凡的博文，感谢作者的详细讲解。&lt;br&gt;
    作者：林慕凡&lt;br&gt;
    原文地址：&lt;a href=&quot;https://blog.csdn.net/weixin_43471926/arti</summary>
      
    
    
    
    <category term="博客配置" scheme="https://blog.jishuqin.cn/categories/%E5%8D%9A%E5%AE%A2%E9%85%8D%E7%BD%AE/"/>
    
    
    <category term="Fluid" scheme="https://blog.jishuqin.cn/tags/Fluid/"/>
    
  </entry>
  
  <entry>
    <title>Fluid 页脚增加网站运行时长</title>
    <link href="https://blog.jishuqin.cn/posts/aabbccdd/"/>
    <id>https://blog.jishuqin.cn/posts/aabbccdd/</id>
    <published>2023-03-04T13:00:00.000Z</published>
    <updated>2025-09-03T08:59:30.029Z</updated>
    
    <content type="html"><![CDATA[<p class="note note-success">本文转载自 Fluid 官方博客文章，版权归原作者所有。<br>本文作者：张凯强<br>原文地址：<a href="https://hexo.fluid-dev.com/posts/fluid-footer-custom/" target="_blank">https://hexo.fluid-dev.com/posts/fluid-footer-custom/</a></p><p>Fluid 1.8.4 版本支持自定义页脚内容了，群友常改的网站运行时长，这次无需再修改源代码。</p><p>只需要在主题配置中的 <code>footer: content</code> 添加：</p><figure class="highlight xml"><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 xml">footer:<br>  content: &#x27;<br>    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;https://hexo.io&quot;</span> <span class="hljs-attr">target</span>=<span class="hljs-string">&quot;_blank&quot;</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">&quot;nofollow noopener&quot;</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Hexo<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;iconfont icon-love&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;https://github.com/fluid-dev/hexo-theme-fluid&quot;</span> <span class="hljs-attr">target</span>=<span class="hljs-string">&quot;_blank&quot;</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">&quot;nofollow noopener&quot;</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Fluid<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;font-size: 0.85rem&quot;</span>&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;timeDate&quot;</span>&gt;</span>载入天数...<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;times&quot;</span>&gt;</span>载入时分秒...<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;/js/duration.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br>  &#x27;<br></code></pre></td></tr></table></figure><p><code>content</code> 前三行是 Fluid 原有的页脚内容，建议不要删除，可稍作修改，保留 Fluid 的超链接，用于向更多人推广主题。</p><p><code>duration.js</code> 包含的才是功能代码，我们在博客目录下创建 <code>source/js/duration.js</code>，内容如下：</p><figure class="highlight javascript"><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 javascript">!(<span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) &#123;<br>  <span class="hljs-comment">/** 计时起始时间，自行修改 **/</span><br>  <span class="hljs-keyword">var</span> start = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>(<span class="hljs-string">&quot;2020/01/01 00:00:00&quot;</span>);<br><br>  <span class="hljs-keyword">function</span> <span class="hljs-title function_">update</span>(<span class="hljs-params"></span>) &#123;<br>    <span class="hljs-keyword">var</span> now = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>();<br>    now.<span class="hljs-title function_">setTime</span>(now.<span class="hljs-title function_">getTime</span>()+<span class="hljs-number">250</span>);<br>    days = (now - start) / <span class="hljs-number">1000</span> / <span class="hljs-number">60</span> / <span class="hljs-number">60</span> / <span class="hljs-number">24</span>;<br>    dnum = <span class="hljs-title class_">Math</span>.<span class="hljs-title function_">floor</span>(days);<br>    hours = (now - start) / <span class="hljs-number">1000</span> / <span class="hljs-number">60</span> / <span class="hljs-number">60</span> - (<span class="hljs-number">24</span> * dnum);<br>    hnum = <span class="hljs-title class_">Math</span>.<span class="hljs-title function_">floor</span>(hours);<br>    <span class="hljs-keyword">if</span>(<span class="hljs-title class_">String</span>(hnum).<span class="hljs-property">length</span> === <span class="hljs-number">1</span> )&#123;<br>      hnum = <span class="hljs-string">&quot;0&quot;</span> + hnum;<br>    &#125;<br>    minutes = (now - start) / <span class="hljs-number">1000</span> /<span class="hljs-number">60</span> - (<span class="hljs-number">24</span> * <span class="hljs-number">60</span> * dnum) - (<span class="hljs-number">60</span> * hnum);<br>    mnum = <span class="hljs-title class_">Math</span>.<span class="hljs-title function_">floor</span>(minutes);<br>    <span class="hljs-keyword">if</span>(<span class="hljs-title class_">String</span>(mnum).<span class="hljs-property">length</span> === <span class="hljs-number">1</span> )&#123;<br>      mnum = <span class="hljs-string">&quot;0&quot;</span> + mnum;<br>    &#125;<br>    seconds = (now - start) / <span class="hljs-number">1000</span> - (<span class="hljs-number">24</span> * <span class="hljs-number">60</span> * <span class="hljs-number">60</span> * dnum) - (<span class="hljs-number">60</span> * <span class="hljs-number">60</span> * hnum) - (<span class="hljs-number">60</span> * mnum);<br>    snum = <span class="hljs-title class_">Math</span>.<span class="hljs-title function_">round</span>(seconds);<br>    <span class="hljs-keyword">if</span>(<span class="hljs-title class_">String</span>(snum).<span class="hljs-property">length</span> === <span class="hljs-number">1</span> )&#123;<br>      snum = <span class="hljs-string">&quot;0&quot;</span> + snum;<br>    &#125;<br>    <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&quot;timeDate&quot;</span>).<span class="hljs-property">innerHTML</span> = <span class="hljs-string">&quot;本站安全运行&amp;nbsp&quot;</span>+dnum+<span class="hljs-string">&quot;&amp;nbsp天&quot;</span>;<br>    <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&quot;times&quot;</span>).<span class="hljs-property">innerHTML</span> = hnum + <span class="hljs-string">&quot;&amp;nbsp小时&amp;nbsp&quot;</span> + mnum + <span class="hljs-string">&quot;&amp;nbsp分&amp;nbsp&quot;</span> + snum + <span class="hljs-string">&quot;&amp;nbsp秒&quot;</span>;<br>  &#125;<br><br>  <span class="hljs-title function_">update</span>();<br>  <span class="hljs-built_in">setInterval</span>(update, <span class="hljs-number">1000</span>);<br>&#125;)();<br></code></pre></td></tr></table></figure><p>不要忘记把上面注释的时间改为自己的时间，至此这项功能就引入到 <code>&lt;footer&gt;</code> 里了。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p class=&quot;note note-success&quot;&gt;
本文转载自 Fluid 官方博客文章，版权归原作者所有。&lt;br&gt;
本文作者：张凯强&lt;br&gt;
原文地址：&lt;a href=&quot;https://hexo.fluid-dev.com/posts/fluid-footer-cust</summary>
      
    
    
    
    <category term="博客配置" scheme="https://blog.jishuqin.cn/categories/%E5%8D%9A%E5%AE%A2%E9%85%8D%E7%BD%AE/"/>
    
    
    <category term="Fluid" scheme="https://blog.jishuqin.cn/tags/Fluid/"/>
    
  </entry>
  
  <entry>
    <title>Cloudreve映射WebDav</title>
    <link href="https://blog.jishuqin.cn/posts/cbe4867c/"/>
    <id>https://blog.jishuqin.cn/posts/cbe4867c/</id>
    <published>2023-03-04T01:57:00.000Z</published>
    <updated>2024-03-23T13:03:18.583Z</updated>
    
    <content type="html"><![CDATA[<h1>一、前言</h1><p>WebDAV 是一种基于 HTTP 协议的文件传输协议，如今有许多第三方文件管理器、视频播放器等产品都支持通过 WebDAV 协议访问 Cloudreve 中的文件，你可以借此实现跨平台的文件共享与同步。</p><h1>二、添加权限</h1><p>登录网盘进入管理面板，点击左侧用户组，点击编辑按钮为对应用户组开启WebDAV协议连接网盘功能。</p><p><img src="https://cdn.gumengyo.top/Snipaste_2023-03-04_10-11-06.png" srcset="/img/loading.gif" lazyload alt=""></p><p>勾选WebDAV选项<br><img src="https://cdn.gumengyo.top/202303041014548.png" srcset="/img/loading.gif" lazyload alt=""></p><p>返回主页，点击左侧连接，创建一个WebDAV账号。</p><p><img src="https://cdn.gumengyo.top//202303041028287.png" srcset="/img/loading.gif" lazyload alt=""></p><h1>三、windows端</h1><h4 id="1-打开windows端的注册表">1. 打开windows端的注册表</h4><p><img src="https://cdn.gumengyo.top//202303041032382.png" srcset="/img/loading.gif" lazyload alt=""></p><h4 id="2-访问路径（复制连接粘贴到搜索框按回车即可）：">2.访问路径（复制连接粘贴到搜索框按回车即可）：</h4><figure class="highlight moonscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs moonscript">计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WebClient\Parameters<br></code></pre></td></tr></table></figure><h4 id="3-把BasicAuthLevel-值改成2，即同时支持http和https，默认只支持https传输协议。">3.把BasicAuthLevel 值改成2，即同时支持http和https，默认只支持https传输协议。</h4><p><img src="https://cdn.gumengyo.top//202303041037097.png" srcset="/img/loading.gif" lazyload alt=""></p><h4 id="4-删除同目录下的-FileSizeLimitInBytes，此操作是为了开放下载大小。">4.删除同目录下的 FileSizeLimitInBytes，此操作是为了开放下载大小。</h4><p><img src="https://cdn.gumengyo.top//202303041039964.png" srcset="/img/loading.gif" lazyload alt=""></p><h4 id="5-在当前目录新建-FileSizeLimitInBytes">5.在当前目录新建 FileSizeLimitInBytes</h4><p>右键修改 十六进制 <span class="label label-primary">ffffffffffffffff</span></p><div class="group-image-container"><div class="group-image-row"><div class="group-image-wrap"><img src="https://cdn.gumengyo.top//202303041044710.png" srcset="/img/loading.gif" lazyload alt=""></div><div class="group-image-wrap"><img src="https://cdn.gumengyo.top/2023-03-03_22-16-16.png" srcset="/img/loading.gif" lazyload alt=""></div></div></div><h4 id="6-打开服务-找到WebClient">6.打开服务 找到WebClient</h4><p>设置为自动启动，并且点击停止 点击启动</p><div class="group-image-container"><div class="group-image-row"><div class="group-image-wrap"><img src="https://cdn.gumengyo.top//202303041058766.png" srcset="/img/loading.gif" lazyload alt=""></div><div class="group-image-wrap"><img src="https://cdn.gumengyo.top//202303041058742.png" srcset="/img/loading.gif" lazyload alt=""></div></div></div><h1>四、映射网络驱动器</h1><p>打开我的电脑，点击映射网络驱动器。<br><img src="https://cdn.gumengyo.top//202303041101387.png" srcset="/img/loading.gif" lazyload alt=""><br>填入创建WebDAV账号页面的WebDAV地址。<br><img src="https://cdn.gumengyo.top//202303041103489.png" srcset="/img/loading.gif" lazyload alt=""><br>填入账号密码连接到网盘。<br><img src="https://cdn.gumengyo.top//2023-03-04_11-05-51.png" srcset="/img/loading.gif" lazyload alt=""><br>查看效果<br><img src="https://cdn.gumengyo.top//202303041106329.png" srcset="/img/loading.gif" lazyload alt=""></p><p>到这Cloudreve映射WebDav就配置完成了，希望对您有所帮助~</p>]]></content>
    
    
    <summary type="html">这篇文章介绍了如何使用WebDAV协议访问Cloudreve中的文件，实现跨平台的文件共享与同步。首先，需要登录网盘管理面板，并为用户组开启WebDAV协议连接功能。然后，在Windows端需要打开注册表，找到WebClient的路径，并将BasicAuthLevel的值改为2，以同时支持http和https传输协议。还需要删除FileSizeLimitInBytes，以开放下载大小。</summary>
    
    
    
    <category term="服务配置" scheme="https://blog.jishuqin.cn/categories/%E6%9C%8D%E5%8A%A1%E9%85%8D%E7%BD%AE/"/>
    
    
    <category term="Cloudreve" scheme="https://blog.jishuqin.cn/tags/Cloudreve/"/>
    
  </entry>
  
  <entry>
    <title>Cloudreve部署配置</title>
    <link href="https://blog.jishuqin.cn/posts/d8e2f4a6/"/>
    <id>https://blog.jishuqin.cn/posts/d8e2f4a6/</id>
    <published>2023-03-02T11:21:00.000Z</published>
    <updated>2025-09-03T08:59:30.028Z</updated>
    
    <content type="html"><![CDATA[<h1>一、前言</h1><p>Cloudreve 可以让您快速搭建起公私兼备的网盘系统。Cloudreve 在底层支持不同的云存储平台，用户在实际使用时无须关心物理存储方式。你可以使用 Cloudreve 搭建个人用网盘、文件分享系统，亦或是针对大小团体的公有云系统。拥有一个自己的网盘，保存文件下载文件将非常方便。</p><p><img src="https://cdn.gumengyo.top/2023-03-03_21-10-31.png" srcset="/img/loading.gif" lazyload alt=""></p><h1>二、安装Cloudreve</h1><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></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 新建一个文件夹存放程序</span><br><span class="hljs-built_in">mkdir</span> /www/wwwroot/cloudreve <br><br><span class="hljs-comment">#进入该文件夹</span><br><span class="hljs-built_in">cd</span> /www/wwwroot/cloudreve<br><br><span class="hljs-comment"># 下载对应资源包（选择对应系统版本的资源包）</span><br>wget https://github.com/cloudreve/Cloudreve/releases/download/3.7.1/cloudreve_3.7.1_linux_amd64.tar.gz<br><br><span class="hljs-comment"># 解压获取到的主程序</span><br>tar -zxvf cloudreve_3.7.1_linux_amd64.tar.gz<br><br><span class="hljs-comment"># 赋予执行权限</span><br><span class="hljs-built_in">chmod</span> +x ./cloudreve<br><br><span class="hljs-comment"># 启动 Cloudreve</span><br>./cloudreve<br></code></pre></td></tr></table></figure><p class="note note-warning">注意Cloudreve首次启动时，会创建初始管理员账号和密码，只有首次启动时才会出现，所以这里需要保存好账号密码，后边登录系统时使用。</p><h1>三、进程守护</h1><p>可以使用Systemd或Supervisor守护进程，下边介绍使用Systemd，可以参考<a href="https://docs.cloudreve.org/getting-started/install#jin-cheng-shou-hu">官方文档</a>。</p><figure class="highlight awk"><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 awk"><span class="hljs-comment"># 编辑配置文件</span><br>vim <span class="hljs-regexp">/usr/</span>lib<span class="hljs-regexp">/systemd/</span>system/cloudreve.service<br></code></pre></td></tr></table></figure><p>将下文 PATH_TO_CLOUDREVE 更换为程序所在目录：</p><figure class="highlight ini"><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 ini"><span class="hljs-section">[Unit]</span><br><span class="hljs-attr">Description</span>=Cloudreve<br><span class="hljs-attr">Documentation</span>=https://docs.cloudreve.org<br><span class="hljs-attr">After</span>=network.target<br><span class="hljs-attr">After</span>=mysqld.service<br><span class="hljs-attr">Wants</span>=network.target<br><br><span class="hljs-section">[Service]</span><br><span class="hljs-attr">WorkingDirectory</span>=/PATH_TO_CLOUDREVE<br><span class="hljs-attr">ExecStart</span>=/PATH_TO_CLOUDREVE/cloudreve<br><span class="hljs-attr">Restart</span>=<span class="hljs-literal">on</span>-abnormal<br><span class="hljs-attr">RestartSec</span>=<span class="hljs-number">5</span>s<br><span class="hljs-attr">KillMode</span>=mixed<br><br><span class="hljs-attr">StandardOutput</span>=null<br><span class="hljs-attr">StandardError</span>=syslog<br><br><span class="hljs-section">[Install]</span><br><span class="hljs-attr">WantedBy</span>=multi-user.target<br></code></pre></td></tr></table></figure><p>更新配置</p><figure class="highlight nsis"><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 nsis"><span class="hljs-comment"># 更新配置</span><br><span class="hljs-params">system</span>ctl daemon-reload<br><br><span class="hljs-comment"># 启动服务</span><br><span class="hljs-params">system</span>ctl start cloudreve<br><br><span class="hljs-comment"># 设置开机启动</span><br><span class="hljs-params">system</span>ctl enable cloudreve<br></code></pre></td></tr></table></figure><p>管理命令：</p><figure class="highlight nsis"><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 nsis"><span class="hljs-comment"># 启动服务</span><br><span class="hljs-params">system</span>ctl start cloudreve<br><br><span class="hljs-comment"># 停止服务</span><br><span class="hljs-params">system</span>ctl stop cloudreve<br><br><span class="hljs-comment"># 重启服务</span><br><span class="hljs-params">system</span>ctl restart cloudreve<br><br><span class="hljs-comment"># 查看状态</span><br><span class="hljs-params">system</span>ctl status cloudreve<br></code></pre></td></tr></table></figure><h1>四、使用Nginx Proxy Manager反向代理</h1><p>配置反向代理需要有一个自己的域名，并解析到启动Cloudreve的服务器。</p><div class="group-image-container"><div class="group-image-row"><div class="group-image-wrap"><img src="https://cdn.gumengyo.top/2023-03-03_22-11-03.png" srcset="/img/loading.gif" lazyload alt=""></div><div class="group-image-wrap"><img src="https://cdn.gumengyo.top/2023-03-03_22-16-16.png" srcset="/img/loading.gif" lazyload alt=""></div></div></div><h1>五、系统配置</h1><ol><li>访问上边配置反向代理的域名进入系统登录页面，使用首次启动系统生成的账户名和密码登录系统。</li></ol><p><img src="https://cdn.gumengyo.top/cloudreve4.png" srcset="/img/loading.gif" lazyload alt=""></p><ol start="2"><li>点击用户头像，进入管理面板。<br><img src="https://cdn.gumengyo.top/cloudreve5.png" srcset="/img/loading.gif" lazyload alt=""></li><li>点击用户界面，设置你自己的账号密码。<br><img src="https://cdn.gumengyo.top/cloudreve6.png" srcset="/img/loading.gif" lazyload alt=""></li></ol><p class="note note-info">默认存储策略是保存到系统本地，想配置七牛云存储、腾讯云COS等云存储，点击添加存储策略，选择对应的存储服务会有详细的配置说明。</p><p><img src="https://cdn.gumengyo.top/cloudreve7.png" srcset="/img/loading.gif" lazyload alt=""></p><p>到这cloudreve基本搭建完成啦，试试上传文件到网盘吧~</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1&gt;一、前言&lt;/h1&gt;
&lt;p&gt;Cloudreve 可以让您快速搭建起公私兼备的网盘系统。Cloudreve 在底层支持不同的云存储平台，用户在实际使用时无须关心物理存储方式。你可以使用 Cloudreve 搭建个人用网盘、文件分享系统，亦或是针对大小团体的公有云系统。拥有一个</summary>
      
    
    
    
    <category term="服务配置" scheme="https://blog.jishuqin.cn/categories/%E6%9C%8D%E5%8A%A1%E9%85%8D%E7%BD%AE/"/>
    
    
    <category term="Cloudreve" scheme="https://blog.jishuqin.cn/tags/Cloudreve/"/>
    
  </entry>
  
</feed>
