From 76a873cb0d6e72377a867fd8d16b39644643940c Mon Sep 17 00:00:00 2001 From: Pragyansh Chaturvedi Date: Wed, 22 Oct 2025 21:47:16 +0530 Subject: [PATCH] Update clone-matplotlib example --- examples/clone-matplotlib.ipynb | 312 ++------------------------------ 1 file changed, 20 insertions(+), 292 deletions(-) diff --git a/examples/clone-matplotlib.ipynb b/examples/clone-matplotlib.ipynb index 44115e8..4d4a30a 100644 --- a/examples/clone-matplotlib.ipynb +++ b/examples/clone-matplotlib.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 4, "id": "22dd4e7b-2ea2-49cb-a8d5-1da108c10034", "metadata": {}, "outputs": [], @@ -12,296 +12,16 @@ "from pythonbpf import bpf, map, section, bpfglobal, BPF\n", "from pythonbpf.helper import pid\n", "from pythonbpf.maps import HashMap\n", - "from pylibbpf import BpfMap\n", "from ctypes import c_void_p, c_int64, c_uint64, c_int32\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 5, "id": "ac7a07bf-440f-41e2-bec8-95f520f9cd53", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Module(\n", - " body=[\n", - " FunctionDef(\n", - " name='hist',\n", - " args=arguments(\n", - " posonlyargs=[],\n", - " args=[],\n", - " kwonlyargs=[],\n", - " kw_defaults=[],\n", - " defaults=[]),\n", - " body=[\n", - " Return(\n", - " value=Call(\n", - " func=Name(id='HashMap', ctx=Load()),\n", - " args=[],\n", - " keywords=[\n", - " keyword(\n", - " arg='key',\n", - " value=Name(id='c_int32', ctx=Load())),\n", - " keyword(\n", - " arg='value',\n", - " value=Name(id='c_uint64', ctx=Load())),\n", - " keyword(\n", - " arg='max_entries',\n", - " value=Constant(value=4096))]))],\n", - " decorator_list=[\n", - " Name(id='bpf', ctx=Load()),\n", - " Name(id='map', ctx=Load())],\n", - " returns=Name(id='HashMap', ctx=Load()),\n", - " type_params=[]),\n", - " FunctionDef(\n", - " name='hello',\n", - " args=arguments(\n", - " posonlyargs=[],\n", - " args=[\n", - " arg(\n", - " arg='ctx',\n", - " annotation=Name(id='c_void_p', ctx=Load()))],\n", - " kwonlyargs=[],\n", - " kw_defaults=[],\n", - " defaults=[]),\n", - " body=[\n", - " Assign(\n", - " targets=[\n", - " Name(id='process_id', ctx=Store())],\n", - " value=Call(\n", - " func=Name(id='pid', ctx=Load()),\n", - " args=[],\n", - " keywords=[])),\n", - " Assign(\n", - " targets=[\n", - " Name(id='one', ctx=Store())],\n", - " value=Constant(value=1)),\n", - " Assign(\n", - " targets=[\n", - " Name(id='prev', ctx=Store())],\n", - " value=Call(\n", - " func=Attribute(\n", - " value=Call(\n", - " func=Name(id='hist', ctx=Load()),\n", - " args=[],\n", - " keywords=[]),\n", - " attr='lookup',\n", - " ctx=Load()),\n", - " args=[\n", - " Name(id='process_id', ctx=Load())],\n", - " keywords=[])),\n", - " If(\n", - " test=Name(id='prev', ctx=Load()),\n", - " body=[\n", - " Assign(\n", - " targets=[\n", - " Name(id='previous_value', ctx=Store())],\n", - " value=BinOp(\n", - " left=Name(id='prev', ctx=Load()),\n", - " op=Add(),\n", - " right=Constant(value=1))),\n", - " Expr(\n", - " value=Call(\n", - " func=Name(id='print', ctx=Load()),\n", - " args=[\n", - " JoinedStr(\n", - " values=[\n", - " Constant(value='count: '),\n", - " FormattedValue(\n", - " value=Name(id='previous_value', ctx=Load()),\n", - " conversion=-1),\n", - " Constant(value=' with '),\n", - " FormattedValue(\n", - " value=Name(id='process_id', ctx=Load()),\n", - " conversion=-1)])],\n", - " keywords=[])),\n", - " Expr(\n", - " value=Call(\n", - " func=Attribute(\n", - " value=Call(\n", - " func=Name(id='hist', ctx=Load()),\n", - " args=[],\n", - " keywords=[]),\n", - " attr='update',\n", - " ctx=Load()),\n", - " args=[\n", - " Name(id='process_id', ctx=Load()),\n", - " Name(id='previous_value', ctx=Load())],\n", - " keywords=[])),\n", - " Return(\n", - " value=Call(\n", - " func=Name(id='c_int64', ctx=Load()),\n", - " args=[\n", - " Constant(value=0)],\n", - " keywords=[]))],\n", - " orelse=[\n", - " Expr(\n", - " value=Call(\n", - " func=Attribute(\n", - " value=Call(\n", - " func=Name(id='hist', ctx=Load()),\n", - " args=[],\n", - " keywords=[]),\n", - " attr='update',\n", - " ctx=Load()),\n", - " args=[\n", - " Name(id='process_id', ctx=Load()),\n", - " Name(id='one', ctx=Load())],\n", - " keywords=[]))]),\n", - " Return(\n", - " value=Call(\n", - " func=Name(id='c_int64', ctx=Load()),\n", - " args=[\n", - " Constant(value=0)],\n", - " keywords=[]))],\n", - " decorator_list=[\n", - " Name(id='bpf', ctx=Load()),\n", - " Call(\n", - " func=Name(id='section', ctx=Load()),\n", - " args=[\n", - " Constant(value='tracepoint/syscalls/sys_enter_clone')],\n", - " keywords=[])],\n", - " returns=Name(id='c_int64', ctx=Load()),\n", - " type_params=[]),\n", - " FunctionDef(\n", - " name='LICENSE',\n", - " args=arguments(\n", - " posonlyargs=[],\n", - " args=[],\n", - " kwonlyargs=[],\n", - " kw_defaults=[],\n", - " defaults=[]),\n", - " body=[\n", - " Return(\n", - " value=Constant(value='GPL'))],\n", - " decorator_list=[\n", - " Name(id='bpf', ctx=Load()),\n", - " Name(id='bpfglobal', ctx=Load())],\n", - " returns=Name(id='str', ctx=Load()),\n", - " type_params=[]),\n", - " Assign(\n", - " targets=[\n", - " Name(id='b', ctx=Store())],\n", - " value=Call(\n", - " func=Name(id='BPF', ctx=Load()),\n", - " args=[],\n", - " keywords=[]))],\n", - " type_ignores=[])\n", - "Found BPF function/struct: hist\n", - "Found BPF function/struct: hello\n", - "Found BPF function/struct: LICENSE\n", - "Found BPF map: hist\n", - "Processing BPF map: hist\n", - "Creating HashMap map: hist\n", - "Map parameters: {'type': 'HASH', 'key': 'c_int32', 'value': 'c_uint64', 'max_entries': 4096}\n", - "Created BPF map: hist\n", - "Found probe_string of hello: tracepoint/syscalls/sys_enter_clone\n", - "Pre-allocated variable process_id for helper\n", - "Pre-allocated variable one of type c_int64\n", - "Pre-allocated variable prev for map\n", - "Pre-allocated variable previous_value of type c_int64\n", - "Local symbol table: dict_keys(['process_id', 'one', 'prev', 'previous_value'])\n", - "Processing statement: Assign(targets=[Name(id='process_id', ctx=Store())], value=Call(func=Name(id='pid', ctx=Load()), args=[], keywords=[]))\n", - "Handling assignment to Name(id='process_id', ctx=Store())\n", - "Assignment call type: pid\n", - "Assigned constant pid to process_id\n", - "Processing statement: Assign(targets=[Name(id='one', ctx=Store())], value=Constant(value=1))\n", - "Handling assignment to Name(id='one', ctx=Store())\n", - "Assigned constant 1 to one\n", - "Processing statement: Assign(targets=[Name(id='prev', ctx=Store())], value=Call(func=Attribute(value=Call(func=Name(id='hist', ctx=Load()), args=[], keywords=[]), attr='lookup', ctx=Load()), args=[Name(id='process_id', ctx=Load())], keywords=[]))\n", - "Handling assignment to Name(id='prev', ctx=Store())\n", - "Assignment call attribute: Attribute(value=Call(func=Name(id='hist', ctx=Load()), args=[], keywords=[]), attr='lookup', ctx=Load())\n", - "{}\n", - "Processing statement: If(test=Name(id='prev', ctx=Load()), body=[Assign(targets=[Name(id='previous_value', ctx=Store())], value=BinOp(left=Name(id='prev', ctx=Load()), op=Add(), right=Constant(value=1))), Expr(value=Call(func=Name(id='print', ctx=Load()), args=[JoinedStr(values=[Constant(value='count: '), FormattedValue(value=Name(id='previous_value', ctx=Load()), conversion=-1), Constant(value=' with '), FormattedValue(value=Name(id='process_id', ctx=Load()), conversion=-1)])], keywords=[])), Expr(value=Call(func=Attribute(value=Call(func=Name(id='hist', ctx=Load()), args=[], keywords=[]), attr='update', ctx=Load()), args=[Name(id='process_id', ctx=Load()), Name(id='previous_value', ctx=Load())], keywords=[])), Return(value=Call(func=Name(id='c_int64', ctx=Load()), args=[Constant(value=0)], keywords=[]))], orelse=[Expr(value=Call(func=Attribute(value=Call(func=Name(id='hist', ctx=Load()), args=[], keywords=[]), attr='update', ctx=Load()), args=[Name(id='process_id', ctx=Load()), Name(id='one', ctx=Load())], keywords=[]))])\n", - "Handling if statement\n", - "Processing statement: Assign(targets=[Name(id='previous_value', ctx=Store())], value=BinOp(left=Name(id='prev', ctx=Load()), op=Add(), right=Constant(value=1)))\n", - "Handling assignment to Name(id='previous_value', ctx=Store())\n", - "; ModuleID = \"/tmp/tmp98sm2v54.py\"\n", - "target triple = \"bpf\"\n", - "target datalayout = \"e-m:e-p:64:64-i64:64-i128:128-n32:64-S128\"\n", - "\n", - "@\"hist\" = dso_local global {ptr, ptr, ptr, ptr} zeroinitializer, section \".maps\", align 8, !dbg !22\n", - "define dso_local i64 @\"hello\"(ptr nocapture %\".1\") noinline nounwind optnone section \"tracepoint/syscalls/sys_enter_clone\"\n", - "{\n", - "entry:\n", - " %\"process_id\" = alloca i64, align 8\n", - " %\"one\" = alloca i64, align 8\n", - " %\"prev\" = alloca i64*\n", - " %\"previous_value\" = alloca i64, align 8\n", - " %\".3\" = inttoptr i64 14 to i64 ()*\n", - " %\".4\" = call i64 %\".3\"()\n", - " %\".5\" = and i64 %\".4\", 4294967295\n", - " store i64 %\".5\", i64* %\"process_id\"\n", - " store i64 1, i64* %\"one\"\n", - " %\".8\" = inttoptr i64 1 to ptr (ptr, ptr)*\n", - " %\".9\" = call ptr %\".8\"({ptr, ptr, ptr, ptr}* @\"hist\", i64* %\"process_id\")\n", - " store ptr %\".9\", i64** %\"prev\"\n", - " %\".11\" = load i64*, i64** %\"prev\"\n", - " %\".12\" = icmp ne i64* %\".11\", null\n", - " br i1 %\".12\", label %\"if.then\", label %\"if.else\"\n", - "if.then:\n", - "if.end:\n", - "if.else:\n", - "}\n", - "\n", - "!llvm.dbg.cu = !{ !1 }\n", - "!0 = !DIFile(directory: \"/tmp\", filename: \"/tmp/tmp98sm2v54.py\")\n", - "!1 = distinct !DICompileUnit(emissionKind: 1, file: !0, isOptimized: true, language: 29, nameTableKind: 0, producer: \"PythonBPF DSL Compiler\", runtimeVersion: 0, splitDebugInlining: false)\n", - "!2 = !DIBasicType(encoding: 7, name: \"unsigned int\", size: 32)\n", - "!3 = !DIBasicType(encoding: 7, name: \"unsigned long long\", size: 64)\n", - "!4 = !DISubrange(count: 1)\n", - "!5 = !{ !4 }\n", - "!6 = !DICompositeType(baseType: !2, elements: !5, size: 32, tag: 1)\n", - "!7 = !DIDerivedType(baseType: !6, size: 64, tag: 15)\n", - "!8 = !DIDerivedType(baseType: !2, size: 64, tag: 15)\n", - "!9 = !DIDerivedType(baseType: !3, size: 64, tag: 15)\n", - "!10 = !DIDerivedType(baseType: !7, file: !0, name: \"type\", offset: 0, size: 64, tag: 13)\n", - "!11 = !DIDerivedType(baseType: !8, file: !0, name: \"key\", offset: 64, size: 64, tag: 13)\n", - "!12 = !DIDerivedType(baseType: !9, file: !0, name: \"value\", offset: 128, size: 64, tag: 13)\n", - "!13 = !DISubrange(count: 4096)\n", - "!14 = !{ !13 }\n", - "!15 = !DICompositeType(baseType: !2, elements: !14, size: 32, tag: 1)\n", - "!16 = !DIDerivedType(baseType: !15, size: 64, tag: 15)\n", - "!17 = !DIDerivedType(baseType: !16, file: !0, name: \"max_entries\", offset: 192, size: 64, tag: 13)\n", - "!18 = !{ !10, !11, !12, !17 }\n", - "!19 = distinct !DICompositeType(elements: !18, file: !0, size: 256, tag: 19)\n", - "!20 = distinct !DIGlobalVariable(file: !0, isDefinition: true, isLocal: false, name: \"hist\", scope: !1, type: !19)\n", - "!21 = !DIExpression()\n", - "!22 = !DIGlobalVariableExpression(expr: !21, var: !20)\n", - "left is %\".15\" = load i64, i64* %\".14\", right is i64 1, op is \n", - "Processing statement: Expr(value=Call(func=Name(id='print', ctx=Load()), args=[JoinedStr(values=[Constant(value='count: '), FormattedValue(value=Name(id='previous_value', ctx=Load()), conversion=-1), Constant(value=' with '), FormattedValue(value=Name(id='process_id', ctx=Load()), conversion=-1)])], keywords=[]))\n", - "Handling expression: Expr(value=Call(func=Name(id='print', ctx=Load()), args=[JoinedStr(values=[Constant(value='count: '), FormattedValue(value=Name(id='previous_value', ctx=Load()), conversion=-1), Constant(value=' with '), FormattedValue(value=Name(id='process_id', ctx=Load()), conversion=-1)])], keywords=[]))\n", - "Evaluating expression: Call(func=Name(id='print', ctx=Load()), args=[JoinedStr(values=[Constant(value='count: '), FormattedValue(value=Name(id='previous_value', ctx=Load()), conversion=-1), Constant(value=' with '), FormattedValue(value=Name(id='process_id', ctx=Load()), conversion=-1)])], keywords=[])\n", - "Value in f-string: Constant(value='count: ')\n", - "Value in f-string: FormattedValue(value=Name(id='previous_value', ctx=Load()), conversion=-1)\n", - "Formatted value: FormattedValue(value=Name(id='previous_value', ctx=Load()), conversion=-1)\n", - "Formatted value variable: %\"previous_value\" = alloca i64, align 8 i64\n", - "Value in f-string: Constant(value=' with ')\n", - "Value in f-string: FormattedValue(value=Name(id='process_id', ctx=Load()), conversion=-1)\n", - "Formatted value: FormattedValue(value=Name(id='process_id', ctx=Load()), conversion=-1)\n", - "Formatted value variable: %\"process_id\" = alloca i64, align 8 i64\n", - "Evaluating expression: Name(id='previous_value', ctx=Load())\n", - "Evaluating expression: Name(id='process_id', ctx=Load())\n", - "Processing statement: Expr(value=Call(func=Attribute(value=Call(func=Name(id='hist', ctx=Load()), args=[], keywords=[]), attr='update', ctx=Load()), args=[Name(id='process_id', ctx=Load()), Name(id='previous_value', ctx=Load())], keywords=[]))\n", - "Handling expression: Expr(value=Call(func=Attribute(value=Call(func=Name(id='hist', ctx=Load()), args=[], keywords=[]), attr='update', ctx=Load()), args=[Name(id='process_id', ctx=Load()), Name(id='previous_value', ctx=Load())], keywords=[]))\n", - "Evaluating expression: Call(func=Attribute(value=Call(func=Name(id='hist', ctx=Load()), args=[], keywords=[]), attr='update', ctx=Load()), args=[Name(id='process_id', ctx=Load()), Name(id='previous_value', ctx=Load())], keywords=[])\n", - "Handling method call: Attribute(value=Call(func=Name(id='hist', ctx=Load()), args=[], keywords=[]), attr='update', ctx=Load())\n", - "{}\n", - "Processing statement: Return(value=Call(func=Name(id='c_int64', ctx=Load()), args=[Constant(value=0)], keywords=[]))\n", - "Processing statement: Expr(value=Call(func=Attribute(value=Call(func=Name(id='hist', ctx=Load()), args=[], keywords=[]), attr='update', ctx=Load()), args=[Name(id='process_id', ctx=Load()), Name(id='one', ctx=Load())], keywords=[]))\n", - "Handling expression: Expr(value=Call(func=Attribute(value=Call(func=Name(id='hist', ctx=Load()), args=[], keywords=[]), attr='update', ctx=Load()), args=[Name(id='process_id', ctx=Load()), Name(id='one', ctx=Load())], keywords=[]))\n", - "Evaluating expression: Call(func=Attribute(value=Call(func=Name(id='hist', ctx=Load()), args=[], keywords=[]), attr='update', ctx=Load()), args=[Name(id='process_id', ctx=Load()), Name(id='one', ctx=Load())], keywords=[])\n", - "Handling method call: Attribute(value=Call(func=Name(id='hist', ctx=Load()), args=[], keywords=[]), attr='update', ctx=Load())\n", - "{}\n", - "Processing statement: Return(value=Call(func=Name(id='c_int64', ctx=Load()), args=[Constant(value=0)], keywords=[]))\n", - "IR written to /tmp/tmpx05plfu1.ll\n" - ] - } - ], + "outputs": [], "source": [ "@bpf\n", "@map\n", @@ -314,14 +34,14 @@ "def hello(ctx: c_void_p) -> c_int64:\n", " process_id = pid()\n", " one = 1\n", - " prev = hist().lookup(process_id)\n", + " prev = hist.lookup(process_id)\n", " if prev:\n", " previous_value = prev + 1\n", " print(f\"count: {previous_value} with {process_id}\")\n", - " hist().update(process_id, previous_value)\n", + " hist.update(process_id, previous_value)\n", " return c_int64(0)\n", " else:\n", - " hist().update(process_id, one)\n", + " hist.update(process_id, one)\n", " return c_int64(0)\n", "\n", "\n", @@ -336,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 6, "id": "93fae9f8-464e-48d6-b61e-57b9f93e508a", "metadata": {}, "outputs": [ @@ -349,7 +69,7 @@ }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHHCAYAAABDUnkqAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjYsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvq6yFwwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAOxxJREFUeJzt3XlcFuX+//H3Dcoa4MoiEK64C65FllhipOQR66jZgnuLWpqlHU99XbKi8mhquZxOqXXMPbXSXMg1lTJLTM00V1IBdxBKVJjfH/68T3eAwi1ww/R6Ph7zeJy55rrm/szk8X57zcw9FsMwDAEAAJiEk6MLAAAAKE6EGwAAYCqEGwAAYCqEGwAAYCqEGwAAYCqEGwAAYCqEGwAAYCqEGwAAYCqEGwAAYCqEGwDFwmKxaOzYsdb1OXPmyGKx6OjRo7e87+LcFwDzI9wAZcTu3bv197//XSEhIXJzc1NgYKA6duyod99919GlwQS2bdumsWPH6sKFC44uBShxhBugDNi2bZtatWqlXbt2aeDAgXrvvfc0YMAAOTk5acqUKY4uDyawbds2jRs3jnCDv4QKji4AgPT666/Lx8dH3333nSpVqmSz7dSpU44pCgDKKWZugDLg0KFDaty4cZ5gI0m+vr7W/x0ZGamwsLB891G/fn1FR0db1xcsWKCWLVvKy8tL3t7eatq0aZ5ZoAsXLuj5559XzZo15erqqqCgIMXFxenMmTOSpMuXL2v06NFq2bKlfHx85OnpqXvuuUcbNmwohqP+n59//lk9evRQ9erV5e7urvr16+vll1++6bjp06ercePGcnV1VY0aNTR48OA8MxPt27dXkyZN9NNPP+nee++Vh4eHAgMD9fbbb+fZX3Z2tsaMGaO6devK1dVVwcHBGjlypLKzswt1HN9++606d+6sypUry9PTU82aNctzztevX6977rlHnp6eqlSpkrp27ap9+/bZ9OnTp49q1qyZZ/9jx46VxWKxabNYLBoyZIiWL1+uJk2ayNXVVY0bN9bq1attxo0YMUKSVKtWLVksFpt7mBISEnT33XerUqVKuu2221S/fn3985//LNQxA2URMzdAGRASEqLExETt2bNHTZo0KbDfE088oYEDB+bp99133+nAgQN65ZVXJF37surVq5c6dOigt956S5K0b98+bd26VUOHDpUkZWZm6p577tG+ffvUr18/tWjRQmfOnNHnn3+u48ePq1q1asrIyNAHH3ygXr16aeDAgbp48aI+/PBDRUdHa/v27QoPD7/lY//xxx91zz33qGLFinryySdVs2ZNHTp0SF988YVef/31AseNHTtW48aNU1RUlJ555hnt379fM2bM0HfffaetW7eqYsWK1r7nz5/XAw88oIceekg9evTQkiVL9NJLL6lp06bq1KmTJCk3N1d/+9vftGXLFj355JNq2LChdu/erXfeeUcHDhzQ8uXLb3gcCQkJevDBBxUQEKChQ4fK399f+/bt04oVK6zn/KuvvlKnTp1Uu3ZtjR07Vr///rveffddtW3bVj/88EO+gaYwtmzZoqVLl2rQoEHy8vLS1KlT9fDDDys5OVlVq1bVQw89pAMHDmj+/Pl65513VK1aNUlS9erVtXfvXj344INq1qyZXn31Vbm6uurgwYPaunWrXbUAZYIBwOHWrl1rODs7G87OzkZERIQxcuRIY82aNcbly5dt+l24cMFwc3MzXnrpJZv25557zvD09DQyMzMNwzCMoUOHGt7e3sbVq1cL/MzRo0cbkoylS5fm2Zabm2sYhmFcvXrVyM7Ottl2/vx5w8/Pz+jXr59NuyRjzJgx1vXZs2cbkowjR47c8NjbtWtneHl5GceOHcu3hvz2derUKcPFxcW4//77jZycHGu/9957z5BkzJo1y9oWGRlpSDI+/vhja1t2drbh7+9vPPzww9a2//73v4aTk5Px9ddf29Qxc+ZMQ5KxdevWAo/h6tWrRq1atYyQkBDj/PnzBR5HeHi44evra5w9e9batmvXLsPJycmIi4uztvXu3dsICQnJ8zljxowx/vzXtiTDxcXFOHjwoM0+JRnvvvuutW3ChAn5/vd45513DEnG6dOnCzw+oLzhshRQBnTs2FGJiYn629/+pl27duntt99WdHS0AgMD9fnnn1v7+fj4qGvXrpo/f74Mw5Ak5eTkaOHChYqNjZWnp6ckqVKlSsrKylJCQkKBn/npp58qLCxM3bp1y7Pt+qUPZ2dnubi4SLo2s3Hu3DldvXpVrVq10g8//HDLx3369Glt3rxZ/fr10+23355vDfn56quvdPnyZQ0bNkxOTv/7a2zgwIHy9vbWypUrbfrfdtttevzxx63rLi4uatOmjQ4fPmxtW7x4sRo2bKgGDRrozJkz1uW+++6TpBteitu5c6eOHDmiYcOG5bm0eP04UlJSlJSUpD59+qhKlSrW7c2aNVPHjh315ZdfFrj/m4mKilKdOnVs9unt7W1zfAW5Xu9nn32m3Nxcu2sAyhLCDVBGtG7dWkuXLtX58+e1fft2jRo1ShcvXtTf//53/fTTT9Z+cXFxSk5O1tdffy3p2hd9WlqannjiCWufQYMGKTQ0VJ06dVJQUJD69etncw+GdO0+nxtdArvuo48+UrNmzeTm5qaqVauqevXqWrlypdLT02/5mK9/+Ramjj86duyYpGv3Gf2Ri4uLateubd1+XVBQUJ6wVLlyZZ0/f966/ssvv2jv3r2qXr26zRIaGirpxjd2Hzp06KbHUVDNktSwYUOdOXNGWVlZBY6/kT8HQynv8RWkZ8+eatu2rQYMGCA/Pz898sgjWrRoEUEH5Rr33ABljIuLi1q3bq3WrVsrNDRUffv21eLFizVmzBhJUnR0tPz8/DR37ly1a9dOc+fOlb+/v6Kioqz78PX1VVJSktasWaNVq1Zp1apVmj17tuLi4vTRRx8Vupa5c+eqT58+io2N1YgRI+Tr6ytnZ2fFx8dbv9DLA2dn53zbr89+Sddmppo2bapJkybl2zc4OLhEastPQbNWOTk5+bYX5vgK4u7urs2bN2vDhg1auXKlVq9erYULF+q+++7T2rVrC9w3UJYxcwOUYa1atZJ07ZLGdc7Oznr00Ue1ZMkSnT9/XsuXL1evXr3yfAm5uLioS5cumj59ug4dOqSnnnpKH3/8sQ4ePChJqlOnjvbs2XPDz1+yZIlq166tpUuX6oknnlB0dLSioqJ06dKlYjm+2rVrS9JN6/izkJAQSdL+/ftt2i9fvqwjR45YtxdFnTp1dO7cOXXo0EFRUVF5lvxmXP44VrrxcRRUs3TtabFq1apZLytWrlw539+j+fOMVFHc6DKfk5OTOnTooEmTJumnn37S66+/rvXr1xf7U3FAaSHcAGXAhg0b8v1X9vX7MP78xfrEE0/o/Pnzeuqpp5SZmWlzP4kknT171mbdyclJzZo1kyTrY80PP/ywdu3apWXLluX53Ou1XA9Mf6zt22+/VWJiYpGOryDVq1dXu3btNGvWLCUnJ+dbQ36ioqLk4uKiqVOn2vT78MMPlZ6erpiYmCLX0qNHD504cUL/+c9/8mz7/fffb3jJqEWLFqpVq5YmT56cJ5Rcry8gIEDh4eH66KOPbPrs2bNHa9euVefOna1tderUUXp6un788UdrW0pKSr7/rQrrenD6c33nzp3L0/f6U3CFfQQeKGu4LAWUAc8++6x+++03devWTQ0aNNDly5e1bds2LVy4UDVr1lTfvn1t+jdv3lxNmjSx3gTbokULm+0DBgzQuXPndN999ykoKEjHjh3Tu+++q/DwcDVs2FCSNGLECC1ZskTdu3dXv3791LJlS507d06ff/65Zs6cqbCwMD344INaunSpunXrppiYGB05ckQzZ85Uo0aNlJmZWSzHPnXqVN19991q0aKFnnzySdWqVUtHjx7VypUrlZSUlO+Y6tWra9SoURo3bpweeOAB/e1vf9P+/fs1ffp0tW7dOk/YK4wnnnhCixYt0tNPP60NGzaobdu2ysnJ0c8//6xFixZpzZo11pm0P3NyctKMGTPUpUsXhYeHq2/fvgoICNDPP/+svXv3as2aNZKkCRMmqFOnToqIiFD//v2tj4L7+PjYvJfrkUce0UsvvaRu3brpueee02+//aYZM2YoNDTU7hu5W7ZsKUl6+eWX9cgjj6hixYrq0qWLXn31VW3evFkxMTEKCQnRqVOnNH36dAUFBenuu++267MAh3PYc1oArFatWmX069fPaNCggXHbbbcZLi4uRt26dY1nn33WSEtLy3fM22+/bUgy3njjjTzblixZYtx///2Gr6+v4eLiYtx+++3GU089ZaSkpNj0O3v2rDFkyBAjMDDQcHFxMYKCgozevXsbZ86cMQzj2mPMb7zxhhESEmK4uroazZs3N1asWJHvo8qy81FwwzCMPXv2GN26dTMqVapkuLm5GfXr1zf+7//+76b7eu+994wGDRoYFStWNPz8/Ixnnnkmz6PYkZGRRuPGjfN8Zn7HcPnyZeOtt94yGjdubLi6uhqVK1c2WrZsaYwbN85IT0+/6XFs2bLF6Nixo+Hl5WV4enoazZo1s3kc2zAM46uvvjLatm1ruLu7G97e3kaXLl2Mn376Kc++1q5dazRp0sRwcXEx6tevb8ydO7fAR8EHDx6cZ3xISIjRu3dvm7bx48cbgYGBhpOTk/V8rlu3zujatatRo0YNw8XFxahRo4bRq1cv48CBAzc9XqCsshhGIe44A1DmTJkyRc8//7yOHj2a79MyAPBXRbgByiHDMBQWFqaqVaty0ycA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AABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMhXADAABMxaHhJj4+Xq1bt5aXl5d8fX0VGxur/fv333Tc4sWL1aBBA7m5ualp06b68ssvS6FaAABQHjg03GzatEmDBw/WN998o4SEBF25ckX333+/srKyChyzbds29erVS/3799fOnTsVGxur2NhY7dmzpxQrBwAAZZXFMAzD0UVcd/r0afn6+mrTpk1q165dvn169uyprKwsrVixwtp25513Kjw8XDNnzrzpZ2RkZMjHx0fp6eny9vYuttoBACgJNf+x0tElFNnRN2OKfZ9F+f4uU/fcpKenS5KqVKlSYJ/ExERFRUXZtEVHRysxMTHf/tnZ2crIyLBZAACAeVVwdAHX5ebmatiwYWrbtq2aNGlSYL/U1FT5+fnZtPn5+Sk1NTXf/vHx8Ro3blyx1nojJGwAAByrzMzcDB48WHv27NGCBQuKdb+jRo1Senq6dfn111+Ldf8AAKBsKRMzN0OGDNGKFSu0efNmBQUF3bCvv7+/0tLSbNrS0tLk7++fb39XV1e5uroWW60AAKBsc+jMjWEYGjJkiJYtW6b169erVq1aNx0TERGhdevW2bQlJCQoIiKipMoEAADliENnbgYPHqx58+bps88+k5eXl/W+GR8fH7m7u0uS4uLiFBgYqPj4eEnS0KFDFRkZqYkTJyomJkYLFizQjh079P777zvsOAAAQNnh0JmbGTNmKD09Xe3bt1dAQIB1WbhwobVPcnKyUlJSrOt33XWX5s2bp/fff19hYWFasmSJli9ffsObkAEAwF+HQ2duCvMTOxs3bszT1r17d3Xv3r0EKgIAAOVdmXlaCgAAoDgQbgAAgKkQbgAAgKkQbgAAgKkQbgAAgKkQbgAAgKkQbgAAgKkQbgAAgKkQbgAAgKkQbgAAgKnYFW4OHz5c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AKWpgiM/vFq1anJ2dlZaWppNe1pamvz9/Qu1j4oVK6p58+Y6ePBgvttdXV3l6up6y7UCAIDywaEzNy4uLmrZsqXWrVtnbcvNzdW6desUERFRqH3k5ORo9+7dCggIKKkyAQBAOeLQmRtJGj58uHr37q1WrVqpTZs2mjx5srKystS3b19JUlxcnAIDAxUfHy9JevXVV3XnnXeqbt26unDhgiZMmKBjx45pwIABjjwMAABQRjg83PTs2VOnT5/W6NGjlZqaqvDwcK1evdp6k3FycrKcnP43wXT+/HkNHDhQqampqly5slq2bKlt27apUaNGjjoEAABQhlgMwzAcXURpysjIkI+Pj9LT0+Xt7V3s+6/5j5XFvs+SdvTNGEeXAAAoAN8r1xTl+7vcPS0FAABwI4QbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKoQbAABgKmUi3EybNk01a9aUm5ub7rjjDm3fvv2G/RcvXqwGDRrIzc1NTZs21ZdffllKlQIAgLLO4eFm4cKFGj58uMaMGaMffvhBYWFhio6O1qlTp/Ltv23bNvXq1Uv9+/fXzp07FRsbq9jYWO3Zs6eUKwcAAGWRw8PNpEmTNHDgQPXt21eNGjXSzJkz5eHhoVmzZuXbf8qUKXrggQc0YsQINWzYUOPHj1eLFi303nvvlXLlAACgLHJouLl8+bK+//57RUVFWducnJwUFRWlxMTEfMckJiba9Jek6OjoAvsDAIC/lgqO/PAzZ84oJydHfn5+Nu1+fn76+eef8x2Tmpqab//U1NR8+2dnZys7O9u6np6eLknKyMi4ldILlJv9W4nstySV1LkAANw6vlds92kYxk37OjTclIb4+HiNGzcuT3twcLADqimbfCY7ugIAgJmU5PfKxYsX5ePjc8M+Dg031apVk7Ozs9LS0mza09LS5O/vn+8Yf3//IvUfNWqUhg8fbl3Pzc3VuXPnVLVqVVkslls8AlsZGRkKDg7Wr7/+Km9v72LdN/6H81w6OM+lg/NcejjXpaOkzrNhGLp48aJq1Khx074ODTcuLi5q2bKl1q1bp9jYWEnXwse6des0ZMiQfMdERERo3bp1GjZsmLUtISFBERER+fZ3dXWVq6urTVulSpWKo/wCeXt783+cUsB5Lh2c59LBeS49nOvSURLn+WYzNtc5/LLU8OHD1bt3b7Vq1Upt2rTR5MmTlZWVpb59+0qS4uLiFBgYqPj4eEnS0KFDFRkZqYkTJyomJkYLFizQjh079P777zvyMAAAQBnh8HDTs2dPnT59WqNHj1ZqaqrCw8O1evVq603DycnJcnL630Ndd911l+bNm6dXXnlF//znP1WvXj0tX75cTZo0cdQhAACAMsTh4UaShgwZUuBlqI0bN+Zp6969u7p3717CVRWdq6urxowZk+cyGIoX57l0cJ5LB+e59HCuS0dZOM8WozDPVAEAAJQTDv+FYgAAgOJEuAEAAKZCuAEAAKZCuAEAAKZCuCmkzZs3q0uXLqpRo4YsFouWL19+0zEbN25UixYt5Orqqrp162rOnDklXqcZFPVcL126VB07dlT16tXl7e2tiIgIrVmzpnSKLcfs+TN93datW1WhQgWFh4eXWH1mYc95zs7O1ssvv6yQkBC5urqqZs2amjVrVskXW47Zc54/+eQThYWFycPDQwEBAerXr5/Onj1b8sWWY/Hx8WrdurW8vLzk6+ur2NhY7d+//6bjFi9erAYNGsjNzU1NmzbVl19+WaJ1Em4KKSsrS2FhYZo2bVqh+h85ckQxMTG69957lZSUpGHDhmnAgAF86RZCUc/15s2b1bFjR3355Zf6/vvvde+996pLly7auXNnCVdavhX1PF934cIFxcXFqUOHDiVUmbnYc5579OihdevW6cMPP9T+/fs1f/581a9fvwSrLP+Kep63bt2quLg49e/fX3v37tXixYu1fft2DRw4sIQrLd82bdqkwYMH65tvvlFCQoKuXLmi+++/X1lZWQWO2bZtm3r16qX+/ftr586dio2NVWxsrPbs2VNyhRooMknGsmXLbthn5MiRRuPGjW3aevbsaURHR5dgZeZTmHOdn0aNGhnjxo0r/oJMqijnuWfPnsYrr7xijBkzxggLCyvRusymMOd51apVho+Pj3H27NnSKcqECnOeJ0yYYNSuXdumberUqUZgYGAJVmY+p06dMiQZmzZtKrBPjx49jJiYGJu2O+64w3jqqadKrC5mbkpIYmKioqKibNqio6OVmJjooIr+OnJzc3Xx4kVVqVLF0aWYzuzZs3X48GGNGTPG0aWY1ueff65WrVrp7bffVmBgoEJDQ/Xiiy/q999/d3RpphIREaFff/1VX375pQzDUFpampYsWaLOnTs7urRyJT09XZJu+PetI74Py8QvFJtRamqq9RUS1/n5+SkjI0O///673N3dHVSZ+f3rX/9SZmamevTo4ehSTOWXX37RP/7xD3399deqUIG/OkrK4cOHtWXLFrm5uWnZsmU6c+aMBg0apLNnz2r27NmOLs802rZtq08++UQ9e/bUpUuXdPXqVXXp0qXIl2n/ynJzczVs2DC1bdv2hq9AKuj7MDU1tcRqY+YGpjJv3jyNGzdOixYtkq+vr6PLMY2cnBw9+uijGjdunEJDQx1djqnl5ubKYrHok08+UZs2bdS5c2dNmjRJH330EbM3xeinn37S0KFDNXr0aH3//fdavXq1jh49qqefftrRpZUbgwcP1p49e7RgwQJHl5IH//wqIf7+/kpLS7NpS0tLk7e3N7M2JWTBggUaMGCAFi9enGcKFLfm4sWL2rFjh3bu3Gl9D1xubq4Mw1CFChW0du1a3XfffQ6u0hwCAgIUGBgoHx8fa1vDhg1lGIaOHz+uevXqObA684iPj1fbtm01YsQISVKzZs3k6empe+65R6+99poCAgIcXGHZNmTIEK1YsUKbN29WUFDQDfsW9H3o7+9fYvUxc1NCIiIitG7dOpu2hIQERUREOKgic5s/f7769u2r+fPnKyYmxtHlmI63t7d2796tpKQk6/L000+rfv36SkpK0h133OHoEk2jbdu2OnnypDIzM61tBw4ckJOT002/RFB4v/32m5ycbL8CnZ2dJUkGr1wskGEYGjJkiJYtW6b169erVq1aNx3jiO9DZm4KKTMzUwcPHrSuHzlyRElJSapSpYpuv/12jRo1SidOnNDHH38sSXr66af13nvvaeTIkerXr5/Wr1+vRYsWaeXKlY46hHKjqOd63rx56t27t6ZMmaI7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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHHCAYAAABDUnkqAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQAAOrxJREFUeJzt3XlYVdX+x/HPAeWABmgqg0o4jygoDqGVqRipedW6Zlaipjaopdmk1S+1icqr2eBwu5XW9ZpTZuVMDllKmQOm5pAjmYCaCkIJCuv3h4/n3hOgcEQO7N6v59nP89trr7XPd29uns9v77XPthljjAAAACzCw90FAAAAFCfCDQAAsBTCDQAAsBTCDQAAsBTCDQAAsBTCDQAAsBTCDQAAsBTCDQAAsBTCDQAAsBTCDYBiYbPZNH78eMf6rFmzZLPZdPjw4aved3HuC4D1EW6AUmLHjh36+9//rtDQUHl7e6tGjRrq0qWL3nnnHXeXBgvYuHGjxo8frzNnzri7FOCaI9wApcDGjRvVqlUrbd++XUOHDtW7776rIUOGyMPDQ2+99Za7y4MFbNy4URMmTCDc4C+hnLsLACC98sor8vf31w8//KBKlSo5bTt+/Lh7igKAMoorN0ApcODAATVt2jRPsJGkgIAAx//doUMHhYeH57uPhg0bKiYmxrE+d+5cRUZGytfXV35+fmrWrFmeq0BnzpzR448/rlq1aslut6tmzZqKjY3VyZMnJUnZ2dl64YUXFBkZKX9/f1WsWFE333yz1q5dWwxH/V979uzR3XffrWrVqsnHx0cNGzbUc889d8Vx06ZNU9OmTWW321W9enUNHz48z5WJW2+9VWFhYfrpp5/UsWNHVahQQTVq1NAbb7yRZ39ZWVkaN26c6tWrJ7vdrpCQED399NPKysoq1HF8//336tatmypXrqyKFSuqefPmec75mjVrdPPNN6tixYqqVKmSevbsqd27dzv1GThwoGrVqpVn/+PHj5fNZnNqs9lsGjFihBYvXqywsDDZ7XY1bdpUK1ascBr31FNPSZJq164tm83mNIcpPj5eN910kypVqqTrrrtODRs21LPPPluoYwZKI67cAKVAaGioEhIStHPnToWFhRXYr3///ho6dGiefj/88IP27dun559/XtLFL6t+/fqpc+fOev311yVJu3fv1oYNGzRy5EhJUkZGhm6++Wbt3r1bDzzwgFq2bKmTJ0/qiy++0NGjR1W1alWlp6fr/fffV79+/TR06FCdPXtWH3zwgWJiYrRp0yZFRERc9bH/+OOPuvnmm1W+fHk9+OCDqlWrlg4cOKAvv/xSr7zySoHjxo8frwkTJig6OlqPPPKI9u7dq+nTp+uHH37Qhg0bVL58eUff06dP6/bbb9edd96pu+++WwsXLtQzzzyjZs2aqWvXrpKk3Nxc/e1vf9O3336rBx98UI0bN9aOHTv05ptvat++fVq8ePFljyM+Pl533HGHgoODNXLkSAUFBWn37t1asmSJ45x/9dVX6tq1q+rUqaPx48frjz/+0DvvvKP27dtr69at+Qaawvj222+1aNEiDRs2TL6+vnr77bd11113KSkpSVWqVNGdd96pffv26ZNPPtGbb76pqlWrSpKqVaumXbt26Y477lDz5s314osvym63a//+/dqwYYNLtQClggHgdqtWrTKenp7G09PTREVFmaefftqsXLnSZGdnO/U7c+aM8fb2Ns8884xT+2OPPWYqVqxoMjIyjDHGjBw50vj5+ZkLFy4U+JkvvPCCkWQWLVqUZ1tubq4xxpgLFy6YrKwsp22nT582gYGB5oEHHnBql2TGjRvnWJ85c6aRZA4dOnTZY7/llluMr6+vOXLkSL415Lev48ePGy8vL3PbbbeZnJwcR793333XSDIffviho61Dhw5Gkvn4448dbVlZWSYoKMjcddddjrZ///vfxsPDw3zzzTdOdcyYMcNIMhs2bCjwGC5cuGBq165tQkNDzenTpws8joiICBMQEGB+++03R9v27duNh4eHiY2NdbQNGDDAhIaG5vmccePGmT//sy3JeHl5mf379zvtU5J55513HG0TJ07M9+/x5ptvGknmxIkTBR4fUNZwWwooBbp06aKEhAT97W9/0/bt2/XGG28oJiZGNWrU0BdffOHo5+/vr549e+qTTz6RMUaSlJOTo3nz5qlXr16qWLGiJKlSpUrKzMxUfHx8gZ/56aefKjw8XL17986z7dKtD09PT3l5eUm6eGXj1KlTunDhglq1aqWtW7de9XGfOHFC69ev1wMPPKAbbrgh3xry89VXXyk7O1ujRo2Sh8d//xkbOnSo/Pz8tHTpUqf+1113ne6//37HupeXl9q0aaODBw862hYsWKDGjRurUaNGOnnypGPp1KmTJF32Vty2bdt06NAhjRo1Ks+txUvHkZycrMTERA0cOFDXX3+9Y3vz5s3VpUsXLVu2rMD9X0l0dLTq1q3rtE8/Pz+n4yvIpXo///xz5ebmulwDUJoQboBSonXr1lq0aJFOnz6tTZs2aezYsTp79qz+/ve/66effnL0i42NVVJSkr755htJF7/oU1NT1b9/f0efYcOGqUGDBuratatq1qypBx54wGkOhnRxns/lboFd8tFHH6l58+by9vZWlSpVVK1aNS1dulRpaWlXfcyXvnwLU8f/OnLkiKSL84z+l5eXl+rUqePYfknNmjXzhKXKlSvr9OnTjvWff/5Zu3btUrVq1ZyWBg0aSLr8xO4DBw5c8TgKqlmSGjdurJMnTyozM7PA8Zfz52Ao5T2+gvTt21ft27fXkCFDFBgYqHvuuUfz588n6KBMY84NUMp4eXmpdevWat26tRo0aKBBgwZpwYIFGjdunCQpJiZGgYGBmj17tm655RbNnj1bQUFBio6OduwjICBAiYmJWrlypZYvX67ly5dr5syZio2N1UcffVToWmbPnq2BAweqV69eeuqppxQQECBPT0/FxcU5vtDLAk9Pz3zbL139ki5emWrWrJkmT56cb9+QkJBrUlt+CrpqlZOTk297YY6vID4+Plq/fr3Wrl2rpUuXasWKFZo3b546deqkVatWFbhvoDTjyg1QirVq1UrSxVsal3h6euree+/VwoULdfr0aS1evFj9+vXL8yXk5eWlHj16aNq0aTpw4IAeeughffzxx9q/f78kqW7dutq5c+dlP3/hwoWqU6eOFi1apP79+ysmJkbR0dE6d+5csRxfnTp1JOmKdfxZaGioJGnv3r1O7dnZ2Tp06JBje1HUrVtXp06dUufOnRUdHZ1nye+Ky/+OlS5/HAXVLF18Wqxq1aqO24qVK1fO9/do/nxFqigud5vPw8NDnTt31uTJk/XTTz/plVde0Zo1a4r9qTigpBBugFJg7dq1+f5/2ZfmYfz5i7V///46ffq0HnroIWVkZDjNJ5Gk3377zWndw8NDzZs3lyTHY8133XWXtm/frs8++yzP516q5VJg+t/avv/+eyUkJBTp+ApSrVo13XLLLfrwww+VlJSUbw35iY6OlpeXl95++22nfh988IHS0tLUvXv3Itdy991369dff9W//vWvPNv++OOPy94yatmypWrXrq0pU6bkCSWX6gsODlZERIQ++ugjpz47d+7UqlWr1K1bN0db3bp1lZaWph9//NHRlpycnO/fqrAuBac/13fq1Kk8fS89BVfYR+CB0obbUkAp8Oijj+r3339X79691ahRI2VnZ2vjxo2aN2+eatWqpUGDBjn1b9GihcLCwhyTYFu2bOm0fciQITp16pQ6deqkmjVr6siRI3rnnXcUERGhxo0bS5KeeuopLVy4UH369NEDDzygyMhInTp1Sl988YVmzJih8PBw3XHHHVq0aJF69+6t7t2769ChQ5oxY4aaNGmijIyMYjn2t99+WzfddJNatmypBx98ULVr19bhw4e1dOlSJSYm5jumWrVqGjt2rCZMmKDbb79df/vb37R3715NmzZNrVu3zhP2CqN///6aP3++Hn74Ya1du1bt27dXTk6O9uzZo/nz52vlypWOK2l/5uHhoenTp6tHjx6KiIjQoEGDFBwcrD179mjXrl1auXKlJGnixInq2rWroqKiNHjwYMej4P7+/k7v5brnnnv0zDPPqHfv3nrsscf0+++/a/r06WrQoIHLE7kjIyMlSc8995zuuecelS9fXj169NCLL76o9evXq3v37goNDdXx48c1bdo01axZUzfddJNLnwW4ndue0wLgsHz5cvPAAw+YRo0ameuuu854eXmZevXqmUcffdSkpqbmO+aNN94wksyrr76aZ9vChQvNbbfdZgICAoyXl5e54YYbzEMPPWSSk5Od+v32229mxIgRpkaNGsbLy8vUrFnTDBgwwJw8edIYc/Ex5ldffdWEhoYau91uWrRoYZYsWZLvo8py8VFwY4zZuXOn6d27t6lUqZLx9vY2DRs2NP/3f/93xX29++67plGjRqZ8+fImMDDQPPLII3kexe7QoYNp2rRpns/M7xiys7PN66+/bpo2bWrsdrupXLmyiYyMNBMmTDBpaWlXPI5vv/3WdOnSxfj6+pqKFSua5s2bOz2ObYwxX331lWnfvr3x8fExfn5+pkePHuann37Ks69Vq1aZsLAw4+XlZRo2bGhmz55d4KPgw4cPzzM+NDTUDBgwwKntpZdeMjVq1DAeHh6O87l69WrTs2dPU716dePl5WWqV69u+vXrZ/bt23fF4wVKK5sxhZhxBqDUeeutt/T444/r8OHD+T4tAwB/VYQboAwyxig8PFxVqlRh0icA/Alz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AACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACW4tZwExcXp9atW8vX11cBAQHq1auX9u7de8VxCxYsUKNGjeTt7a1mzZpp2bJlJVAtAAAoC9wabr7++msNHz5c3333neLj43X+/HnddtttyszMLHDMxo0b1a9fPw0ePFjbtm1Tr1691KtXL+3cubMEKwcAAKWVzRhj3F3EJSdOnFBAQIC+/vpr3XLLLfn26du3rzIzM7VkyRJH24033qiIiAjNmDHjip+Rnp4uf39/paWlyc/Pr9hqB1A61Bqz1N0lFNnh17q7uwSg1CvK93epmnOTlpYmSbr++usL7JOQkKDo6GintpiYGCUkJOTbPysrS+np6U4LAACwrlITbnJzczVq1Ci1b99eYWFhBfZLSUlRYGCgU1tgYKBSUlLy7R8XFyd/f3/HEhISUqx1AwCA0qXUhJvhw4dr586dmjt3brHud+zYsUpLS3Msv/zyS7HuHwAAlC7l3F2AJI0YMUJLlizR+vXrVbNmzcv2DQoKUmpqqlNbamqqgoKC8u1vt9tlt9uLrVYAAFC6ufXKjTFGI0aM0GeffaY1a9aodu3aVxwTFRWl1atXO7XFx8crKirqWpUJAADKELdeuRk+fLjmzJmjzz//XL6+vo55M/7+/vLx8ZEkxcbGqkaNGoqLi5MkjRw5Uh06dNCkSZPUvXt3zZ07V5s3b9Z7773ntuMAAAClh1uv3EyfPl1paWm69dZbFRwc7FjmzZvn6JOUlKTk5GTHert27TRnzhy99957Cg8P18KFC7V48eLLTkIGAAB/HW69clOYn9hZt25dnrY+ffqoT58+16AiAABQ1pWap6UAAACKA+EGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYikvh5uDBg8VdBwAAQLFwKdzUq1dPHTt21OzZs3Xu3LnirgkAAMBlLoWbrVu3qnnz5ho9erSCgoL00EMPadOmTcVdGwAAQJG5FG4iIiL01ltv6dixY/rwww+VnJysm266SWFhYZo8ebJOnDhR3HUCAAAUylVNKC5XrpzuvPNOLViwQK+//rr279+vJ598UiEhIYqNjVVycnJx1QkAAFAoVxVuNm/erGHDhik4OFiTJ0/Wk08+qQMHDig+Pl7Hjh1Tz549i6tOAACAQinnyqDJkydr5syZ2rt3r7p166aPP/5Y3bp1k4fHxaxUu3ZtzZo1S7Vq1SrOWgEAAK7IpXAzffp0PfDAAxo4cKCCg4Pz7RMQEKAPPvjgqooDAAAoKpfCzc8//3zFPl5eXhowYIAruwcAAHCZS3NuZs6cqQULFuRpX7BggT766KOrLgoAAMBVLoWbuLg4Va1aNU97QECAXn311asuCgAAwFUuhZukpCTVrl07T3toaKiSkpKuuigAAABXuRRuAgIC9OOPP+Zp3759u6pUqXLVRQEAALjKpXDTr18/PfbYY1q7dq1ycnKUk5OjNWvWaOTIkbrnnnuKu0YAAIBCc+lpqZdeekmHDx9W586dVa7cxV3k5uYqNjaWOTcAAMCtXAo3Xl5emjdvnl566SVt375dPj4+atasmUJDQ4u7PgAAgCJxKdxc0qBBAzVo0KC4agEAALhqLoWbnJwczZo1S6tXr9bx48eVm5vrtH3NmjXFUhwAAEBRuRRuRo4cqVmzZql79+4KCwuTzWYr7roAAABc4lK4mTt3rubPn69u3boVdz0AAABXxaVHwb28vFSvXr3irgUAAOCquRRunnjiCb311lsyxhR3PQAAAFfFpdtS3377rdauXavly5eradOmKl++vNP2RYsWFUtxAAAAReVSuKlUqZJ69+5d3LUAAABcNZfCzcyZM4u7DgAAgGLh0pwbSbpw4YK++uor/fOf/9TZs2clSceOHVNGRkaxFQcAAFBULl25OXLkiG6//XYlJSUpKytLXbp0ka+vr15//XVlZWVpxowZxV0nAABAobh05WbkyJFq1aqVTp8+LR8fH0d77969tXr16mIrDgAAoKhcunLzzTffaOPGjfLy8nJqr1Wrln799ddiKQwAAMAVLl25yc3NVU5OTp72o0ePytfX96qLAgAAcJVL4ea2227TlClTHOs2m00ZGRkaN24cr2QAAABu5dJtqUmTJikmJkZNmjTRuXPndO+99+rnn39W1apV9cknnxR3jQAAAIXmUripWbOmtm/frrlz5+rHH39URkaGBg8erPvuu89pgjEAAEBJcyncSFK5cuV0//33F2ctAAAAV82lcPPxxx9fdntsbKxLxQAAAFwtl8LNyJEjndbPnz+v33//XV5eXqpQoQLhBgAAuI1LT0udPn3aacnIyNDevXt10003MaEYAAC4lcvvlvqz+vXr67XXXstzVedy1q9frx49eqh69eqy2WxavHjxZfuvW7dONpstz5KSknKV1QMAAKsotnAjXZxkfOzYsUL3z8zMVHh4uKZOnVqkz9m7d6+Sk5MdS0BAQFFLBQAAFuXSnJsvvvjCad0Yo+TkZL377rtq3759offTtWtXde3atcifHxAQoEqVKhV5HAAAsD6Xwk2vXr2c1m02m6pVq6ZOnTpp0qRJxVHXZUVERCgrK0thYWEaP358kQIVAACwNpfCTW5ubnHXUSjBwcGaMWOGWrVqpaysLL3//vu69dZb9f3336tly5b5jsnKylJWVpZjPT09vaTKBQAAbuDyj/i5Q8OGDdWwYUPHert27XTgwAG9+eab+ve//53vmLi4OE2YMKGkSgQAAG7mUrgZPXp0oftOnjzZlY8otDZt2ujbb78tcPvYsWOd6k1PT1dISMg1rQkAALiPS+Fm27Zt2rZtm86fP++4krJv3z55eno63R6y2WzFU+VlJCYmKjg4uMDtdrtddrv9mtcBAABKB5fCTY8ePeTr66uPPvpIlStXlnTxh/0GDRqkm2++WU888USh9pORkaH9+/c71g8dOqTExERdf/31uuGGGzR27Fj9+uuvjtc9TJkyRbVr11bTpk117tw5vf/++1qzZo1WrVrlymEAAAALcincTJo0SatWrXIEG0mqXLmyXn75Zd12222FDjebN29Wx44dHeuXbh8NGDBAs2bNUnJyspKSkhzbs7Oz9cQTT+jXX39VhQoV1Lx5c3311VdO+wAAAH9tLoWb9PR0nThxIk/7iRMndPbs2ULv59Zbb5UxpsDts2bNclp/+umn9fTTTxd6/wAA4K/HpV8o7t27twYNGqRFixbp6NGjOnr0qD799FMNHjxYd955Z3HXCAAAUGguXbmZMWOGnnzySd177706f/78xR2VK6fBgwdr4sSJxVogAABAUbgUbipUqKBp06Zp4sSJOnDggCSpbt26qlixYrEWBwAAUFRX9eLMSy+urF+/vipWrHjZ+TMAAAAlwaVw89tvv6lz585q0KCBunXrpuTkZEnS4MGDC/2kFAAAwLXgUrh5/PHHVb58eSUlJalChQqO9r59+2rFihXFVhwAAEBRuTTnZtWqVVq5cqVq1qzp1F6/fn0dOXKkWAoDAABwhUtXbjIzM52u2Fxy6tQpXnUAAADcyqVwc/PNNzteiSBdfIdUbm6u3njjDX4tGAAAuJVLt6XeeOMNde7cWZs3b1Z2draefvpp7dq1S6dOndKGDRuKu0YAAIBCc+nKTVhYmPbt26ebbrpJPXv2VGZmpu68805t27ZNdevWLe4aAQAACq3IV27Onz+v22+/XTNmzNBzzz13LWoCAABwWZGv3JQvX14//vjjtagFAADgqrl0W+r+++/XBx98UNy1AAAAXDWXJhRfuHBBH374ob766itFRkbmeafU5MmTi6U4AACAoipSuDl48KBq1aqlnTt3qmXLlpKkffv2OfWx2WzFVx0AAEARFSnc1K9fX8nJyVq7dq2ki69bePvttxUYGHhNigMAACiqIs25+fNbv5cvX67MzMxiLQgAAOBquDSh+JI/hx0AAAB3K1K4sdlseebUMMcGAACUJkWac2OM0cCBAx0vxzx37pwefvjhPE9LLVq0qPgqBAAAKIIihZsBAwY4rd9///3FWgwAAMDVKlK4mTlz5rWqAwAAoFhc1YRiAACA0oZwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALIVwAwAALMWt4Wb9+vXq0aOHqlevLpvNpsWLF19xzLp169SyZUvZ7XbVq1dPs2bNuuZ1AgCAssOt4SYzM1Ph4eGaOnVqofofOnRI3bt3V8eOHZWYmKhRo0ZpyJAhWrly5TWuFAAAlBXl3PnhXbt2VdeuXQvdf8aMGapdu7YmTZokSWrcuLG+/fZbvfnmm4qJiblWZQIAgDKkTM25SUhIUHR0tFNbTEyMEhISChyTlZWl9PR0pwUAAFhXmQo3KSkpCgwMdGoLDAxUenq6/vjjj3zHxMXFyd/f37GEhISURKkAAMBNylS4ccXYsWOVlpbmWH755Rd3lwQAAK4ht865KaqgoCClpqY6taWmpsrPz08+Pj75jrHb7bLb7SVRHgAAKAXK1JWbqKgorV692qktPj5eUVFRbqoIAACUNm4NNxkZGUpMTFRiYqKki496JyYmKikpSdLFW0qxsbGO/g8//LAOHjyop59+Wnv27NG0adM0f/58Pf744+4oHwAAlEJuDTebN29WixYt1KJFC0nS6NGj1aJFC73wwguSpOTkZEfQkaTatWtr6dKlio+PV3h4uCZNmqT333+fx8ABAICDzRhj3F1ESUpPT5e/v7/S0tLk5+fn7nIAFLNaY5a6u4QiO/xad3eXAJR6Rfn+LlNzbgAAAK6EcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACyFcAMAACylVISbqVOnqlatWvL29lbbtm21adOmAvvOmjVLNpvNafH29i7BagEAQGnm9nAzb948jR49WuPGjdPWrVsVHh6umJgYHT9+vMAxfn5+Sk5OdixHjhwpwYoBAEBp5vZwM3nyZA0dOlSDBg1SkyZNNGPGDFWoUEEffvhhgWNsNpuCgoIcS2BgYAlWDAAASjO3hpvs7Gxt2bJF0dHRjjYPDw9FR0crISGhwHEZGRkKDQ1VSEiIevbsqV27dhXYNysrS+np6U4LAACwLreGm5MnTyonJyfPlZfAwEClpKTkO6Zhw4b68MMP9fnnn2v27NnKzc1Vu3btdPTo0Xz7x8XFyd/f37GEhIQU+3EAAIDSw+23pYoqKipKsbGxioiIUIcOHbRo0SJV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bjp16uTUNnr0aNO+fftrWqeVSDKfffbZZfs8/fTTpmnTpk5tffv2NTExMdewMmspzHnOT5MmTcyECROKvyCLKsp57tu3r3n++efNuHHjTHh4+DWtq6ziyo2FZWdna8uWLYqOjna0eXh4KDo6WgkJCfmO+eKLLxQVFaXhw4crMDBQYWFhevXVV5WTk1NSZZc5rpzndu3aacuWLY5bVwcPHtSyZcvUrVu3Eqn5ryIhIcHp7yJJMTExBf5dUDxyc3N19uxZXX/99e4uxXJmzpypgwcPaty4ce4upVQrFb9QjGvj5MmTysnJcbzK4pLAwEDt2bMn3zEHDx7UmjVrdN9992nZsmXav3+/hg0bpvPnz/MfUwFcOc/33nuvTp48qZtuuknGGF24cEEPP/wwt6WKWUpKSr5/l/T0dP3xxx/y8fFxU2XW9o9//EMZGRm6++673V2Kpfz8888aM2aMvvnmG5Urx9f35XDlBk5yc3MVEBCg9957T5GRkerbt6+ee+45zZgxw92lWcq6dev06quvatq0adq6dasWLVqkpUuX6qWXXnJ3acBVmTNnjiZMmKD58+crICDA3eVYRk5Oju69915NmDBBDRo0cHc5pR7Rz8KqVq0qT09PpaamOrWnpqYqKCgo3zHBwcEqX768PD09HW2NGzdWSkqKsrOz5eXldU1rLotcOc//93//p/79+2vIkCGSpGbNmikzM1MPPvignnvuOaeXxcJ1QUFB+f5d/Pz8uGpzDcydO1dDhgzRggUL8twOxNU5e/asNm/erG3btjnexZibmytjjMqVK6dVq1apU6dObq6y9OBfUAvz8vJSZGSkVq9e7WjLzc3V6tWrFRUVle+Y9u3ba//+/crNzXW07du3T8HBwQSbArhynn///fc8AeZSoDS87q3YREVFOf1dJCk+Pr7Avwtc98knn2jQoEH65JNP1L17d3eXYzl+fn7asWOHEhMTHcvDDz+shg0bKjExUW3btnV3iaWLmyc04xqbO3eusdvtZtasWeann34yDz74oKlUqZJJSUkxxhjTv39/M2bMGEf/pKQk4+vra0aMGGH27t1rlixZYgICAszLL7/srkMoE4p6nseNG2d8fX3NJ598Yg4ePGhWrVpl6tata+6++253HUKZcPbsWbNt2zazbds2I8lMnjzZbNu2zRw5csQYY8yYMWNM//79Hf0PHjxoKlSoYJ566imze/duM3XqVOPp6WlWrFjhrkMoE4p6nv/zn/+YcuXKmalTp5rk5GTHcubMGXcdQplQ1PP8ZzwtVTDCzV/AO++8Y2644Qbj5eVl2rRpY7777jvHtg4dOpgBAwY49d+4caNp27atsdvtpk6dOuaVV14xFy5cKOGqy56inOfz58+b8ePHm7p16xpvb28TEhJihg0bZk6fPl3yhZcha9euNZLyLJfO7YABA0yHDh3yjImIiDBeXl6mTp06ZubMmSVed1lT1PPcoUOHy/ZH/lz53/P/ItwUzGYM18ABAIB1MOcGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEG+Iuy2WxavHixu8u4arfeeqtGjRrlWK9Vq5amTJnitnoAuB/hBrCglJQUPfroo6pTp47sdrtCQkLUo0ePPO9ZgnvVqlVLNptNNptNFStWVMuWLbVgwQLH9vHjxysiIsJp/VL/cuXKqWrVqrrllls0ZcoUZWVlueEIgNKJcANYzOHDhxUZGak1a9Zo4sSJ2rFjh1asWKGOHTtq+PDh7i7vL+n8+fMFbnvxxReVnJysbdu2qXXr1urbt682btxYYP+mTZsqOTlZSUlJWrt2rfr06aO4uDi1a9dOZ8+evRblA2UO4QawmGHDhslms2nTpk2666671KBBAzVt2lSjR4/Wd999V+C4HTt2qFOnTvLx8VGVKlX04IMPKiMjw7F94MCB6tWrl/7xj38oODhYVapU0fDhw52+uLOysvTkk0+qRo0aqlixotq2bat169Zdtt4zZ87ooYceUmBgoLy9vRUWFqYlS5ZIkn777Tf169dPNWrUUIUKFdSsWTN98sknhT4XxhiNHz9eN9xwg+x2u6pXr67HHnuswP6XrpT885//VEhIiCpUqKC7775baWlpTv3ef/99NW7cWN7e3mrUqJGmTZvm2Hb48GHZbDbNmzdPHTp0kLe3t/7zn/8U+Jm+vr4KCgpSgwYNNHXqVPn4+OjLL78ssH+5cuUUFBSk6tWrq1mzZnr00Uf19ddfa+fOnXr99dcLfW4AKyvn7gIAFJ9Tp05pxYoVeuWVV1SxYsU82ytVqpTvuMzMTMXExCgqKko//PCDjh8/riFDhmjEiBGaNWuWo9/atWsVHBystWvXav/+/erbt68iIiI0dOhQSdKIESP0008/ae7cuapevbo+++wz3X777dqxY4fq16+f53Nzc3PVtWtXnT17VrNnz1bdunX1008/ydPTU5J07tw5RUZG6plnnpGfn5+WLl2q/v37q27dumrTps0Vz8enn36qN998U3PnzlXTpk2VkpKi7du3X3bM/v37NX/+fH355ZdKT0/X4MGDNWzYMEdA+c9//qMXXnhB7777rlq0aKFt27Zp6NChqlixogYMGODYz5gxYzRp0iS1aNFC3t7eV6xVuhhcypcvr+zs7EL1v6RRo0bq2rWrFi1apJdffrlIYwFLcvOLOwEUo++//95IMosWLbpiX0nms88+M8YY895775nKlSubjIwMx/alS5caDw8Pk5KSYoy5+Ibi0NBQpzfE9+nTx/Tt29cYY8yRI0eMp6en+fXXX50+p3Pnzmbs2LH51rBy5Urj4eFh9u7dW+hj7N69u3niiScc6x06dDAjR450rIeGhpo333zTGGPMpEmTTIMGDUx2dnah9j1u3Djj6elpjh496mhbvny58fDwMMnJycYYY+rWrWvmzJnjNO6ll14yUVFRxhhjDh06ZCSZKVOmXPHz/rfWrKws8+qrrxpJZsmSJY56/vetz5d7C/QzzzxjfHx8CnWcgNVx5QawEGOMS+N2796t8PBwp6s97du3V25urvbu3avAwEBJF+d7XLqqIknBwcHasWOHpIu3tXJyctSgQQOnfWdlZalKlSr5fm5iYqJq1qyZZ8wlOTk5evXVVzV//nz9+uuvys7OVlZWlipUqFCo4+rTp4+mTJmiOnXq6Pbbb1e3bt3Uo0cPlStX8D99N9xwg2rUqOFYj4qKcpwHX19fHThwQIMHD3ZcrZKkCxcuyN/f32k/rVq1KlSNzzzzjJ5//nmdO3dO1113nV577TV17969UGP/lzFGNputyOMAKyLcABZSv3592Ww27dmz55rsv3z58k7rNptNubm5kqSMjAx5enpqy5YtTgFIkq677rp89+fj43PZz5s4caLeeustTZkyRc2aNVPFihU1atSoQt+2CQkJ0d69e/XVV18pPj5ew4YN08SJE/X111/nOZbCuDQH6V//+pfatm3rtO3Px5zfbcH8PPXUUxo4cKCuu+46BQYGuhxQdu/erdq1a7s0FrAaJhQDFnL99dcrJiZGU6dOVWZmZp7tZ86cyXdc48aNtX37dqcxGzZskIeHhxo2bFioz27RooVycnJ0/Phx1atXz2kJCgrKd0zz5s119OhR7du3L9/tGzZsUM+ePXX//fcrPDxcderUKbBvQXx8fNSjRw+9/fbbWrdunRISEhxXm/KTlJSkY8eOOda/++47x3kIDAxU9erVdfDgwTzH6GqwqFq1quMcuRps9uzZoxUrVuiuu+5yaTxgNYQbwGKmTp2qnJwctWnTRp9++ql+/vln7d69W2+//baioqLyHXPffffJ29tbAwYM0M6dO7V27Vo9+uij6t+/v+OW1JU0aNBA9913n2JjY7Vo0SIdOnRImzZtUlxcnJYuXZrvmA4dOuiWW27RXXfdpfj4eB06dEjLly/XihUrJF28EhUfH6+NGzdq9+7deuihh5SamlroczFr1ix98MEH2rlzpw4ePKjZs2fLx8dHoaGhBY65dB62b9+ub775Ro899pjuvvtuR0CbMGGC4uLi9Pbbb2vfvn3asWOHZs6cqcmTJxe6rqtx4cIFpaSk6NixY9qxY4feeecddejQQREREXrqqadKpAagtOO2FGAxderU0datW/XKK6/oiSeeUHJysqpVq6bIyEhNnz493zEVKlTQypUrNXLkSLVu3VoVKlTQXXfdVeQv7JkzZ+rll1/WE088oV9//VVVq1bVjTfeqDvuuKPAMZ9++qmefPJJ9evXT5mZmapXr55ee+01SdLzzz+vgwcPKiYmRhUqVNCDDz6oXr165Xk0uyCVKlXSa6+9ptGjRysnJ0fNmjXTl19+WeAcIEmqV6+e7rzzTnXr1k2nTp3SHXfc4fSo95AhQ1ShQgVNnDhRTz31lCpWrKhmzZo5/UrytbRr1y4FBwfL09NT/v7+atKkicaOHatHHnlEdru9RGoASjubcXUGIgBYzPjx47V48WIlJia6uxQAV4HbUgAAwFIINwAAwFK4LQUAACyFKzcAAMBSCDcAAMBSCDcAAMBSCDcAAMBSCDcAAMBSCDcAAMBSCDcAAMBSCDcAAMBSCDcAAMBS/h+V28zQoqB6OAAAAABJRU5ErkJggg==", "text/plain": [ "
" ] @@ -359,12 +79,12 @@ } ], "source": [ - "b.load_and_attach()\n", - "hist = BpfMap(b, hist)\n", + "b.load()\n", + "b.attach_all()\n", "print(\"Recording\")\n", "time.sleep(10)\n", "\n", - "counts = list(hist.values())\n", + "counts = list(b[\"hist\"].values())\n", "\n", "plt.hist(counts, bins=10)\n", "plt.xlabel(\"Clone calls per PID\")\n", @@ -372,6 +92,14 @@ "plt.title(\"Syscall clone counts\")\n", "plt.show()" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37fc74e9-d69c-4a8f-b84a-a3a4113f87cc", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -390,7 +118,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.3" + "version": "3.13.3" } }, "nbformat": 4,