{
"cells": [
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import PIL.Image\n",
"import glob\n",
"import os\n",
"\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31mnotebook controller is DISPOSED. \n",
"View Jupyter log for further details."
]
}
],
"source": [
"IMAGE_SIZE = (400, 150, 3)\n",
"RESIZED_SIZE = (100, 50, 3)\n",
"RESIZED_SIZE_PIL = (RESIZED_SIZE[1], RESIZED_SIZE[0], RESIZED_SIZE[2])\n",
"DATASET_PATH = \"./dataset_rot/\"\n",
"DATASET_PATH = os.path.abspath(DATASET_PATH)\n",
"CLASSES = next(os.walk(DATASET_PATH))[1]\n",
"\n",
"print(DATASET_PATH)\n",
"print(CLASSES)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31mnotebook controller is DISPOSED. \n",
"View Jupyter log for further details."
]
}
],
"source": [
"def load_data():\n",
" # Récupération des fichiers\n",
" files = glob.glob(f\"{DATASET_PATH}/**/*.jpg\", recursive = True)\n",
"\n",
" # Initialise les structures de données\n",
" x = np.zeros((len(files), *RESIZED_SIZE_PIL))\n",
" y = np.zeros((len(files), 1))\n",
"\n",
" # print(f\"x.shape = {x.shape}\")\n",
"\n",
" for i, path in enumerate(files):\n",
" # Lecture de l'image\n",
" img = PIL.Image.open(path)\n",
"\n",
" # print(f\"img.size = {img.size}\")\n",
"\n",
" # Redimensionnement de l'image\n",
" img = img.resize(RESIZED_SIZE[:-1], PIL.Image.ANTIALIAS)\n",
"\n",
" # print(f\"img.size = {img.size}\")\n",
"\n",
" test = np.asarray(img)\n",
"\n",
" # print(f\"test.shape = {test.shape}\")\n",
"\n",
" # Remplissage de la variable x\n",
" x[i] = test\n",
"\n",
" # On récupère l'index dans le path\n",
" class_label = path.split(\"/\")[-2]\n",
"\n",
" # On récupère le numéro de la classe à partir du string\n",
" class_label = CLASSES.index(class_label)\n",
" \n",
" # Remplissage de la variable y\n",
" y[i] = class_label\n",
"\n",
" return x, y"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31mnotebook controller is DISPOSED. \n",
"View Jupyter log for further details."
]
}
],
"source": [
"x, y = load_data()\n",
"x = x / 255"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31mnotebook controller is DISPOSED. \n",
"View Jupyter log for further details."
]
}
],
"source": [
"# Randomisation des indices et affichage de 9 images alétoires de la base d'apprentissage\n",
"indices = np.arange(x.shape[0])\n",
"np.random.shuffle(indices)\n",
"\n",
"plt.figure(figsize=(12, 6))\n",
"\n",
"for i in range(0, 3*3):\n",
" plt.subplot(3, 3, i+1)\n",
" plt.title(CLASSES[int(y[indices[i]])])\n",
" plt.imshow(x[indices[i]])\n",
"\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31mnotebook controller is DISPOSED. \n",
"View Jupyter log for further details."
]
}
],
"source": [
"import tensorflow\n",
"from tensorflow.keras.models import Sequential\n",
"from tensorflow.keras.layers import InputLayer, Dense, Flatten, Conv2D, MaxPooling2D\n",
"from tensorflow.keras import optimizers"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31mnotebook controller is DISPOSED. \n",
"View Jupyter log for further details."
]
}
],
"source": [
"model = Sequential()\n",
"\n",
"model.add(InputLayer(input_shape=RESIZED_SIZE_PIL))\n",
"\n",
"model.add(Conv2D(32, 3, activation=\"relu\"))\n",
"model.add(MaxPooling2D(pool_size=(2, 2)))\n",
"\n",
"model.add(Conv2D(64, 3, activation=\"relu\"))\n",
"model.add(MaxPooling2D(pool_size=(2, 2)))\n",
"\n",
"model.add(Conv2D(92, 3, activation=\"relu\"))\n",
"model.add(MaxPooling2D(pool_size=(2, 2)))\n",
"\n",
"model.add(Flatten())\n",
"\n",
"model.add(Dense(250, activation=\"relu\"))\n",
"\n",
"model.add(Dense(4, activation=\"softmax\"))\n",
"\n",
"model.summary()\n",
"\n",
"adam = optimizers.Adam(learning_rate=7e-6)\n",
"model.compile(optimizer=adam, loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n",
"history = model.fit(x, y, validation_split=0.15, epochs=10, batch_size=25)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"ename": "",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31mnotebook controller is DISPOSED. \n",
"View Jupyter log for further details."
]
}
],
"source": [
"def plot_training_analysis():\n",
" acc = history.history['accuracy']\n",
" val_acc = history.history['val_accuracy']\n",
" loss = history.history['loss']\n",
" val_loss = history.history['val_loss']\n",
"\n",
" epochs = range(len(acc))\n",
"\n",
" plt.plot(epochs, acc, 'b', linestyle=\"--\",label='Training acc')\n",
" plt.plot(epochs, val_acc, 'g', label='Validation acc')\n",
" plt.title('Training and validation accuracy')\n",
" plt.legend()\n",
"\n",
" plt.figure()\n",
"\n",
" plt.plot(epochs, loss, 'b', linestyle=\"--\",label='Training loss')\n",
" plt.plot(epochs, val_loss,'g', label='Validation loss')\n",
" plt.title('Training and validation loss')\n",
" plt.legend()\n",
"\n",
" plt.show()\n",
"\n",
"plot_training_analysis()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"/tmp/deepl/data\n",
"[]\n"
]
}
],
"source": [
"IMAGE_SIZE = (400, 150, 3)\n",
"RESIZED_SIZE = (100, 50, 3)\n",
"RESIZED_SIZE_PIL = (RESIZED_SIZE[1], RESIZED_SIZE[0], RESIZED_SIZE[2])\n",
"DATASET_PATH = \"./data/\"\n",
"DATASET_PATH = os.path.abspath(DATASET_PATH)\n",
"CLASSES = next(os.walk(DATASET_PATH))[1]\n",
"\n",
"print(DATASET_PATH)\n",
"print(CLASSES)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"import tensorflow\n",
"from tensorflow.keras.models import Sequential\n",
"from tensorflow.keras.layers import InputLayer, Dense, Flatten, Conv2D, MaxPooling2D\n",
"from tensorflow.keras import optimizers"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"dataset_length = 10000\n",
"batch size = 32\n",
"number of batchs = 312\n",
"\n",
"train_size = 250\n",
"validation_size = 9750\n"
]
}
],
"source": [
"import tensorflow as tf\n",
"import tensorflow_addons as tfa\n",
"import sqlite3\n",
"\n",
"AUTOTUNE = tf.data.experimental.AUTOTUNE\n",
"BATCH_SIZE = 32\n",
"SHUFFLE_SIZE = 32\n",
"LIMIT = 10000\n",
"\n",
"def customGenerator():\n",
" data = sqlite3.connect(f\"{DATASET_PATH}/index.db\").execute(f\"SELECT uuid, model from data LIMIT {LIMIT}\").fetchall()\n",
"\n",
" for uuid, model in data:\n",
" img = tf.io.read_file(f\"{DATASET_PATH}/{uuid}.jpg\")\n",
" img = tf.image.decode_jpeg(img, channels=IMAGE_SIZE[2])\n",
" img = tf.image.convert_image_dtype(img, tf.float32)\n",
" img = tf.image.resize(img, RESIZED_SIZE[:-1])\n",
" \n",
" label = tf.convert_to_tensor(model, dtype=tf.uint8)\n",
" \n",
" yield img, label\n",
"\n",
"def cutout(image, label):\n",
" img = tfa.image.random_cutout(image, (6, 6), constant_values=1)\n",
" return (img, label)\n",
"\n",
"def rotate(image,label) :\n",
" img = tfa.image.rotate(image, tf.constant(np.pi)) \n",
" return (img, label)\n",
"\n",
"def set_shapes(image, label):\n",
" image.set_shape(RESIZED_SIZE)\n",
" label.set_shape([])\n",
" return image, label\n",
"\n",
"dataset = tf.data.Dataset.from_generator(\n",
" generator=customGenerator, \n",
" output_types=(tf.float32, tf.uint8)\n",
")\n",
"\n",
"(dataset_length,) = sqlite3.connect(f\"{DATASET_PATH}/index.db\").execute(\"SELECT count(uuid) from data\").fetchone()\n",
"dataset_length = min(dataset_length, LIMIT)\n",
"\n",
"print(f\"dataset_length = {dataset_length}\")\n",
"print(f\"batch size = {BATCH_SIZE}\")\n",
"print(f\"number of batchs = {dataset_length // BATCH_SIZE}\")\n",
"\n",
"print()\n",
"\n",
"train_size = int(0.8 * dataset_length / BATCH_SIZE)\n",
"print(f\"train_size = {train_size}\")\n",
"print(f\"validation_size = {dataset_length - train_size}\")\n",
"\n",
"dataset = (\n",
" dataset.shuffle(SHUFFLE_SIZE)\n",
" .map(set_shapes)\n",
" .batch(BATCH_SIZE)\n",
" # .map(cutout)\n",
" .prefetch(AUTOTUNE)\n",
")\n",
"\n",
"dataset_train = dataset.take(train_size)\n",
"dataset_validate = dataset.skip(train_size)\n",
"\n",
"# print()\n",
"# print(RESIZED_SIZE)\n",
"# for boop in dataset_train.take(2):\n",
"# print(boop)\n",
"\n",
"# for image_batch, label_batch in dataset.take(1):\n",
"# print(label_batch.shape, image_batch.shape)\n",
"# pass\n",
"# for image_batch, label_batch in dataset_train.take(1):\n",
"# print(label_batch.shape, image_batch.shape)\n",
"# pass\n",
"# for image_batch, label_batch in dataset_validate.take(1):\n",
"# print(label_batch.shape, image_batch.shape)\n",
"# pass"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential_7\"\n",
"_________________________________________________________________\n",
" Layer (type) Output Shape Param # \n",
"=================================================================\n",
" conv2d_21 (Conv2D) (None, 98, 48, 32) 896 \n",
" \n",
" max_pooling2d_21 (MaxPoolin (None, 49, 24, 32) 0 \n",
" g2D) \n",
" \n",
" conv2d_22 (Conv2D) (None, 47, 22, 64) 18496 \n",
" \n",
" max_pooling2d_22 (MaxPoolin (None, 23, 11, 64) 0 \n",
" g2D) \n",
" \n",
" conv2d_23 (Conv2D) (None, 21, 9, 92) 53084 \n",
" \n",
" max_pooling2d_23 (MaxPoolin (None, 10, 4, 92) 0 \n",
" g2D) \n",
" \n",
" flatten_7 (Flatten) (None, 3680) 0 \n",
" \n",
" dense_14 (Dense) (None, 250) 920250 \n",
" \n",
" dense_15 (Dense) (None, 4) 1004 \n",
" \n",
"=================================================================\n",
"Total params: 993,730\n",
"Trainable params: 993,730\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n",
"Epoch 1/25\n",
"250/250 [==============================] - 53s 211ms/step - loss: 0.9718 - accuracy: 0.6635 - val_loss: 2.2070 - val_accuracy: 0.1400\n",
"Epoch 2/25\n",
"250/250 [==============================] - 52s 209ms/step - loss: 0.7459 - accuracy: 0.6416 - val_loss: 2.2988 - val_accuracy: 0.1400\n",
"Epoch 3/25\n",
"250/250 [==============================] - 53s 210ms/step - loss: 0.6746 - accuracy: 0.6664 - val_loss: 2.4333 - val_accuracy: 0.1400\n",
"Epoch 4/25\n",
"250/250 [==============================] - 53s 211ms/step - loss: 0.6437 - accuracy: 0.6920 - val_loss: 2.3739 - val_accuracy: 0.1400\n",
"Epoch 5/25\n",
"250/250 [==============================] - 53s 211ms/step - loss: 0.5982 - accuracy: 0.7157 - val_loss: 2.1336 - val_accuracy: 0.1400\n",
"Epoch 6/25\n",
"250/250 [==============================] - 53s 210ms/step - loss: 0.5497 - accuracy: 0.7380 - val_loss: 2.0098 - val_accuracy: 0.1400\n",
"Epoch 7/25\n",
"250/250 [==============================] - 53s 210ms/step - loss: 0.5108 - accuracy: 0.7561 - val_loss: 1.9775 - val_accuracy: 0.1400\n",
"Epoch 8/25\n",
"250/250 [==============================] - 53s 211ms/step - loss: 0.4761 - accuracy: 0.7725 - val_loss: 1.9294 - val_accuracy: 0.1400\n",
"Epoch 9/25\n",
"250/250 [==============================] - 53s 210ms/step - loss: 0.4304 - accuracy: 0.7940 - val_loss: 2.0166 - val_accuracy: 0.1400\n",
"Epoch 10/25\n",
"250/250 [==============================] - 53s 214ms/step - loss: 0.4140 - accuracy: 0.8075 - val_loss: 1.7652 - val_accuracy: 0.1400\n",
"Epoch 11/25\n",
"250/250 [==============================] - 53s 211ms/step - loss: 0.3672 - accuracy: 0.8279 - val_loss: 1.6594 - val_accuracy: 0.1400\n",
"Epoch 12/25\n",
"250/250 [==============================] - 53s 211ms/step - loss: 0.3285 - accuracy: 0.8512 - val_loss: 1.5178 - val_accuracy: 0.1400\n",
"Epoch 13/25\n",
"250/250 [==============================] - 52s 210ms/step - loss: 0.2867 - accuracy: 0.8702 - val_loss: 1.4753 - val_accuracy: 0.1400\n",
"Epoch 14/25\n",
"250/250 [==============================] - 52s 209ms/step - loss: 0.2500 - accuracy: 0.8905 - val_loss: 1.3835 - val_accuracy: 0.1400\n",
"Epoch 15/25\n",
"250/250 [==============================] - 53s 210ms/step - loss: 0.2186 - accuracy: 0.9100 - val_loss: 1.1579 - val_accuracy: 0.1405\n",
"Epoch 16/25\n",
"250/250 [==============================] - 53s 210ms/step - loss: 0.1810 - accuracy: 0.9309 - val_loss: 1.0902 - val_accuracy: 0.1510\n",
"Epoch 17/25\n",
"250/250 [==============================] - 52s 210ms/step - loss: 0.1555 - accuracy: 0.9451 - val_loss: 0.9250 - val_accuracy: 0.2240\n",
"Epoch 18/25\n",
"250/250 [==============================] - 53s 210ms/step - loss: 0.1280 - accuracy: 0.9626 - val_loss: 0.7926 - val_accuracy: 0.3720\n",
"Epoch 19/25\n",
"250/250 [==============================] - 53s 212ms/step - loss: 0.1065 - accuracy: 0.9728 - val_loss: 0.6717 - val_accuracy: 0.5145\n",
"Epoch 20/25\n",
"250/250 [==============================] - 53s 211ms/step - loss: 0.0878 - accuracy: 0.9816 - val_loss: 0.5564 - val_accuracy: 0.6530\n",
"Epoch 21/25\n",
"250/250 [==============================] - 53s 212ms/step - loss: 0.0714 - accuracy: 0.9901 - val_loss: 0.4285 - val_accuracy: 0.8095\n",
"Epoch 22/25\n",
"250/250 [==============================] - 53s 212ms/step - loss: 0.0567 - accuracy: 0.9942 - val_loss: 0.3829 - val_accuracy: 0.8545\n",
"Epoch 23/25\n",
"250/250 [==============================] - 53s 213ms/step - loss: 0.0473 - accuracy: 0.9975 - val_loss: 0.2913 - val_accuracy: 0.9285\n",
"Epoch 24/25\n",
"250/250 [==============================] - 53s 210ms/step - loss: 0.0383 - accuracy: 0.9990 - val_loss: 0.2352 - val_accuracy: 0.9615\n",
"Epoch 25/25\n",
"250/250 [==============================] - 53s 211ms/step - loss: 0.0311 - accuracy: 0.9996 - val_loss: 0.1907 - val_accuracy: 0.9815\n"
]
}
],
"source": [
"model = Sequential([\n",
" InputLayer(input_shape=RESIZED_SIZE),\n",
" \n",
" Conv2D(32, 3, activation=\"relu\"),\n",
" MaxPooling2D(pool_size=(2, 2)),\n",
" \n",
" Conv2D(64, 3, activation=\"relu\"),\n",
" MaxPooling2D(pool_size=(2, 2)),\n",
"\n",
" Conv2D(92, 3, activation=\"relu\"),\n",
" MaxPooling2D(pool_size=(2, 2)),\n",
"\n",
" Flatten(),\n",
"\n",
" Dense(250, activation=\"relu\"),\n",
" Dense(4, activation=\"softmax\")\n",
"])\n",
"\n",
"model.summary()\n",
"\n",
"adam = optimizers.Adam(learning_rate=7e-6)\n",
"model.compile(optimizer=adam, loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n",
"history = model.fit(dataset_train, validation_data=dataset_validate, epochs=25, batch_size=BATCH_SIZE)"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAEICAYAAACktLTqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAzGklEQVR4nO3dd3hU1db48e9KIIQSem9SBAQMISGAl6JwUSkiiCAQEAiIoNjbffV6VS6Wnyh6fXmxXHqXIkVEEEVBsdNCB0EIEjqhE0La/v2xJxBCKkxyMjPr8zzz5Mw5Z86sMydZ2bP3PnuLMQallFLexc/pAJRSSrmfJnellPJCmtyVUsoLaXJXSikvpMldKaW8kCZ3pZTyQprcvZiILBeRQe7e10kiEi0id+bBcY2I3Oxa/kREXsnJvtfxPv1F5OvrjVOpnBLt516wiMj5NE+LAZeAZNfz4caYWfkfVcEhItHAUGPMSjcf1wD1jDF73LWviNQC9gGFjTFJbglUqRwq5HQA6mrGmBKpy1klMhEppAlDFRT6+1jwaLWMhxCRdiISIyL/IyJHgCkiUkZElorIcRE55VqunuY1q0VkqGs5UkR+FJExrn33iUjn69y3toj8ICLnRGSliHwoIjMziTsnMb4uIj+5jve1iJRPs32AiOwXkVgReTmLz6eliBwREf8063qIyGbXcgsR+UVETovIYREZJyIBmRxrqoi8keb5C67XHBKRIen2vUdENorIWRE5ICIj02z+wfXztIicF5G/pX62aV7fSkTWisgZ189WOf1scvk5lxWRKa5zOCUii9Ns6y4iUa5z+FNEOrnWX1UFJiIjU6+ziNRyVU89JCJ/Ad+51s93XYczrt+RxmleX1RE3nNdzzOu37GiIvKliDyR7nw2i0iPjM5V5Ywmd89SGSgL3AQMw16/Ka7nNYGLwLgsXt8S2AWUB94BJomIXMe+s4HfgXLASGBAFu+Zkxj7AYOBikAA8DyAiDQCPnYdv6rr/aqTAWPMb8AF4O/pjjvbtZwMPOM6n78BHYARWcSNK4ZOrnjuAuoB6ev7LwADgdLAPcCjInKfa9vtrp+ljTEljDG/pDt2WeBLYKzr3N4HvhSRcunO4ZrPJgPZfc4zsNV8jV3H+o8rhhbAdOAF1zncDkRn8h4ZuQNoCHR0PV+O/ZwqAhuAtNWIY4BmQCvs7/E/gBRgGvBg6k4iEgJUw3426noZY/RRQB/YP7I7XcvtgAQgMIv9mwKn0jxfja3WAYgE9qTZVgwwQOXc7ItNHElAsTTbZwIzc3hOGcX4rzTPRwBfuZZfBeak2Vbc9Rncmcmx3wAmu5aDsIn3pkz2fRpYlOa5AW52LU8F3nAtTwbeTrNf/bT7ZnDcD4D/uJZrufYtlGZ7JPCja3kA8Hu61/8CRGb32eTmcwaqYJNomQz2+29qvFn9/rmej0y9zmnOrU4WMZR27VMK+8/nIhCSwX6BwClsOwbYfwIf5cXflC89tOTuWY4bY+JTn4hIMRH5r+tr7llsNUDptFUT6RxJXTDGxLkWS+Ry36rAyTTrAA5kFnAOYzySZjkuTUxV0x7bGHMBiM3svbCl9PtFpAhwP7DBGLPfFUd9V1XFEVccb2FL8dm5KgZgf7rzaykiq1zVIWeAR3J43NRj70+3bj+21Joqs8/mKtl8zjWw1+xUBi+tAfyZw3gzcvmzERF/EXnbVbVzlivfAMq7HoEZvZfrd3ou8KCI+AER2G8a6gZocvcs6bs2PQc0AFoaY0pypRogs6oWdzgMlBWRYmnW1chi/xuJ8XDaY7ves1xmOxtjtmOTY2eurpIBW72zE1s6LAn883piwH5zSWs2sASoYYwpBXyS5rjZdUU7hK1GSasmcDAHcaWX1ed8AHvNSmfwugNA3UyOeQH7rS1V5Qz2SXuO/YDu2KqrUtjSfWoMJ4D4LN5rGtAfW10WZ9JVYanc0+Tu2YKwX3VPu+pvX8vrN3SVhNcBI0UkQET+BtybRzF+BnQVkTauxs9RZP87Oxt4Cpvc5qeL4yxwXkRuAR7NYQzzgEgRaeT655I+/iBsqTjeVX/dL82249jqkDqZHHsZUF9E+olIIRHpAzQCluYwtvRxZPg5G2MOY+vCP3I1vBYWkdTkPwkYLCIdRMRPRKq5Ph+AKKCva/9woFcOYriE/XZVDPvtKDWGFGwV1/siUtVVyv+b61sWrmSeAryHltrdQpO7Z/sAKIotFf0KfJVP79sf2ygZi63nnov9o87IB1xnjMaYbcBj2IR9GFsvG5PNyz7FNvJ9Z4w5kWb989jEew6Y4Io5JzEsd53Dd8Ae18+0RgCjROQcto1gXprXxgFvAj+J7aVzW7pjxwJdsaXuWGwDY9d0cefUB2T9OQ8AErHfXo5h2xwwxvyObbD9D3AG+J4r3yZewZa0TwH/5upvQhmZjv3mdBDY7oojreeBLcBa4CQwmqtz0HQgGNuGo26Q3sSkbpiIzAV2GmPy/JuD8l4iMhAYZoxp43Qs3kBL7irXRKS5iNR1fY3vhK1nXexwWMqDuaq8RgDjnY7FW2hyV9ejMrab3nlsH+1HjTEbHY1IeSwR6YhtnzhK9lU/Koe0WkYppbyQltyVUsoLOTZwWPny5U2tWrWcenullPJI69evP2GMqZDdfo4l91q1arFu3Tqn3l4ppTySiKS/qzlDWi2jlFJeSJO7Ukp5IU3uSinlhQrUTEyJiYnExMQQHx+f/c7KEYGBgVSvXp3ChQs7HYpSKgsFKrnHxMQQFBRErVq1yHwOCeUUYwyxsbHExMRQu3Ztp8NRSmUh22oZEZksIsdEZGsm20VExorIHtfUWGHXG0x8fDzlypXTxF5AiQjlypXTb1ZKeYCc1LlPBTplsb0zdlqtetip3z6+kYA0sRdsen2U8gzZVssYY34QkVpZ7NIdmG7sOAa/ikhpEaniGkNaKaU8RlISxMXBpUtXP+rVg8KFYd8+2L376m1JSRARAQEB8MsvsGEDJCdfeaSkwAsvgAgsXQrx8dAru5Hx3cAdde7VuHoashjXumuSu4gMw5buqVkz/YQ2zouNjaVDhw4AHDlyBH9/fypUsDeC/f777wQEBGT62nXr1jF9+nTGjh2b5Xu0atWKn3/+2X1BK6UuS0iAI0fgxAk4eRJOn4YzZ+Dee6FiRfjxR5g40a5L+1ixAurWhbFj4bnnrj3ugQNQvTrMmAGvZTCwdffuNrkvWgTvvnvt9ueeA39/+PJLOHXKc5J7jhljxuMa0jM8PLzAjVhWrlw5oqKiABg5ciQlSpTg+eevTDaflJREoUIZf2Th4eGEh4dn+x6a2JXKOWMgJgZKloRSpWzJeeJEiI298jhxAsaNg9tvhy++yDhxfv+9Te6HD8N339ljlSoFlStDgwaQ+md9xx02ORcpAoGB9meRIlCmjN0+aBB06HBlfZEitkQfFGS3v/IKPP+8TeRpH36uCvCPPrIl+PzgjuR+kKvnmKzO9c0BWSBFRkYSGBjIxo0bad26NX379uWpp54iPj6eokWLMmXKFBo0aMDq1asZM2YMS5cuZeTIkfz111/s3buXv/76i6effponn3wSgBIlSnD+/HlWr17NyJEjKV++PFu3bqVZs2bMnDkTEWHZsmU8++yzFC9enNatW7N3716WLr165rXo6GgGDBjAhQsXABg3bhytWrUCYPTo0cycORM/Pz86d+7M22+/zZ49e3jkkUc4fvw4/v7+zJ8/n7p1M5vOUqn8ZYxNeidOwIcfwq5dsHMn/PEHXLgAU6ZAZCQcPQqjR0PZslCunH3UqWOTLEDz5jb5p24rXdr+Y6hSxW5/4AH7yEyzZvaRmZtuso/MBAVdSfQZyc8mK3ck9yXA4yIyB2gJnHFXfXu7dteu690bRoyw9WJduly7PTLSPk6cuPY/+OrV1xdHTEwMP//8M/7+/pw9e5Y1a9ZQqFAhVq5cyT//+U8WLFhwzWt27tzJqlWrOHfuHA0aNODRRx+9pm/4xo0b2bZtG1WrVqV169b89NNPhIeHM3z4cH744Qdq165NREREhjFVrFiRb775hsDAQHbv3k1ERATr1q1j+fLlfP755/z2228UK1aMkydPAtC/f39efPFFevToQXx8PCkpKdf3YSh1A5KSbCl650772LXLPoYNg5dftvXT//63TaC33GJL47fcAm1cczO1aGGrXvwy6QpSsyY89FD+nU9uXUy8yBd/fMHfqv+NGqWymlf+xmWb3EXkU6AdUF5EYrAT7xYGMMZ8gp3ktwt2fsk47HyMXuWBBx7A398fgDNnzjBo0CB2796NiJCYmJjha+655x6KFClCkSJFqFixIkePHqV69epX7dOiRYvL65o2bUp0dDQlSpSgTp06l/uRR0REMH78tZPTJCYm8vjjjxMVFYW/vz9//PEHACtXrmTw4MEUK2YnrS9btiznzp3j4MGD9OjRA7A3IimVV1JSIDoaduywj+3boWHDK42K99xjGyJLlLCJu21baNzYvrZCBVtSL1o042NnltQLshSTwpr9a5ixeQbzt8/n7KWzvHPnO7zQ+oU8fd+c9JbJuOh4ZbvBTmLsdlmVtIsVy3p7+fLXX1JPr3jx4peXX3nlFdq3b8+iRYuIjo6mXUZfL4Aiqd8TAX9/f5KSkq5rn8z85z//oVKlSmzatImUlBRN2CrfJSfDn3/C5s2QmGh7jADceqtN6qkqVbJVI2Drn1evhho1oGrVa6spRDJP7J5mx/EdzNg8g1lbZvHXmb8oEVCCng178mCTB2lfq32ev3+BukPVE5w5c4Zq1aoBMHXqVLcfv0GDBuzdu5fo6Ghq1arF3LlzM42jevXq+Pn5MW3aNJKTkwG46667GDVqFP37979cLVO2bFmqV6/O4sWLue+++7h06RLJycmXS/dKZefixStJ9913YcEC2LLFVo+C7WmSmtyffdb+bNTIlthTGyNT3XZb/sTshGMXjvHplk+ZsXkG6w+vx0/8uLvu3fy/Dv+P7g26UzygePYHcRNN7rn0j3/8g0GDBvHGG29wzz33uP34RYsW5aOPPqJTp04UL16c5s2bZ7jfiBEj6NmzJ9OnT7+8L0CnTp2IiooiPDycgIAAunTpwltvvcWMGTMYPnw4r776KoULF2b+/PnUqVPH7fErz3f4MPz2G2zadOVx5AicPWtL3idO2J4kQ4dCSAg0aWKTeKqhQ52L3QlxiXEs2bWEGZtnsGLPCpJNMqGVQ3n/7veJCI6gconKjsTl2Byq4eHhJv1kHTt27KBh2t8SH3X+/HlKlCiBMYbHHnuMevXq8cwzzzgd1mV6nbxLQoLtHtiunU3ao0bZvtwicPPNNoGHhNgSuX7Zu+LUxVOMXD2SKVFTOJdwjhola9A/uD8PNnmQxhUb59n7ish6Y0y2/a615F4ATZgwgWnTppGQkEBoaCjDhw93OiTlZc6fh6++goUL7Y01Z8/CkiX2Zp+BA+HuuyE4GIrnXy2Cx0gxKUzZOIUXv32RkxdP8mCTB4kMieSOWnfgJwWnxVeTewH0zDPPFKiSuvIOqX3Jd++2ifvSJdvxoFcvuP9+e3MOQK1a9qGutf7Qeh5b9hi/HfyNNjXbMK7zOEIqhzgdVoY0uSvlxQ4cgMWL7W3xjRrZOznr1rW3w999N7RufeXuTJW52LhYXv7uZcavH0/F4hWZft90HmzyYIEeSE8vq1Je6O23YfZs26MFbINnavu/nx+8+aZzsXmSFJPCpA2TeOnblzgdf5qnWj7FyHYjKRVYyunQsqXJXSkPFhcHP/1kG0Q3boTly23Vy6FDtn95//5w3312/BSVO2sPruWxZY+x9tBa2tZsy4ddPiS4UrDTYeWYJnelPNCKFfDWW3aI2cREW7Vy2212IK3y5e3ohur6xMbF8s9v/8mEDROoVKISM3vMpF9wvwJdBZORgtO0WwC0b9+eFStWXLXugw8+4NFHH830Ne3atSO1S2eXLl04ffr0NfuMHDmSMWPGZPneixcvZvv27Zefv/rqq6xcuTIX0StvdeECTJ8OnTvD77/bdYmJdv3TT9vS+qlTsGaNTezq+iSnJPPfdf+l/rj6TNo4iadve5pdj++if5P+HpfYQUvuV4mIiGDOnDl07Njx8ro5c+bwzjvv5Oj1y5Ytu+73Xrx4MV27dqVRo0YAjBo16rqPpTyfMfDzz3Y0xHnz4Nw5O/rhqVN2e9eu9qHc59kVzzL297HccdMdjOsyjlsr3up0SDdES+5p9OrViy+//JKEhATADqt76NAh2rZty6OPPkp4eDiNGzfmtYxG6wdq1arFiRMnAHjzzTepX78+bdq0YdeuXZf3mTBhAs2bNyckJISePXsSFxfHzz//zJIlS3jhhRdo2rQpf/75J5GRkXz22WcAfPvtt4SGhhIcHMyQIUO4dOnS5fd77bXXCAsLIzg4mJ07d14TU3R0NG3btiUsLIywsLCrxpMfPXo0wcHBhISE8OKLLwKwZ88e7rzzTkJCQggLC+PPP/90wyercsp1aYmLg44dYc4c21Xx++9hzx67Trnfwh0LGfv7WJ5o8QSrBq3y+MQOBbjk/vRXTxN1JMqtx2xauSkfdPog0+1ly5alRYsWLF++nO7duzNnzhx69+6NiPDmm29StmxZkpOT6dChA5s3b6ZJkyYZHmf9+vXMmTOHqKgokpKSCAsLo5lrkOj777+fhx9+GIB//etfTJo0iSeeeIJu3brRtWtXeqUbpzg+Pp7IyEi+/fZb6tevz8CBA/n44495+umnAShfvjwbNmzgo48+YsyYMUycOPGq1+vQwAVffDx8/rktpR89aqdpK17c3mTUtKkdPVHlnX2n9jHk8yE0r9qcMXeP8cgqmIxoyT2d1KoZsFUyqeOpz5s3j7CwMEJDQ9m2bdtV9ePprVmzhh49elCsWDFKlixJt27dLm/bunUrbdu2JTg4mFmzZrFt27Ys49m1axe1a9emfv36AAwaNIgffvjh8vb7778fgGbNmhEdHX3N6xMTE3n44YcJDg7mgQceuBx3TocG1sHF8s727fDYY3Yiib597fOuXe2Y52DHMNfEnrcSkhPo81kfAOb2mkuAf+ZTaXqaAltyz6qEnZe6d+/OM888w4YNG4iLi6NZs2bs27ePMWPGsHbtWsqUKUNkZCTx8fHXdfzIyEgWL15MSEgIU6dOZfUNjkucOmxwZkMG69DABUt0tB3+tmxZW0KfPBl69IDBg+Hvf7cDc6n889LKl1h7aC0Lei+gdpnaTofjVlpyT6dEiRK0b9+eIUOGXC61nz17luLFi1OqVCmOHj3K8uXLszzG7bffzuLFi7l48SLnzp3jiy++uLzt3LlzVKlShcTERGbNmnV5fVBQEOfOnbvmWA0aNCA6Opo9e/YAMGPGDO64444cn8+ZM2eoUqUKfn5+zJgx46qhgadMmUKca8zWkydPEhQUdHloYIBLly5d3q6u34kTdu7MNm2gdm1b/QK2Lv3wYXuz0V13aWLPb1/s+oL3f32fx5s/zv0N73c6HLfT5J6BiIgINm3adDm5h4SEEBoayi233EK/fv1o3bp1lq8PCwujT58+hISE0Llz56uG7X399ddp2bIlrVu35pZbbrm8vm/fvrz77ruEhoZe1YgZGBjIlClTeOCBBwgODsbPz49HHnkkx+cyYsQIpk2bRkhICDt37rxqaOBu3boRHh5O06ZNL3fVnDFjBmPHjqVJkya0atWKI0eO5Pi91NWSk6FbN1vt8thjcPq07Zue2qwSGGjn+FT5768zfzFo8SDCqoQx5u6suyl7Kh3yV+WaXqeMJSbCN9/YmYlcnY+IjLxyp2hwcP5OkKwylpicyB1T72Drsa1sGL6Bm8ve7HRIuaJD/iqVD4yBX3+FmTNtf/QTJ+w8oE8+acc+z4PJutQNemXVK/wS8wtzes7xuMSeG1oto9QN+PhjaNXK1qN36GC7NMbE6KQWBdXy3csZ/dNohjcbTp9b+zgdTp4qcCV3Y4zX9DP1Rk5V4xUEZ87AZ5/ZoQAeecTOGXrffTaR9+wJQUFOR6iycvDsQQYuHkiTSk34T8f/OB1OnitQyT0wMJDY2FjKlSunCb4AMsYQGxvrU90pjbE3E02fbsdFj4+3Iyz6ub7zVq1q69VVwZaUkkTEggguJl5kXq95FC1c1OmQ8lyBSu7Vq1cnJiaG48ePOx2KykRgYCDVq1d3Oow8d/AgVKtml194wXZZfOghOwVd8+baMOppRq4eyZq/1jCzx0walPeN8Y8LVHIvXLgwtWt7140EynPs2wdz59p+5/v22aEAihWzJfaaNSHAe25e9Cnf/PkNb615iyFNh9C/SX+nw8k32qCqfN6aNfC3v9lRF196yY7rMnr0le0336yJ3VMdPneYBxc9SKMKjfi/Lv/ndDj5qkCV3JXKDydOwIIF0KwZhIfb0nl8vJ2ark8fnRzaWySnJNN/YX/OJ5xn1aBVFCvsW12YNLkrn3D2rK1emTPH3miUlGRvNAoPt0l+40anI1Tu9sYPb7AqehVTuk+hUYVGToeT7zS5K69nDDRpAvv3w003wXPP2VEYQ0KcjkzlBWMM7//yPv/+/t8MDBlIZNNIp0NyhCZ35XWOHYPx420J/bvv7IBcY8bY3i+33aY9XbxZfFI8w74YxozNM+jVqBcf3/Ox0yE5RpO78hq//QbjxtlhABIS7EiLsbFQseKVwbqU9zp07hA95vbg94O/M6rdKP51+798+n4ZTe7KK3z3nb39PygIhg+HESMgzaCbysv9FvMbPeb24FzCORb1WcR9t9zndEiO0+SuPFJMDHzyiZ304tln4Y47YMIE6N3bToahfMe0qGkMWzqMakHV+HrA114x/6k7aD935TGMsRNF9+pluyu+9Rbs2GG3+fvD0KGa2H1JUkoSz614jsjPI2lTsw1rH16riT0NLbkrj/H88/D++1CmjC2tP/qondlI+Z5TF0/Rd0Ffvv7za55s8STvdXyPQn6aztLST0MVSBcuwMKFdsCuDz6Axo1tlUvjxrYbow6p67t2HN9Btznd2H96P5O6TWJI6BCnQyqQNLmrAiMlBX74AaZNs0Prnj9vS+aHDtmk3rKlfSjftfSPpfRb0I9ihYuxOnI1rWq0cjqkAkuTu3LchQt2PJfz56FLFyhUyA4DMGgQtG59ZXhd5buMMbz949u8/N3LhFUJY1GfRdQoVcPpsAq0HCV3EekE/C/gD0w0xrydbntNYBpQ2rXPi8aYZe4NVXmT6GhYvhxmzLB90tets42hK1dC06Za7aKu9uTyJxm3dhz9gvsx8d6JPjEe+43KtkwkIv7Ah0BnoBEQISLpB2r4FzDPGBMK9AU+cnegynMZYx9gp6W76SZb3TJihB3zpU8fSE6221u10sSurnYi7gSfrP+EoaFDmdljpib2HMpJyb0FsMcYsxdAROYA3YHtafYxQGontFLAIXcGqTyLMbB9u60///57+/Pnn233xZIloUULOwFGu3a2Lt2HbyJUOTB/23ySUpJ4ouUTPn3HaW7lJLlXAw6keR4DpG/WGgl8LSJPAMWBOzM6kIgMA4YB1KxZM7exqgIsJcXWjf/4I/ToYYfVBTueS/v2tuoFoH9/+1Aqp2ZvnU3jCo0JrhjsdCgexV1NVRHAVGNMdaALMENErjm2MWa8MSbcGBNeoUIFN721csqZM/Yu0ebN7U+AunXhnntg0iTYswcOHIBZs6B+fWdjVZ5p/+n9/PjXj/QL7qel9lzKScn9IJC2Wbq6a11aDwGdAIwxv4hIIFAeOOaOIFXB8uOPMHGiHaDr4kUIDoby5e22KlVg6lRHw1NeZM7WOQBE3BrhcCSeJycl97VAPRGpLSIB2AbTJen2+QvoACAiDYFAQGe59iLnz19ZfvFFe4PRgAHw+++waZO9wUgpd5u9dTatarSidhm9FTm3si25G2OSRORxYAW2m+NkY8w2ERkFrDPGLAGeAyaIyDPYxtVIY1L7RyhPlZwMX39tS+krVtjui+XL25J5lSq2b7pSeWXrsa1sPrqZcZ3HOR2KR8pRP3dXn/Vl6da9mmZ5O9DavaEpp5w4Af/3fzB5sh19sXx5eOQR22gKdsJopfLa7C2z8Rd/Hmj8gNOheCS9Q1WRmGjr0YsXt90Uz52D11+Hjh3tuC733gsBAU5HqXyJMYbZW2ZzV927qFi8otPheCRN7j7qxAl7h+jSpfDVV/Zmot69Ye5ce4PRwYO26kUpJ/wS8wv7z+zn9favOx2Kx9Lk7iOMsVUsNVz9njp0gM2boXJlm9S7drXrUmliV06atXkWRQsV1RmVboAmdy+WlASrV8OiRbaEfvKknVM0IADeew9Kl4awMB2YSxUsicmJzNs+j24NuhFUJMjpcDyWJncvNX++ncwiNtaO1XLXXbZ0njqGy50Z3kOslPNW7l3JibgT9Avu53QoHk2Tuxe4dMmOpvjZZzBkCLRta+vNO3a0U9J17KiDcSnPMXvrbMoElqHTzZ2cDsWjaXL3UElJsGyZLaEvWWIbREuVshNFt20L4eH2tn+lPElcYhyLdiyiX3A/Avy1i9aN0OTuQRIT4Y8/roykOHSorWbp1cs+OnTQLovKsy3ZtYQLiRfoH6yjy90oTe4eIDoaJkywNxUFBNjn/v52ON2bb4bChZ2OUCn3mL1lNtWCqtH2prZOh+LxtJ9EAfbrr3bauTp14O23bVXLhx9emfiiYUNN7Mp7xMbFsnzPciJujcDv2kFlVS5pyb2AiYmxCbtSJdt1cdMmeOUVWwVTQ6eMVF5swY4FJKUkaS8ZN9F/jwVAcjJ8+SV062anoPvgA7u+UyfYvx/+/W9N7Mr7zd4ym4blG9K0clOnQ/EKmtwd9u67ttqla1c7fO7//A8MG2a3+flBIf1upXzAgTMH+H7/9zophxtp6nDA9u3QyDXF+MaNdpai996D7t21Dl35Jp2Uw/00ueeThAR7k9H//q8toW/ebGcwmj5dS+dKzd46m5bVWlK3bF2nQ/EaWi2Tx86cgVGjbF16//5w+rQdK71WLbtdE7vydduPbyfqSJQ2pLqZppY8cvYslCxpuy2++y60aQNPPmmHAtCBupS64tMtn+InfvRp3MfpULyKJnc3Sky0c4uOHQtxcbBhgx15MToaypVzOjqlCh5jDLO3zubOOndSqUQlp8PxKlqGdIMzZ+Cdd+xgXX37wpEjMGjQlREYNbErlbHfDv7G3lN76XerVsm4m5bc3WDhQtuF8e9/h08+gc6d7fAASqmszd4ymyL+RejRsIfToXgdTe7XYfduW4/etCmMGAH9+kGTJtCsmdORKeU5klKSmLttLvc2uJeSRUo6HY7X0eSeC2vXwujRtqQeEABVq9r1RYpoYlcqt77b9x3HLhzTESDziCb3HHr++StT0730ku35Uknbf5S6brO2zKJUkVJ0vrmz06F4JU3umUhKshNhtG9vJ5Hu0sVOGj1sGATptI5K3ZCLiRdZuGMhfRr3oUihIk6H45U8srdMXFzeHfvcOXsXab16ti59+nS7/u9/h+ee08SulDss/WMp5xPO641Lecgjk3vfvtC8OYwfb5OxOxgDL79sR198+mlbn75oka2OUUq51+yts6lSogp33HSH06F4LY9M7p06QXw8DB9uq0oefhiioq7vWHv32p8idvnuu+0kGT/9BPfdp3eTKuVupy6eYtnuZUTcGoG/n/YZzisembpGjLADb/3yC/TuDbNnw9KldltCgh2/JSspKXZy6Q4doG5d2LHDrp81C+bNg5Yt8zR8pXzagh0LSEhO0CqZPOaRyR1sSfu22+y8oocOweOP2/Wff26rVAYPtsk/dUo6sKX9CRPg1lvhnntg1y7btTG1S6OW0pXKe5M2TqJh+YaEVQlzOhSv5hXprFQp20URoHFjGDDADq/bqpUdVnfsWDvuy4UL8NRTtl/6jBm2GuYf/7CvV0rlvc1HN/NrzK8MazZMJ+XIY16R3NNq1Aj++184fNiW0osVg48+skPrlitn5yTdsAEefNDeiKSUyj8T1k+giH8RBjQZ4HQoXs/rknuqEiXspNK//26rZ1ILCfXqXVlWSuWfuMQ4ZmyeQa9GvShXTEfTy2tem9zTKlPG6QiUUvO3zefMpTMMazbM6VB8gk8kd6WU88ZvGE+Dcg1oW7Ot06H4BE3uSqk8t/XYVn4+8LM2pOYjTe5KqTw3Yf0EAvwDGBgy0OlQfIYmd6VUnrqYeJHpm6fTs2FPyhcr73Q4PiNHyV1EOonILhHZIyIvZrJPbxHZLiLbRGS2e8NUSnmqz7Z/xun409qQms+yHfJXRPyBD4G7gBhgrYgsMcZsT7NPPeAloLUx5pSIVMyrgJVSnmX8hvHUK1tPBwnLZzkpubcA9hhj9hpjEoA5QPd0+zwMfGiMOQVgjDnm3jCVUp5o+/Ht/PjXj9qQ6oCcJPdqwIE0z2Nc69KqD9QXkZ9E5FcR6ZTRgURkmIisE5F1x48fv76IlVIeY8L6CRT2K8ygkEFOh+Jz3NWgWgioB7QDIoAJIlI6/U7GmPHGmHBjTHiFChXc9NZKqYIoPimeaZum0aNhDyoU17/3/JaT5H4QqJHmeXXXurRigCXGmERjzD7gD2yyV0r5qAXbF3Aq/hTDwrQh1Qk5Se5rgXoiUltEAoC+wJJ0+yzGltoRkfLYapq97gtTKeVpxm8YT90ydWlfu73TofikbJO7MSYJeBxYAewA5hljtonIKBHp5tptBRArItuBVcALxpjYvApaKVWw7Tyxkx/2/8DDYQ/jJ3o7jROy7QoJYIxZBixLt+7VNMsGeNb1UEr5uAnrJ1DIrxCRTSOdDsVn6b9UpZRbpTak3nfLfVQqUcnpcHyWJnellFst2rGI2Iux2pDqME3uSim3Gr9hPLVL16ZDnQ5Oh+LTNLkrpdzmj9g/WB29WhtSCwD99JVSbjNxw0QK+RVicOhgp0PxeZrclVJucSnpElOiptCtQTcql6jsdDg+T5O7UsotPt/1OSfiTmhDagGhyV0p5Rbj14/nplI3cVfdu5wORaHJXSnlBntO7uHbfd8yNGyoNqQWEHoVlFI3bOKGifiLP4ObakNqQaHJXSl1QxKSE5gSNYWu9btSrWT6qR6UUzS5K6VuyJJdSzh24ZjOkVrAaHJXSt2Q8evHU6NkDTrW7eh0KCoNTe5Kqeu299Revtn7DUPDhuLv5+90OCoNTe5Kqes2eeNkBNGG1AJIk7tS6rokpyQzNWoqHW/uSI1SNbJ/gcpXmtyVUtdlxZ8rOHjuIA+FPuR0KCoDmtyVUtdl0sZJlC9Wnm4NumW/s8p3mtyVUrl27MIxluxawsAmAwnwD3A6HJUBTe5KqVybsWkGSSlJPBSmVTIFlSZ3pVSuGGOYtHESt1W/jUYVGjkdjsqEJnelVK78GvMrO07s0IbUAk6Tu1IqVyZtnETxwsXp07iP06GoLGhyV0rl2PmE88zdNpfejXsTVCTI6XBUFjS5K6VybN62eZxPOK9VMh5Ak7tSKscmbZxEg3INaFWjldOhqGxocldK5ciO4zv4+cDPPBT6ECLidDgqG5rclVI5MmnjJAr5FWJgyECnQ1E5oMldKZWthOQEpm+azr3176VSiUpOh6NyQJO7UipbS/9YyvG449qQ6kE0uSulsjVp4ySqBlWl480625Kn0OSulMrSwbMH+WrPV0SGRFLIr5DT4agc0uSulMrS1KippJgUhoQOcToUlQua3JVSmUoxKUyOmky7Wu2oW7au0+GoXNDkrpTK1PfR37P31F5tSPVAmtyVUpmatHESpYqUomfDnk6HonJJk7tSKkOn40+zYMcC+gX3o2jhok6Ho3IpR8ldRDqJyC4R2SMiL2axX08RMSIS7r4QlVJOmL1lNvFJ8Vol46GyTe4i4g98CHQGGgERInLN9CsiEgQ8Bfzm7iCVUvlv0sZJhFQKIaxKmNOhqOuQk5J7C2CPMWavMSYBmAN0z2C/14HRQLwb41NKOSDqSBQbDm9gaNhQHSTMQ+UkuVcDDqR5HuNad5mIhAE1jDFfZnUgERkmIutEZN3x48dzHaxSKn9M2jCJIv5F6B/c3+lQ1HW64QZVEfED3geey25fY8x4Y0y4MSa8QoUKN/rWSqk8EJ8Uz6wts7i/4f2UKVrG6XDUdcpJcj8I1EjzvLprXaog4FZgtYhEA7cBS7RRVSnPtGjHIk7Fn9KGVA+Xk+S+FqgnIrVFJADoCyxJ3WiMOWOMKW+MqWWMqQX8CnQzxqzLk4iVUnlq4saJ1C5dm/a12zsdiroB2SZ3Y0wS8DiwAtgBzDPGbBORUSLSLa8DVErln72n9vLdvu8Y3HQwfqK3wXiyHA3xZoxZBixLt+7VTPZtd+NhKaWcMGXjFAQhsmmk06GoG6T/mpVSACSnJDN101Q63tyRGqVqZP8CVaBpcldKAbAqehUxZ2MY3HSw06EoN9DkrpQC7LjtpQNL062BNqV5A03uSinOXjrLwh0L6du4L4GFAp0OR7mBJnelFJ9t/4yLSRcZ1HSQ06EoN9HkrpRiatRU6perT8tqLZ0ORbmJJnelfNyfJ/9kzV9riAyJ1EHCvIgmd6V83PRN0xGEASEDnA5FuZEmd6V8WIpJYfrm6dxZ506ql6zudDjKjTS5K+XD1uxfQ/TpaAaFaEOqt9HkrpQPm7ppKkEBQfRo2MPpUJSbaXJXykedTzjP/G3z6d24N8UKF3M6HOVmmtyV8lELdyzkQuIFrZLxUprclfJR0zZNo06ZOrSp2cbpUFQe0OSulA/af3o/q/atYlDIIO3b7qU0uSvlg2ZsnoHBMDBkoNOhqDyiyV0pH2OMYfqm6bSr1Y5apWs5HY7KI5rclfIxv8T8wu6Tu7Uh1ctpclfKx0yNmkqxwsXo2bCn06GoPKTJXSkfcjHxInO3zaVXo14EFQlyOhyVhzS5K+VDFu9czNlLZ7VKxgdoclfKh0zbNI2apWrSrlY7p0NReUyTu1I+4uDZg3yz9xsGNhmIn+ifvrfTK6yUj5i5eSYpJkX7tvsITe5K+QBjDNM2TaN1jdbUK1fP6XBUPtDkrpQPWHtoLTtO7NCGVB+iyV0pHzAtahqBhQLp3bi306GofKLJXSkvdynpEp9u/ZQet/SgVGApp8NR+USTu1Je7os/vuBU/CmtkvExmtyV8nLTNk2jalBV7qxzp9OhqHykyV0pL3b0/FGW717OgCYD8PfzdzoclY80uSvlxWZtmUWySdYqGR+kyV0pL2WMYWrUVFpUa0HDCg2dDkflM03uSnmpqCNRbDm2RUvtPkqTu1JeyBjDG2veIMA/gL639nU6HOWAQk4HoJRyvw/XfsjCHQsZfedoyhYt63Q4ygFaclfKy6w7tI5nVzzLPfXu4flWzzsdjnJIjpK7iHQSkV0iskdEXsxg+7Misl1ENovItyJyk/tDVUpl59TFUzww/wGqBFVh2n3TdGhfH5btlRcRf+BDoDPQCIgQkUbpdtsIhBtjmgCfAe+4O1ClVNaMMQz+fDAxZ2OY22su5YqVczok5aCc/FtvAewxxuw1xiQAc4DuaXcwxqwyxsS5nv4KVHdvmEqp7Hzw6wd8vutz3r3rXW6rfpvT4SiH5SS5VwMOpHke41qXmYeA5RltEJFhIrJORNYdP34851EqpbL0a8yv/GPlP+hxSw+eavmU0+GoAsCtFXIi8iAQDryb0XZjzHhjTLgxJrxChQrufGulfFZsXCy95/emRskaTO4+GRFxOiRVAOSkK+RBoEaa59Vd664iIncCLwN3GGMuuSc8pVRWUkwKAxcP5OiFo/w05CdKB5Z2OiRVQOSk5L4WqCcitUUkAOgLLEm7g4iEAv8Fuhljjrk/TKVURt796V2W7V7G+3e/T3jVcKfDUQVItsndGJMEPA6sAHYA84wx20RklIh0c+32LlACmC8iUSKyJJPDKaXcZM3+Nbz83cv0btybEc1HOB2OKmDEGOPIG4eHh5t169Y58t5KebpjF44R+t9Qihcuzrph6yhZpKTTIal8IiLrjTHZfk3T4QeU8jApJoUBiwYQGxfLl0O/1MSuMqTJXSkP89aat/j6z68Z33U8TSs3dTocVUDpvclKeZBV+1bx2urX6B/cn6FhQ50ORxVgmtyV8hBHzh8hYkEE9cvV55Oun2h/dpUlrZZRqoBLSE5g+/HtPLPiGc5eOsvKgSspEVDC6bBUAafJXakC5Nylc2w6uomNhzey8chGoo5EsfXYVhJTEgGY2n0qt1a81eEolSfQ5K6UQ46cP0LUkajLiXzjkY3sObnn8vbyxcoTWjmUZ257htAqoTSv2py6Zes6GLHyJB6X3CdvnMx7v7zndBhKXSXFpFx+JKckX1k2yRmuS0pJIi4x7vLra5euTWiVUAY2GUholVBCK4dSNaiq1qur6+Zxyb1c0XI0qpB+OHmlnOcv/vj7+eMnfviL/XnNst+V5RolaxBaJZSmlZvqmDDK7TwuuXe/pTvdb+me/Y5KKeXDtCukUkp5IU3uSinlhTS5K6WUF9LkrpRSXkiTu1JKeSFN7kop5YU0uSullBfS5K6UUl7IsWn2ROQ4sP86X14eOOHGcDyNL5+/L587+Pb567lbNxljKmT3AseS+40QkXU5mUPQW/ny+fvyuYNvn7+ee+7OXatllFLKC2lyV0opL+SpyX280wE4zJfP35fPHXz7/PXcc8Ej69yVUkplzVNL7koppbKgyV0ppbyQxyV3EekkIrtEZI+IvOh0PPlJRKJFZIuIRInIOqfjyWsiMllEjonI1jTryorINyKy2/WzjJMx5pVMzn2kiBx0Xf8oEeniZIx5RURqiMgqEdkuIttE5CnXel+59pmdf66uv0fVuYuIP/AHcBcQA6wFIowx2x0NLJ+ISDQQbozxiRs5ROR24Dww3Rhzq2vdO8BJY8zbrn/uZYwx/+NknHkhk3MfCZw3xoxxMra8JiJVgCrGmA0iEgSsB+4DIvGNa5/Z+fcmF9ff00ruLYA9xpi9xpgEYA6gc+55KWPMD8DJdKu7A9Ncy9Owv/ReJ5Nz9wnGmMPGmA2u5XPADqAavnPtMzv/XPG05F4NOJDmeQzXcdIezABfi8h6ERnmdDAOqWSMOexaPgJUcjIYBzwuIptd1TZeWS2RlojUAkKB3/DBa5/u/CEX19/Tkruva2OMCQM6A4+5vrr7LGPrFD2nXvHGfQzUBZoCh4H3HI0mj4lICWAB8LQx5mzabb5w7TM4/1xdf09L7geBGmmeV3et8wnGmIOun8eARdhqKl9z1FUnmVo3eczhePKNMeaoMSbZGJMCTMCLr7+IFMYmtlnGmIWu1T5z7TM6/9xef09L7muBeiJSW0QCgL7AEodjyhciUtzVuIKIFAfuBrZm/SqvtAQY5FoeBHzuYCz5KjWxufTAS6+/iAgwCdhhjHk/zSafuPaZnX9ur79H9ZYBcHX/+QDwByYbY950NqL8ISJ1sKV1gELAbG8/dxH5FGiHHe70KPAasBiYB9TEDhnd2xjjdQ2PmZx7O+xXcgNEA8PT1EF7DRFpA6wBtgAprtX/xNY7+8K1z+z8I8jF9fe45K6UUip7nlYto5RSKgc0uSullBfS5K6UUl5Ik7tSSnkhTe5KKeWFNLkrpZQX0uSulFJe6P8DF73hD/ohJC8AAAAASUVORK5CYII=",
"text/plain": [
"