{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import os\n", "import json\n", "\n", "import matplotlib.pyplot as plt\n", "from dataclasses import dataclass\n", "import numpy as np" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "this_dir = os.path.dirname(os.path.abspath(''))\n", "# results is in \"../results\"\n", "results_dir = os.path.join(this_dir, \"results\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "experiment_folder = \"casestudy_example\"\n", "experiment_name = \"cs_example_edf\"\n", "\n", "experiment_file = os.path.join(results_dir, experiment_folder, experiment_name + \".json\")\n", "if not os.path.exists(experiment_file):\n", " print(\"Experiment file not found: \", experiment_file)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "with open(experiment_file) as f:\n", " experiment_data_raw = json.load(f)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of records: 12118\n", "First record: {'entry': {'operation': 'start_work', 'chain': 0, 'node': 'node_0', 'count': 500, 'next_release_us': 99886}, 'time': 0.0001}\n", "Operation types: ['get_next_executable', 'next_deadline', 'wait_for_work', 'end_work', 'start_work']\n" ] } ], "source": [ "def pre_process_data(data):\n", " for record in data:\n", " record[\"time\"] = int(record[\"time\"])\n", "\n", " min_time = min([record[\"time\"] for record in data])\n", " for record in data:\n", " record[\"time\"] -= min_time\n", " record[\"time\"] /= (1000 * 1000)\n", "\n", " if record[\"entry\"][\"operation\"] == \"next_deadline\":\n", " #print(\"Record: \", record)\n", " record[\"entry\"][\"deadline\"] = int(record[\"entry\"][\"deadline\"])\n", " record[\"entry\"][\"deadline\"] -= min_time\n", " record[\"entry\"][\"deadline\"] /= (1000 * 1000)\n", "\n", " # data = sorted(data, key=lambda x: x[\"time\"])\n", " return data\n", "\n", "experiment_data = pre_process_data(experiment_data_raw)\n", "\n", "print(\"Number of records: \", len(experiment_data))\n", "print(\"First record: \", experiment_data[0])\n", "operation_types = list(set([record[\"entry\"][\"operation\"] for record in experiment_data]))\n", "print(\"Operation types: \", operation_types)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "@dataclass\n", "class Record:\n", " start_time: float\n", " end_time: float\n", " node_name: str\n", "\n", "@dataclass\n", "class RecordLine:\n", " node_name: str\n", " count: int\n", "\n", " def __eq__(self, other):\n", " return self.node_name == other.node_name and self.count == other.count\n", "\n", " def __hash__(self):\n", " return hash((self.node_name, self.count))\n", "\n", "def get_records(data) -> list[Record]:\n", " # used to match start_work and end_work records\n", " current_records: dict[RecordLine, Record] = {}\n", " records = []\n", " for record in data:\n", " if record[\"entry\"][\"operation\"] == \"start_work\":\n", " current_record = Record(start_time=record[\"time\"], node_name=record[\"entry\"][\"node\"], end_time=None)\n", " current_record_line = RecordLine(node_name=record[\"entry\"][\"node\"], count=record[\"entry\"][\"count\"])\n", " if current_record_line in current_records:\n", " raise Exception(\"Overlapping records\")\n", " current_records[current_record_line] = current_record\n", " elif record[\"entry\"][\"operation\"] == \"end_work\":\n", " current_record_line = RecordLine(node_name=record[\"entry\"][\"node\"], count=record[\"entry\"][\"count\"])\n", " if current_record_line not in current_records:\n", " raise Exception(\"No start record\")\n", " current_record = current_records[current_record_line]\n", " current_record.end_time = record[\"time\"]\n", " records.append(current_record)\n", " del current_records[current_record_line]\n", " return records\n", "\n", "records = get_records(experiment_data)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of nodes: 4\n" ] } ], "source": [ "num_nodes = len(set([record.node_name for record in records]))\n", "print(\"Number of nodes: \", num_nodes)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "3c172c35015c4ffd92a176ce80ffd18d", "version_major": 2, "version_minor": 0 }, "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAJHtJREFUeJzt3X+M1/V9wPHXlx8eCNzh6YS7eVoQW37kqA4UQSNYLu7YEsnaFWqIP5bTTtyKratYkwGHxdOqTVn8sSl0igmZsszMxJq507XMtHCKk1Xh2tSDCpUCqwintpzKffZH4zdeBT30+/3e9+79eCTfcD8+38/7x31zPPM5Pkcuy7IsAABIxqC+ngAAAKUlAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEjOkryfQn3V3d8eePXti1KhRkcvl+no6AEAvZFkWb775ZtTW1sagQWleCxOAn8KePXuirq6ur6cBAHwCu3fvjtNOO62vp9EnBOCnMGrUqIj4/QuosrKyj2cDAPRGZ2dn1NXV5f8eT5EA/BTe/7FvZWWlAASAfiblf76V5g++AQASJgABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwDLWC5XmGMKea5Sj9db1jfwXwu5XOnn3hvluleF0p/H66+v9d4qx7mXen18cgIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDH9JgCbm5vj7LPP7utpAAD0e/0mAAvpl7/8ZTQ1NcW4ceNi+PDhceaZZ8aKFSvinXfe6eupAQAU3ZC+nkBf+NnPfhbd3d1x//33x4QJE+Lll1+Oa665Jt5+++246667+np6AABFVZQrgHPmzIklS5bE0qVLo7q6OsaOHRvNzc35z+/atSvmz58fI0eOjMrKyliwYEHs27evxzluv/32GDNmTIwaNSqampri8OHDHxpn7dq1MWnSpBg2bFhMnDgx7rvvvl7Nr7GxMR588MG45JJLYvz48XHppZfGN7/5zXjsscc+1boBAPqDov0IeN26dTFixIhoa2uLO+64I2655ZZobW2N7u7umD9/fhw4cCA2btwYra2tsWPHjli4cGH+uRs2bIjm5uZoaWmJLVu2RE1NzYfibv369bF8+fK49dZbo729PVpaWmLZsmWxbt26TzTfQ4cORXV19adaMwBAf5DLsiwr9EnnzJkTR44ciWeffTb/sfPOOy++8IUvxNy5c2PevHmxc+fOqKuri4iI7du3x5QpU+K5556Lc889N2bNmhXnnHNO3Hvvvfnnn3/++XH48OHYunVrRERMmDAhvv3tb8dll12WP2bVqlXx5JNPxk9+8pPjmu8rr7wS06ZNi7vuuiuuueaaYx7X1dUVXV1d+fc7Ozujrq4uDh06FJWVlcc1Zm/kchEf99XpzTGFPFepx+st6xv4r4Vc7vd/lnLuvVGue1WO6yv1eP31td5b5Tj3Uq/vk+rs7Iyqqqqi/f3dHxTtCuDUqVN7vF9TUxP79++P9vb2qKury8dfRMTkyZNj9OjR0d7eHhER7e3tMWPGjB7PnzlzZv7tt99+Ozo6OqKpqSlGjhyZf6xatSo6OjqOa56vvfZaNDY2xpe//OWPjL+IiNtuuy2qqqryjw+uAQCgvyjaTSBDhw7t8X4ul4vu7u6CnPutt96KiIg1a9Z8KBQHDx7c6/Ps2bMnLr744pg1a1Y88MADH3v8zTffHDfccEP+/fevAAIA9Cclvwt40qRJsXv37ti9e3ePHwEfPHgwJk+enD+mra0trrjiivzzNm/enH97zJgxUVtbGzt27IhFixZ9onm89tprcfHFF8e0adPiwQcfjEGDPv5iaEVFRVRUVHyi8QAAykXJA7ChoSHq6+tj0aJFsXr16njvvffiuuuui9mzZ8f06dMjIuL666+Pq666KqZPnx4XXHBBrF+/PrZt2xbjx4/Pn2flypWxZMmSqKqqisbGxujq6ootW7bEG2+80eMq3dG89tprMWfOnDjjjDPirrvuiv/7v//Lf27s2LHFWTgAQJkoeQDmcrl4/PHH42tf+1pcdNFFMWjQoGhsbIy77747f8zChQujo6Mjli5dGocPH44vfelLsXjx4njqqafyx1x99dVx4oknxp133hk33nhjjBgxIurr6+PrX//6x86htbU1XnnllXjllVfitNNO6/G5ItwTAwBQVopyF3Aqin0XUX++w6sc7xazvsKey13AhR+vv96JWa7j9dfXem+V49zdBdx/JPlfwQEApGxABmBLS0uPXw/zwce8efP6enoAAH1qQP5fwNdee20sWLDgqJ8bPnx4iWcDAFBeBmQAVldX+2/dAACOYUD+CBgAgGMTgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkZ0tcT4NiyrDDHFPJcpR6vt6xv4L8WfG0KP15v9OfxvPbKd696o5Dn4sNcAQQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAsY7lcYY4p5LlKPV5vGa9vxivl66rU4/WW9ZXveL7vle/ce6PU46VGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkpt8EYHNzc5x99tl9PQ0AgH6v3wRgoR04cCAWLVoUlZWVMXr06Ghqaoq33nqrr6cFAFB0yQbgokWLYtu2bdHa2hpPPPFE/Pd//3d89atf7etpAQAUXVECcM6cObFkyZJYunRpVFdXx9ixY6O5uTn/+V27dsX8+fNj5MiRUVlZGQsWLIh9+/b1OMftt98eY8aMiVGjRkVTU1McPnz4Q+OsXbs2Jk2aFMOGDYuJEyfGfffd16v5tbe3x3/8x3/E2rVrY8aMGXHhhRfG3XffHY888kjs2bPnU60dAKDcFe0K4Lp162LEiBHR1tYWd9xxR9xyyy3R2toa3d3dMX/+/Dhw4EBs3LgxWltbY8eOHbFw4cL8czds2BDNzc3R0tISW7ZsiZqamg/F3fr162P58uVx6623Rnt7e7S0tMSyZcti3bp1Hzu3TZs2xejRo2P69On5jzU0NMSgQYOira3tmM/r6uqKzs7OHg8AgP5mSLFOPHXq1FixYkVERJx11llxzz33xDPPPBMRES+99FLs3Lkz6urqIiLi4YcfjilTpsTzzz8f5557bqxevTqampqiqakpIiJWrVoVTz/9dI+rgCtWrIjvfve78cUvfjEiIsaNGxfbt2+P+++/P6688sqPnNvevXvj1FNP7fGxIUOGRHV1dezdu/eYz7vtttti5cqVx7kTAADlpWhXAKdOndrj/Zqamti/f3+0t7dHXV1dPv4iIiZPnhyjR4+O9vb2iPj9j2hnzJjR4/kzZ87Mv/32229HR0dHNDU1xciRI/OPVatWRUdHR7GWFDfffHMcOnQo/9i9e3fRxgIAKJaiXQEcOnRoj/dzuVx0d3cX5Nzv3627Zs2aD4Xi4MGDP/b5Y8eOjf379/f42HvvvRcHDhyIsWPHHvN5FRUVUVFR8QlmDABQPkp+F/CkSZNi9+7dPa6ebd++PQ4ePBiTJ0/OH/OH/xZv8+bN+bfHjBkTtbW1sWPHjpgwYUKPx7hx4z52DjNnzoyDBw/GCy+8kP/Yf/3Xf0V3d/eHghIAYKAp2hXAY2loaIj6+vpYtGhRrF69Ot5777247rrrYvbs2fmbMq6//vq46qqrYvr06XHBBRfE+vXrY9u2bTF+/Pj8eVauXBlLliyJqqqqaGxsjK6urtiyZUu88cYbccMNN3zkHCZNmhSNjY1xzTXXxD/90z/Fu+++G3/7t38bX/nKV6K2trao6wcA6GslvwKYy+Xi8ccfj5NOOikuuuiiaGhoiPHjx8ejjz6aP2bhwoWxbNmyWLp0aUybNi1effXVWLx4cY/zXH311bF27dp48MEHo76+PmbPnh0PPfRQr64ARvz+LuKJEyfG3Llz48/+7M/iwgsvjAceeKCgawUAKEe5LMuyvp5Ef9XZ2RlVVVVx6NChqKysLPj5c7mIj/vq9OaYQp6r1OP1lvH6ZryI0r2uSj1eb1lf+Y7n+175zr03ijlesf/+7g+S/Z9AAABSNSADsKWlpcevh/ngY968eX09PQCAPlXym0BK4dprr40FCxYc9XPDhw8v8WwAAMrLgAzA6urqqK6u7utpAACUpQH5I2AAAI5NAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRGAAIAJEYAAgAkRgACACRmSF9PgGPLssIcU8hzlXq83jJe+Y7ntWd9fTWer035zr03Sj1ealwBBABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAsc7lcYY7pi/EKda6+WF+hxuyL/Szlvpd6vOM518cdV45zOp5zleqY4zlXIfb8eMYr5bkG+ni9VervHRSPAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABITL8JwObm5jj77LP7ehoAAP1evwnAQrv00kvj9NNPj2HDhkVNTU1cfvnlsWfPnr6eFgBA0SUbgBdffHFs2LAhfv7zn8e//du/RUdHR/zlX/5lX08LAKDoihKAc+bMiSVLlsTSpUujuro6xo4dG83NzfnP79q1K+bPnx8jR46MysrKWLBgQezbt6/HOW6//fYYM2ZMjBo1KpqamuLw4cMfGmft2rUxadKkGDZsWEycODHuu+++Xs/xG9/4Rpx//vlxxhlnxKxZs+Jb3/pWbN68Od59991PvG4AgP6gaFcA161bFyNGjIi2tra444474pZbbonW1tbo7u6O+fPnx4EDB2Ljxo3R2toaO3bsiIULF+afu2HDhmhubo6WlpbYsmVL1NTUfCju1q9fH8uXL49bb7012tvbo6WlJZYtWxbr1q077rkeOHAg1q9fH7NmzYqhQ4d+6rUDAJSzXJZlWaFPOmfOnDhy5Eg8++yz+Y+dd9558YUvfCHmzp0b8+bNi507d0ZdXV1ERGzfvj2mTJkSzz33XJx77rkxa9asOOecc+Lee+/NP//888+Pw4cPx9atWyMiYsKECfHtb387Lrvssvwxq1atiieffDJ+8pOf9GqeN910U9xzzz3x29/+Ns4///x44okn4uSTTz7m8V1dXdHV1ZV/v7OzM+rq6uLQoUNRWVnZqzGPVy4X8XFfod4c0xfjFepcfbG+iMKM2Rf7GVG6fS/1eIWcVznOqZDzKsf1lfp7RyHPNdDH661Sf+8ols7Ozqiqqirq39/lrmhXAKdOndrj/Zqamti/f3+0t7dHXV1dPv4iIiZPnhyjR4+O9vb2iIhob2+PGTNm9Hj+zJkz82+//fbb0dHREU1NTTFy5Mj8Y9WqVdHR0dHrOd54443x4osvxn/+53/G4MGD44orroiP6uHbbrstqqqq8o8PrgEAoL8YUqwT/+GPUnO5XHR3dxfk3G+99VZERKxZs+ZDoTh48OBen+eUU06JU045JT772c/GpEmToq6uLjZv3twjNj/o5ptvjhtuuCH//vtXAAEA+pOiBeCxTJo0KXbv3h27d+/u8SPggwcPxuTJk/PHtLW1xRVXXJF/3ubNm/NvjxkzJmpra2PHjh2xaNGigszr/Tj94I94/1BFRUVUVFQUZDwAgL5S8gBsaGiI+vr6WLRoUaxevTree++9uO6662L27Nkxffr0iIi4/vrr46qrrorp06fHBRdcEOvXr49t27bF+PHj8+dZuXJlLFmyJKqqqqKxsTG6urpiy5Yt8cYbb/S4Snc0bW1t8fzzz8eFF14YJ510UnR0dMSyZcvizDPPPObVPwCAgaLkvwcwl8vF448/HieddFJcdNFF0dDQEOPHj49HH300f8zChQtj2bJlsXTp0pg2bVq8+uqrsXjx4h7nufrqq2Pt2rXx4IMPRn19fcyePTseeuihGDdu3MfO4cQTT4zHHnss5s6dG5/73Oeiqakppk6dGhs3bnSFDwAY8IpyF3AqSnEXUX+9w6uQ53IX8PGdK8JdwO4CLs/1uQu4fMfrLXcBDxzJ/k8gAACpGpAB2NLS0uPXw3zwMW/evL6eHgBAnyr5TSClcO2118aCBQuO+rnhw4eXeDYAAOVlQAZgdXV1VFdX9/U0AADK0oD8ETAAAMcmAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIjAAEAEiMAAQASIwABABIzpK8nwEfLssIc0xfjFepc5bq+Uo9Xjuca6HO3vv49XiHPNdDH661y/L7OJ+MKIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBCAAQGIEIABAYgQgAEBiBGCZy+UKc0whz1Wu4/VGb8cr1Jh9sZ8fd1xv11fIfe+NcnxdlXpOx3Ou3nydSz2nchuvkOca6OP1Vjl+X+eTEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiRGAAACJEYAAAIkRgAAAiek3Adjc3Bxnn312X08DAKDf6zcBWGi33nprzJo1K0488cQYPXp0X08HAKBkkg3Ad955J7785S/H4sWL+3oqAAAlVZQAnDNnTixZsiSWLl0a1dXVMXbs2Ghubs5/fteuXTF//vwYOXJkVFZWxoIFC2Lfvn09znH77bfHmDFjYtSoUdHU1BSHDx/+0Dhr166NSZMmxbBhw2LixIlx33339XqOK1eujG984xtRX1//idcJANAfFe0K4Lp162LEiBHR1tYWd9xxR9xyyy3R2toa3d3dMX/+/Dhw4EBs3LgxWltbY8eOHbFw4cL8czds2BDNzc3R0tISW7ZsiZqamg/F3fr162P58uVx6623Rnt7e7S0tMSyZcti3bp1xVpSdHV1RWdnZ48HAEB/M6RYJ546dWqsWLEiIiLOOuusuOeee+KZZ56JiIiXXnopdu7cGXV1dRER8fDDD8eUKVPi+eefj3PPPTdWr14dTU1N0dTUFBERq1atiqeffrrHVcAVK1bEd7/73fjiF78YERHjxo2L7du3x/333x9XXnllUdZ02223xcqVK4tybgCAUinaFcCpU6f2eL+mpib2798f7e3tUVdXl4+/iIjJkyfH6NGjo729PSIi2tvbY8aMGT2eP3PmzPzbb7/9dnR0dERTU1OMHDky/1i1alV0dHQUa0lx8803x6FDh/KP3bt3F20sAIBiKdoVwKFDh/Z4P5fLRXd3d0HO/dZbb0VExJo1az4UioMHDy7IGEdTUVERFRUVRTs/AEAplPwu4EmTJsXu3bt7XD3bvn17HDx4MCZPnpw/pq2trcfzNm/enH97zJgxUVtbGzt27IgJEyb0eIwbN640CwEA6KeKdgXwWBoaGqK+vj4WLVoUq1evjvfeey+uu+66mD17dkyfPj0iIq6//vq46qqrYvr06XHBBRfE+vXrY9u2bTF+/Pj8eVauXBlLliyJqqqqaGxsjK6urtiyZUu88cYbccMNN3zsPHbt2hUHDhyIXbt2xZEjR2Lr1q0RETFhwoQYOXJkUdYOAFAOSh6AuVwuHn/88fja174WF110UQwaNCgaGxvj7rvvzh+zcOHC6OjoiKVLl8bhw4fjS1/6UixevDieeuqp/DFXX311nHjiiXHnnXfGjTfeGCNGjIj6+vr4+te/3qt5LF++vMcdw+ecc05ERPzwhz+MOXPmFGStAADlKJdlWdbXk+ivOjs7o6qqKg4dOhSVlZVFGSOXi/i4r1Bvjinkucp1vN7o7XgRhRmzL/Yz4qOP6+36CrnvvVGOr6tSz+l4zhXx8V/ncltfOe9n6uP1Vjl+X/8kSvH3d7lL9n8CAQBI1YAMwJaWlh6/HuaDj3nz5vX19AAA+lTJ/w1gKVx77bWxYMGCo35u+PDhJZ4NAEB5GZABWF1dHdXV1X09DQCAsjQgfwQMAMCxCUAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAzp6wnw0bKsMMcU8lzlOl5v9OfxyvHrV0jluA+lnlMhz9Vf51Su5xro4/VWOX5f55NxBRAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxQ/p6Av1ZlmUREdHZ2dnHMwEAeuv9v7ff/3s8RQLwU3jzzTcjIqKurq6PZwIAHK8333wzqqqq+noafSKXpZy/n1J3d3fs2bMnRo0aFblcrmDn7ezsjLq6uti9e3dUVlYW7Lz0ZJ9Lwz6Xjr0uDftcGsXc5yzL4s0334za2toYNCjNfw3nCuCnMGjQoDjttNOKdv7KykrfXErAPpeGfS4de10a9rk0irXPqV75e1+a2QsAkDABCACQGAFYhioqKmLFihVRUVHR11MZ0Oxzadjn0rHXpWGfS8M+F5ebQAAAEuMKIABAYgQgAEBiBCAAQGIEIABAYgRgCdx7773xmc98JoYNGxYzZsyI55577iOP/9d//deYOHFiDBs2LOrr6+PJJ5/s8fksy2L58uVRU1MTw4cPj4aGhvjFL35RzCX0C4Xe58ceeywuueSSOPnkkyOXy8XWrVuLOPv+pZB7/e6778ZNN90U9fX1MWLEiKitrY0rrrgi9uzZU+xllL1Cv6abm5tj4sSJMWLEiDjppJOioaEh2trairmEfqPQe/1B1157beRyuVi9enWBZ93/FHqfr7rqqsjlcj0ejY2NxVzCwJFRVI888kh2wgknZP/8z/+cbdu2Lbvmmmuy0aNHZ/v27Tvq8T/+8Y+zwYMHZ3fccUe2ffv27O///u+zoUOHZi+99FL+mNtvvz2rqqrK/v3f/z373//93+zSSy/Nxo0bl/3ud78r1bLKTjH2+eGHH85WrlyZrVmzJouI7MUXXyzRaspboff64MGDWUNDQ/boo49mP/vZz7JNmzZl5513XjZt2rRSLqvsFOM1vX79+qy1tTXr6OjIXn755aypqSmrrKzM9u/fX6pllaVi7PX7Hnvssezzn/98Vltbm33ve98r8krKWzH2+corr8waGxuzX//61/nHgQMHSrWkfk0AFtl5552X/c3f/E3+/SNHjmS1tbXZbbfddtTjFyxYkP35n/95j4/NmDEj++u//ussy7Ksu7s7Gzt2bHbnnXfmP3/w4MGsoqIi+5d/+ZcirKB/KPQ+f9DOnTsF4AcUc6/f99xzz2URkb366quFmXQ/VIp9PnToUBYR2dNPP12YSfdTxdrrX/3qV9kf//EfZy+//HJ2xhlnJB+AxdjnK6+8Mps/f35R5jvQ+RFwEb3zzjvxwgsvRENDQ/5jgwYNioaGhti0adNRn7Np06Yex0dE/Omf/mn++J07d8bevXt7HFNVVRUzZsw45jkHumLsM0dXqr0+dOhQ5HK5GD16dEHm3d+UYp/feeedeOCBB6Kqqio+//nPF27y/Uyx9rq7uzsuv/zyuPHGG2PKlCnFmXw/UszX9I9+9KM49dRT43Of+1wsXrw4Xn/99cIvYAASgEX0m9/8Jo4cORJjxozp8fExY8bE3r17j/qcvXv3fuTx7/95POcc6IqxzxxdKfb68OHDcdNNN8Vll11WlP8Avj8o5j4/8cQTMXLkyBg2bFh873vfi9bW1jjllFMKu4B+pFh7/Z3vfCeGDBkSS5YsKfyk+6Fi7XNjY2M8/PDD8cwzz8R3vvOd2LhxY8ybNy+OHDlS+EUMMEP6egIA73v33XdjwYIFkWVZ/OM//mNfT2dAuvjii2Pr1q3xm9/8JtasWRMLFiyItra2OPXUU/t6agPGCy+8EP/wD/8Q//M//xO5XK6vpzOgfeUrX8m/XV9fH1OnTo0zzzwzfvSjH8XcuXP7cGblzxXAIjrllFNi8ODBsW/fvh4f37dvX4wdO/aozxk7duxHHv/+n8dzzoGuGPvM0RVzr9+Pv1dffTVaW1uTvfoXUdx9HjFiREyYMCHOP//8+P73vx9DhgyJ73//+4VdQD9SjL1+9tlnY//+/XH66afHkCFDYsiQIfHqq6/G3/3d38VnPvOZoqyj3JXq+/T48ePjlFNOiVdeeeXTT3qAE4BFdMIJJ8S0adPimWeeyX+su7s7nnnmmZg5c+ZRnzNz5swex0dEtLa25o8fN25cjB07tscxnZ2d0dbWdsxzDnTF2GeOrlh7/X78/eIXv4inn346Tj755OIsoJ8o5Wu6u7s7urq6Pv2k+6li7PXll18eP/3pT2Pr1q35R21tbdx4443x1FNPFW8xZaxUr+lf/epX8frrr0dNTU1hJj6Q9fVdKAPdI488klVUVGQPPfRQtn379uyrX/1qNnr06Gzv3r1ZlmXZ5Zdfnn3rW9/KH//jH/84GzJkSHbXXXdl7e3t2YoVK476a2BGjx6dPf7449lPf/rTbP78+X4NTBH2+fXXX89efPHF7Ac/+EEWEdkjjzySvfjii9mvf/3rkq+vnBR6r995553s0ksvzU477bRs69atPX6dQ1dXV5+ssRwUep/feuut7Oabb842bdqU/fKXv8y2bNmS/dVf/VVWUVGRvfzyy32yxnJRjO8ff8hdwIXf5zfffDP75je/mW3atCnbuXNn9vTTT2d/8id/kp111lnZ4cOH+2SN/YkALIG77747O/3007MTTjghO++887LNmzfnPzd79uzsyiuv7HH8hg0bss9+9rPZCSeckE2ZMiX7wQ9+0OPz3d3d2bJly7IxY8ZkFRUV2dy5c7Of//znpVhKWSv0Pj/44INZRHzosWLFihKsprwVcq/f/zU7R3v88Ic/LNGKylMh9/l3v/td9hd/8RdZbW1tdsIJJ2Q1NTXZpZdemj333HOlWk5ZK/T3jz8kAH+vkPv829/+NrvkkkuyP/qjP8qGDh2anXHGGdk111yTD0o+Wi7Lsqxvrj0CANAX/BtAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDECEAAgMQIQACAxAhAAIDE/D/XO5KUeP3l9gAAAABJRU5ErkJggg==", "text/html": [ "\n", "