diff --git a/ruty/WhykIA/Mon premier neurone.ipynb b/ruty/WhykIA/Mon premier neurone.ipynb new file mode 100644 index 0000000..fb5cd95 --- /dev/null +++ b/ruty/WhykIA/Mon premier neurone.ipynb @@ -0,0 +1,384 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1048, + "metadata": {}, + "outputs": [], + "source": [ + "#Neurone artificiel\n", + "#importation\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.metrics import *\n", + "from sklearn.datasets import make_blobs" + ] + }, + { + "cell_type": "code", + "execution_count": 1049, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dimension de X: (100, 2)\n", + "dimension de y: (100, 1)\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiIAAAGdCAYAAAAvwBgXAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABhIElEQVR4nO3dd5wU9f3H8dfMXgXujt6PIkVBQKQ3C6KIGhV7RazRRCzBJMaY/KImhhg10Wg0tmDvBrGholKlSAepgughvd7BwbXd+f3xvTvuYHdv7253Z/f2/Xw8Vm93Zmc+7O3tfPZbPl/LcRwHERERERfYbgcgIiIiiUuJiIiIiLhGiYiIiIi4RomIiIiIuEaJiIiIiLhGiYiIiIi4RomIiIiIuEaJiIiIiLgmye0AgvH5fGzZsoWMjAwsy3I7HBEREQmB4zjs37+f1q1bY9vB2zxiOhHZsmUL2dnZbochIiIiNbBp0ybatm0bdJ+YTkQyMjIA8w/JzMx0ORoREREJRV5eHtnZ2eXX8WBiOhEp647JzMxUIiIiIhJnQhlWocGqIiIi4holIiIiIuIaJSIiIiLiGiUiIiIi4holIiIiIuIaJSIiIiLiGiUiIiIi4holIiIiIuKamC5oJuGXW3CIL75fTX5xIT2at6FPq3ZuhyQiIglMiUiC8Pp8/HHaZP4570sKSorLHz+xZTYvjb6Oni3auBidiIgkKnXNJIhbP3mdv83+tFISArB8+2aGTfw73+3e7lJkIiKSyNQikgDW7trGM4tm+d3mdXwcLCrir7OmMHH0tdENTERCUuLz8sqyefx7wXTW7t5Og5RUrujRnzsGjqB9wyZuhydSK2oRSQCvLJ9Hkh34V13i+Hj9228oPKK1RETcV+Qt4dzX/831H7zMkm2bOFBUyLYDefxr/jR6Pn0/32ze6HaIIrWiRCQBbDuQV+U+RV4vuYWHohCNiFTHQ7M/4/PvVwHgc5zyx72Oj4PFRZz/5lMUe71uhSdSa0pEEkCbjIZU+PzyK9WTRMO0etEJSERCUuLz8sQ3X1VKQCryOg7bDuQxee3S6AYmEkZKRBLANScMxuv4Am5Psm2u7jWQFI+GDCUCx3E4UFTAweIit0ORKmzK3cvOgweC7pNse5j3k7pnJH7pypMAOjVuxq8GjeCf8748apvHsslMTecPJ5/tQmQSTT7Hx/OLZ/PPeV+yZtc2AAa26chvhozkou59XI5O/Ak2tquMgxPSfiKxSu/eBPHIyIt58LTzyUxNq/T40HadmHvD3XRo2NSlyCQaHMfh+skvc/NHr7G2NAkBWLDlBy5+5xkemPGRi9FJIG0zG9GlcXOsIPuU+Hyc2en4qMUkEm6W41Q1esA9eXl5ZGVlkZubS2Zmptvh1AmHiouY+eN3HCwuonuzVhzbtKXbIUkUvLdqMRe/80zQfZbc/Ad6t8yOUkQSqhcWz+bGD1/xuy3JsunevDVLb/4DlhUsXRGJrupcv9UikmDSk1M4s/PxXNDtRCUhCeTJBdPwBLlQJdk2Ty2YEcWIJFTXnziUXw8+AzjcVWOX/i7bN2zCh1fcqiRE4prGiIgkgGXbfsIbpPGzxOdj6bacKEYkobIsi4dHXsxlPfrx7KJZrNq5lazUdC49vh+XHt+X9OQUt0MUqZWIJyKbN2/m7rvvZsqUKRw6dIiuXbvywgsv0Ldv30ifWkRKpScns7cg8HYLqJecGrV4pPr6te5Av9Yd3A5DJOwi2jWzd+9ehg4dSnJyMlOmTGHVqlU8+uijNGzYMJKnFZEjXNytLx4r+J/7Rd1OjFI0IiKHRbRF5KGHHiI7O5uJEyeWP9ahQ4dInlJE/Lh94Gk8t3gWhV7nqOJYHsumSb36XHPCYJeiE5FEFtEWkQ8++IB+/fpxySWX0Lx5c0488USee+65gPsXFhaSl5dX6SYitdepcTM+ueo2MlLSsDCDHssGPrZskMlX14wnKy3d3SBFJCFFdPpuWpqpWTF+/HguueQSvvnmG+68806eeeYZrrnmmqP2v++++7j//vuPelzTd0XC40BRAW+sWMDXmzaQZNucfkw3Lux2oqrqikhYVWf6bkQTkZSUFPr168ecOXPKH7v99ttZsGABc+fOPWr/wsJCCgsLy+/n5eWRnZ2tRERERCSOxEwdkVatWtG9e/dKj3Xr1o2cHP/TBFNTU8nMzKx0ExERkboroonI0KFDWbt2baXH1q1bR/v27SN5WhEREYkTEU1EfvWrXzFv3jz++te/sn79el5//XWeffZZbr311kieVkQkIZT4vBR7vW6HIVIrEV9r5qOPPuKee+7hu+++o2PHjowfP56bbroppOdqrRkR93y/dyfzftqIx7I4uX1XWmVkuR2SlPpg7TIe/vpzZm9aD0CfVu0YP+h0ruw5QOXeJSbEzGDV2lIiIhJ92w/kccMHL/HJd99S9uHgsWyu6Nmfp86+kowjVnCW6Hpw5if8YdpkPJZVXrbftix8jsOt/U/libMuVzIirouZwaoiEl/2FxZw8ouP8On6VVT8huJ1fLyx4hvOeu1flPjUFeCWRVt+5A/TJgNUWjuorEjdvxdMZ8r6b12JTaSmlIiISLnnF8/mu9078Dq+o7Z5HYevN21g8pplLkQmAE8tnFFeiM4fj2Xz72+mRy8gkTBQIiIi5f675GsgcG+tx7KZuHROwO0SWYu2/EiJ7+gksYzX8bFo649RjEik9pSIiEi5rQdyg6Qh5kL3U97eqMUjlaUnJVe5T1oI+4jEEiUiIlKuTWZDgg1z9Fg22VmNoxaPVDb6uN7YQQaieiybC7WKssQZJSIiUu6GE4cF3e51fNxw4tAoRSNHuqHPMLJS0/H4SUZsyyLF42HcgOEuRCZSc0pERKTcDScOpXuz1nisoz8abMvi1A5dObdrLxciE4Cm9RrwxTW/onF6fQA8loVtWVhA/eRUPr7yNo5p1MzdIEWqSXVERKSS3QcPcPNHrzFpzZLyaaHJtoexvQfz+KjLqJec4nKEcrC4iDe/XcBXG9fgcxyGZndizAmDyExNdzs0EUAFzURinuM47DmUj8e2aZhWz+1w/Popby8LNv+AbVkMbdeZpvUauB2SiMSJ6ly/k6IUk4gAXp+Pfy+YzmPzvmDjvt0A9G6Zzd1Dz+TyHv1djq6ytpmNaJvZyO0w4t7GvbvYW3CQ7MxGNKuf4XY4IjFHiYhIlPgcH1e+9wLvrFpY6fHl23/iiveeZ/XOrdw//DyXopNw+3zDKn7/5SQWbc0BzBib84/tzd/PuJDOjZu7HJ1I7NBgVZEoeXvlIt5etRCHyiXDysZhPDDzY5aUXrQkvr27ahGjXv0XS7ZtKn/M5zh8sHYZA56bwHe7t7sYnUhsUSIiEiVPfjPN77TLMkm2zTOLZkUxIomEgpJifv7hqzg45UlmGa/jI6+wgLs+f9el6ERijxIRkSj5dseWSguVHanE52PZ9k0Bt0t8mLxmKXsLDgbc7nV8fLRuBdsO5EYxKpHYpUREJEqqmvZqAQ1SUqMTjETMhr07gy5MB+Dg8OO+PVGKSCS2KRERiZJLuvf1Wyisoou69YlSNBIpjdLq4/VVXRWhYZpqfoiAEhGJI7kFh3hi/ldcM2kiN37wMu+uWkSx1+t2WCG7Y9BppCYl+V0rxGPZtM5oyFU9B7oQmYTTBd1647EDjwWysOjRvDVdm7SIYlQisUvTdyUufLxuBZe++yyHiouwLRvLgheWfE3Hhk357Orb6RIHH+rHNGrGp1fdzug3n2JPwcHS5nuLEp+XdlmN+fTq28lITXM7TKmllg2yGNd/OI/P/9LvSsYODg+eNhoryMBlkUSiyqoS81Zs30zfZx+kxOc96oM9ybZp1SCLteMeID1OSo8fKi7irZULmbvpe5JsmzM6dednXXuSZHvcDk3CxOvzcdfn7/DkN9NxcPBYNsU+Lxkpafz77CsYc8Igt0MUiSiVeJc65br3X+TVFfMp8fkC7jPx/LFc23tIFKNKTLkFh9i4bxf1k1Po3Li5vtVXYcv+fby7ajF7DuXTqVEzLureR2v1SEJQiXeJWXM3beCJb6bxdc4Gkjw253TpybgBw4P2l/9vzZKgSYiFxeQ1S5WIRNDO/P387stJvLp8HkWl43KObdKC+049N+ZK08eS1hkNuX3gaW6HIRLTlIhI1Dw0+1N+9+Ukkmy7PLF4esEM/rNwJu9eejPnHXuC3+cVlBQHPa6DQ35xUdjjFWP3wQMMeuFv/LhvD17ncEK4bvd2rnjvebYdyOXOQae7GKGIxDPNmpGomLZxLb/7chJApdaNEsdHic/LJe88w+a8vX6f26N5G78zTcp4LJsTWrQNb8BS7sFZnxyVhMDhMvW//vw9FecSkRpTi4hExT/nfVGpJaQiB5OcPLd4Nmcc042nFsxg4dYfqJeUwkXd+3BNr0EsDrIGi8/x8fO+J0Uw+sRV7PXy/OKvj0pCKnJweGnpXO4eNiqKkYlIXaFERKJixo/rgo7z8DkOE5fM4f4ZH1VKWJbv2EyD5FRO63As035YCxz+Ju6xbLyOj3+eeWlcTN+NR3sO5bO/qCDoPrZlsWHvzihFJCJ1jbpmJCosqp5dkZNnSl5XTFh8jkN+cSHLtv3EoyMvoVPjZuXbhrXrzMdXjuOOQSPCH7AAkJGaFrRbrEzDtHpRiEZE6iK1iEhUnH7McUxeu6yK2S/4LQDldRx2F+STlZbOunF/Jr+4kGTbQ2pScsTiFaNecgo/69qLj9etCNg9U+Lzcdnx/aIcmYjUFWoRkai4c9DpAZOQstaSYAVtPJbN9B/WYVkWDVLSlIRE0R9PPhvbsvy2anksi3O79qJv6/YuRCYidYESEYmKYe0688RZl2NBpZVJbcsi2RPa29AJmqpIpPRr3YGPrhxHk3r1AUi2PXhKu2su7NaHNy660c3wRCTOqWtGombcgOEMaduJGz58iWXbfsLBjAEp8npJT0qmoKQkYLLhdXyc3K5LdAOWciM7dWfz+IeYvGYZq3ZuoV5yCqOP661BwiJSa0pEJKqeXTyzPAmpKFgSYlsWWanpXNlzQOQDlIBSPElccnxfoK/boYhIHaJERKJm9c6tPLNolt9tDk75YNUky6akdGCkx7JJT07moyvHUT8lNXrBSq3lFR5iza5tpHiS6NG8tRb1ExG/lIhI1Ly6fH7AomZQmoTYNmd36cnSbZtIT0rm4u59uKXfKbTNbBTdYKXGcgsO8dsv3uPlpXMp8JYA0LJBJncPPZM7Bo7QQnkiUklEE5H77ruP+++/v9JjLVq0YNu2bZE8rcSobQfyqtynxOfj+XPH0Kx+RhQiknA7UFTAyS8+wsodWypN9912II9fffYO3+/dxb/OutzFCEUk1kS8ReT444/niy++KL/v8bjXPOs4DlPWf8tTC6azdNtP1E9J5dLufbml38m00TfuiGudkYVTxcSXtKQkstLSoxOQhN2/v5nOtzs24wvwi37im2lcf+JQerfMjnJkIhKrIj59NykpiZYtW5bfmjVrVvWTIsBxHH7+0auc8/qTfLp+FZv372Pd7u1MmD2F7k/dxzebN7oSVyK55oRBQdcsSbJtxvQaRIpHPYbx6j8LZwZMQsD8jl9YPDuKEYlIrIt4IvLdd9/RunVrOnbsyOWXX873338fcN/CwkLy8vIq3cLl+cWzeb70A7DixdDrOBwoKuRnrz9Z5XLzUjtdmrTgtgHD/W7zWDaZqence9LZUY5KwqmsTH8gJT4fG/builI0IhIPIpqIDBw4kJdffpnPPvuM5557jm3btjFkyBB2797td/8JEyaQlZVVfsvODk/zreM4PDp3asDVTnyOw86DB3h31aKwnE8Ce2zUpTxw6nlkHDEDZkj2Mcy94W7aN2ziUmQSDpmpwbvVPJZdXhhNRATAcpyqeu3DJz8/n06dOvHb3/6W8ePHH7W9sLCQwsLC8vt5eXlkZ2eTm5tLZmZmjc+7r+AgjR76VdB9kmyb63oP4dlzx9T4PBK6g8VFzPhhHQeLizi+eWuOa9rS7ZAkDG6f8iZPL5hRPv3an4+vHMfZXXpGMSoRiba8vDyysrJCun5HtTO+fv369OzZk++++87v9tTUVFJTw18rIpSVXy38r6UhkVEvOYWzuvRwOwwJs/GDT+flZfM4UFR41Hggj2UzsE1Hzux0vEvRiUgsiupaM4WFhaxevZpWrVpF87RkpaXTs3kb7CCJRrHPy2kdj41iVCJ1T4eGTZl+7V10KO1i81g2dmndkFGdj+fjq8bhsbXElYgcFtEWkV//+tece+65tGvXjh07dvCXv/yFvLw8xo4dG8nT+o9lyBmMff9Fv9s8lk2LBhlc0O3E6AYlUgf1bpnNutse4KuNa1m45UdSPB7O7tJT3W8i4ldEE5GffvqJK664gl27dtGsWTMGDRrEvHnzaN8++kuGj+k1iGXbfuIf876oVN3TtiwapqUz5arbE3ra6Irtm5mzaQMe22Z4h2Pp1NidadZSN9iWzenHdOP0Y7q5HYqIxLioDlatruoMdgnVrB+/4+mFM1i6bVN5QbPrTxxKk3oNwnL8eLMpdw9X/e8FZuWsr/T4uV178dLoa2mUrhkOIiJSPdW5fidcIiKH7Ss4SO///JnN+/cdtf6Lx7Lp3bItc264O6FbiuJRflEhuYWHaJJen9SkZJZu28S/5n/F1O9X4ThwSoeu3D7gNAa27eh2qCJSR8XsrBmJLc8snMmmvL1+K2F6HR+Ltubwv9VLuLxHfxeiC6+CkmIcxyE9OcXtUCJm2bZN/Hnmx0xasxSf45CelMygtscw48d12JZVnmy+vXIhr6/4hn+NuozbBp7m9zjPLZ7Nd7t30Ci9Hpcd349zj+2l1XNFJCKUiCSwF5fODVqO27YsXlo6N24TEcdxeHvlQh6e8zmLtuYAcEKLttw1+Ayu7jWwTq0C+3XOek5/5Z8Ue33lv9NDJcVM+2EtQKXfc1lCcvunbzGo7TH0b9MBMK/Xb6a+x6Nzp5aPo7KweGvlQhqn1+fxUZdyRY8BmvUiImGlT5QEtuPg/qDbfY7DtvzwldmPtt9/+T6Xv/c8S7ZtKn9sxY7NXPP+RO787G1iuFeyWnyOj6v+9wJFXm/QtXyOlGTb/Oubr8rvP71wBo/OnQocTlYczGu051A+YyZNpPczf2br/twwRi8iiU6JSAJrl9U4aAk3j2XTsWHTqMUTTrNz1vO3rz8FKrcGlP38r/lf8cX3q12JLdy+/H4NP+buCdq65U+Jz8f08hYTH3+b/WmVz1m9cytnv/4EvmokPBU5jsNXG9dww+SXOf/Np7jtkzdYUtpaJSKJSYlIAvt5n5OCbvc6Pm7sMzRK0YTXUwumkxSkC8Fj2fx7wfToBRRBq3ZuLS8aVl02NvsLC/jv4q/ZlLe3yv29jsPSbZv48vs11T5XflEhZ776OCNe/icvL5/LB2uX8Z9FM+nz7IPc8tFrNU5uRCS+KRFJYNf2HkzfVu3xWEe/DWzL4mddejKqc3yW4168NeeomUAVeR0fi+vIN/H6KanVbg0B0zXTKL0eLR/9DTd99Gq1nvfhuuXVPt/PP3yVLzeaBKbsd1P2/2cWzeSh2Z9V+5giEv+UiCSw9OQUvhz7K645YRDJFWZE1EtO4c6BI3j30pux/SQp8aBeCLNj6soMmp917ek3maxKic/Hsu0/cbC4qNrPLSgprtb+Obl7eOPbBUETpkfmTqWwmscVkfinWTMJLjM1nf+eP5aHz7iIxVtz8Ng2/Vt3ICM1ze3QauWibn1Ytv2ngBc+j2VxSfc+UY4qMlo2yOKmvsN4dtGsgP9eGwtf6cBTj2Xj4NSoFQXA6/PRu2V2tZ7z6fpvywe+BrLnUD4Lt/zI0HadaxSXiMQnJSICQJN6DTijU3e3wwibm/oO45G5n7O/sADvERdc27JIT07hln6nuBRd+D0+6jLyiwp5Zfl8kmwbCwufY1KPXw08HY9tM/X7Vfgch+EdjuWnvL28v3Zp0O4rfyxMS9LVvQZW63lFXi8WVJGKQKG3pFrHFZH4p0RE6qTm9TP5YsyvOOu1J9h5cH9514XX8dEwNZ2PrhxH28xGLkcZPimeJF6+4Hp+N2wUr6/4ht0H82nfsAljeg2kTem/8yEuLN9/1KuPVzsJ8Vg2lgWvXXgDmanp1Xpun1btqkxCkmybHs1bV+u4IhL/lIhIndW3dXt+vPOvvLVyIdN/WIeDw0ntunBFj/7UT0l1O7yI6N6sNX85bXSV+7VskEWSZVMSZKZKg5RUmqY34Ifc3Xgsm9HHncBvh57JgDbVLw0/uO0x9GjemtU7t/mtdeKxbC7u1ofm9bWUg0ii0VozIi77fu9Onl4wgynrV+J1fJzSviu39j+Vni3aROycX36/mtNfeSzgdo9l89uhI/nriAsoLCkm2eOp9cDllTu2cNLEh8krLKiUjHgsi46NmjHn+t/SrH5Grc4hIrFBi96JxImP1i3norf/g9fnlF+ck2wbr8/H0+dcxc39To7IeR3H4ezXnuDz0nEjFSVZNk3rN2DpzX+kRYPw/t3l5O7h0TlTeWnZXHILD9GqQRY/73sSdww8rVYrPe89lM8ry+ezbNtPJHtsjmnUjO7NWtGrRVvaZTUO479AREKhREQkDmzK3UPnJ/5Asdfrd/yEBcy78Xc16goJxaHiIsZ98gYvLZtXqYViaHYnXrngejo2imxVXZ/jC8v08HdWLuKa9ydSUFKMbVmVEisLOLtLD/7zs6vr1JggkVinREQkDvzxq8lMmD3lqFk9ZZJsm0u69+X1i26MaBzbDuTy5fdrKPKW0K91h4h2CYXbnE0bOGniwzhO4MnBHsumZYNMFv383rC38IiIf9W5fmuwqtRpXp+P1bu2UuT10rVJcxqkxE59lC82rg6YhIApOPb5hlURj6NlgyyuquZ03FgxYfYUM1U5yJwcr+Nj24E8/v71Zzx65iVRjE5EQqFEROokx3F48ptp/O3rT9lSulpselIyN5w4lL+OuCAmCraF0ha5+1A+t095k0dHXkKyx1P1ExJIsdfLJ999G1JhNq/j44UlX/PIyIuxarguj4hERnzW7xapwl2fv8Ptn75VnoQAHCop5umFMxn+0qM1KmsebsM7HIsnhIvik99M59rJL0Y+oDhT5C2pVnXY3MJDMfF7F5HKlIhInbN02yb+Oe9Lv9vMYnebeCoGVt69ud9J2JZNVamIg8PrK75h6bZNUYkrXtRLTiG7GgNQ05OSSU9OjmBEIlITSkSkznl+8WyS7MBvbQeH/yycGcWI/OvQsClvXnwjdgitIkm2zSvL5kUhqvhhWRa39j815NfvmhMGx+0ijiJ1mf4qpc5Zv2dHleXLf8zdHaVogruwWx/m3/i7KvdzHNienxeFiOLLHYNGMKxd56DJiMeyaZCSyt1Dz4xiZCISKiUiUuc0Tq9fvrZMIBkxNHumd8t2NKii5LxlQXamCnMdKS0pmc+uvoM/Dz+PFgGqsh7fvDWzrvtNxOuiiEjNaNaM1DmX9+jPG98uCLg9ybIZ02tQFCMKzmPbXN97KE8tnB6wJafE5+Pa3oOjHFl8SEtK5vcnnc3vho1iX8EhcgsOMTtnPQUlxZzQsi39W3fQTBmRGKZEROqcc7r0pH/r9izeuumoBdY8lk29lBR+NXiES9H5d/ewM3l71UJ25h/wuyjcuAHDObZpSxciix+2ZdM4vT6N0+ur9UMkjqhrRuocj23z6dV3MKLjcea+ZZUPXm2X1YjpY++iQ8PYulC1zmjI3Bvu5vRjjqs0iyYrNZ2/DD+fx0dd6lpsieSHfbtYsjWHXQcPuB2KSMJQiXep01Zs38yU9d9S5C2hf+sOnNGpW8zPnNi4dxcrd24hPSmZoe06k5akKaeRNnXDKu796n0WbPkRANuyuOC43vz9jIs4plEzl6MTiT9aa0ZEqpSTu4eXl83lx317aFa/AVf1HMjxzVu7HVbUvbdqMZe88yyWRaUCaR7LJistnW9uvIdOjatORvIKD/Hsolk8v3g2Ww/k0rJ+Jjf0GcbNfU8mKy09kv8EkZijRERqZN3u7Xzy3QoKS0ro06odI445LuZbD6T6HMfhT9M/5C8zP8G2LMrGcZb4fIzpNZDnz7uGFE9iDB8rKCmm9aO/ZV/BQb+r1Xgsm5917cn7l/8y6HF25Odx0sRHWL9nR6VkxrYsjmnUlFnX/YaWDbJqFev2A3k8t3gWk9cuo7CkhIFtO3Jr/1Pp3TK7VscViQQteifVkld4iLGTJvL+2mXmwoSF1/FxTKOmvH3xz+nbur3bIUoY/XvBdP4882MAs+hehSvwq8u/ITM1nSfPvsKl6KJr8pql7C04GHC71/Hx4brlbD+QF3Tl3p9/+Cob9uw8quS8z3H4Yd9ubpj8Mh9fdVuN45yzaQOjXv0X+cWF5edYvWsrzy+ezcNnXMSvh4ys8bFF3KavuwnOcRzOe+MpPly3HDAfnGWzNn7ct4fhL/2DDXt2uhmihFGx11uehPjj4PDMopnsSJDiaev37AxahRfM30SwAng5uXv4YO1yv7OdwLQ0TVn/Ld/vrdnfUW7BIc5+7YlKSUjZcQF+M/W9qKzSLBIpSkQS3Jcb1zDjx3V+l6P3Oj4OlRTxyJzPXYhMImHBlh/Ykb8/6D4lPh8fr1sRpYjc1TAtHa+v6t7phmn1Am5bsPkHHL8dO4c5wPyfNlY3PABeWT6PvMJDARf481g2/5g7tUbHFokFSkQS3BsrFgT9Rlji8/HK8vlRjChxLN6aw4RZU/jzjI/5dP23+AJ8ow6n/KLCKvexIGFWqb2g24lBy8NbWPRo3poujZsH3MdTRYtKmSTbU+34AL7auAaCLI3odXx8tXEtMTzcTySoqCUiEyZMwLIs7rzzzmidUkKwpyC/ynVZ8osL8Vaxj4RuZ/5+Tn3xEfo++yB/nPYBD8z8iLNee4LO//pDxFfY7dasFVYV6/06kDCzZ1pnNOTWAacGfEUcHB48bXTQyqwntetMchVJRpJtc0qHLjWK0bSEVNXioiRE4ldUEpEFCxbw7LPP0qtXr2icTqqhY8MmVfaRt87ICvlbnwRX7PVy+iuP8XXOBsB8my1LBHNy93Lqi4+Sk7snYudvm9mIs7scH3AtHo9l0blxM05p3zViMcSaR0dezLgBw7EtC9uyypOKBimpvDz6Os479oSgz29SrwHXnTgkYMuKbVmM6TWI5vVrNvNvaHanoImQx7IYUsU+IrEs4rNmDhw4wFVXXcVzzz3HX/7yl0ifTqrpxj7D+Oe8LwNuty2Lm/ueHMWIYkux18uLS+fw5IJprNm5jSSPhybp9UmybdpmNuKaEwZzZc8B1EtOCel4769ZyvLtP/nd5nV8HCgq5PF5X/LomZeE859RyZNnX8Gg5x9i98EDlFToDkqybJI9Hl654PqEuqgl2R7+ddbl3D30TN5dtZg9h/I5plEzLu7eh/pVLEZY5rEzL+X7vbv44vvVeCwbr+Mr///J7bvwxFmX1zi+608cyn0zPuJQcbHflg+v4/CrQafX+Pgibot4HZGxY8fSuHFj/vnPf3LqqafSu3dvHnvsMb/7FhYWUlh4uA87Ly+P7Oxs1RGJsN98/i6P+Bns5rFsjm3agrk33E1mauIVZCrylnD+G0/x2YaVfhu+LUyD+XFNWzJ97F1Bp3eWuejt/zB5zVK/g4PLNK+fwfZfP1LjuEOxOW8vD86awotL53CopJgk2+bibn34w8nn+O2WOVRcRG7hIRql1SNVlV798vp8fLp+JROXzmFT3h7aZjTi2t6DObtLz1q3KH66/ltGv/l0pRa0JMumxPHxu6GjmHD6BeH4J4iETczUEXnzzTdZvHgxCxYEXgm1ogkTJnD//fdHMiTx4+9nXES7rMZMmP0pWw/kApDqSeLqXgN5+IyLEjIJAXh0zlQ+/35VwN73ssfX79nBle89z5djx1d5zD0H84MmIQB5hQXVC7QG2mQ24qlzruSxUZey99BBMlPTSPfTqrN651b+PPNj3lm1iBKfj7SkJMb0GsQfTj6HdlmNIx5nPPHYNud07ck5XXuG/dijOvfg21/+iSe/mcbkNcso9JYwoE0Hxg0YzunHdAv7+USiKWItIps2baJfv358/vnnnHCC6WNVi0hs8/p8rNixmcKSEo5t2iLolMW6zuvzkf3P35UnZqH49hd/4vjmrXEch5k/fsecTRvw2DYjOh5XXhTu5g9f5b9Lvw44QNjCDChd+cv7wvCvqJ1FW37klBcfobCkpHIXjm3TMK0e82/8ndZhERG/YqJFZNGiRezYsYO+ffuWP+b1epk5cyZPPvkkhYWFeDyVR5qnpqaSmhpan6yEn8e2VS661Pb8vGolIRYWX21cQ7LHw4VvPc3KnVvLB4R6HR/DsjvxzqU3c1PfYTy7eFbQY90SA2NyHMdhzKT/UlBSclShrhKfj72HDnLLR6/x+Zg73QlQROqMiE2FGDFiBCtWrGDp0qXlt379+nHVVVexdOnSo5IQkVhS1XTMI1kW7C8q4OSJj7B213bAJCBlF/F5P21k+Ev/4PhmrRk3YLjfY3gsi0Ftj+GmvifVLvgwmLNpA6t3bQtYLdTr+Jj6/Wo27t0V5chEpK6JWItIRkYGPXr0qPRY/fr1adKkyVGPi8SapvUa0KtFW77dvhlfCDUafI7Dpry97Dy4328FzBLHx5pd23h75SL+NeoyujRuzt+//ozN+/cBZqroz/ucxAPDzyMtBgaDrty5JaT91uzaRsdGTSMcjYjUZVr0TsQPy7K4Z9gornjv+Sr3TbJs+rfpwNQNqwOW4QYzFfq1FfMZ23swtw88jVv7n8ra3dso9nrp0qRFyFOAo6F+cmhdpLEUs4jEp6gmItOnT4/m6URq5fIe/flu9w7+b/oHeCzrqNkuVul/22Y14q2Lb6L3M8Hr5Pgch10HD5Tf99g23ZvFZgXTUZ2PJ8XjocjrDbhPk/T6DM4+JopRiUhdpBYRSRh7D+WzcudWUjweerfMJsVT9dv/j6ecw0XdT+TZRbNYvn0zuYWHOFBUyIHCAprXz2Bs78Fc13soWWnpdGrUjH0FBwO2iiTZNl2btAj3PysimtRrwK39h/PYvC8Dlg///UlnhfQaiogEo08RqfP2Hsrnrs/f5bUV88u/4TdJr89vhozkN0NHYgcod16me7PWPDbqsirPc0u/k7nhg5cDbi/x+bixz7DqBe+iv59xIbmFB/nvkjnlywA4DvgcH3cPHaVqniISFhGvrFob1ZmHLOLP/sIChvz3IVbv9D8D5Od9T+KZn10dlnMVeUs489XHmfnjd0e1iljAlT0HxGX59NU7t/LaivnsyN9PdmZjrjlhEO0bNnE7LBGJYdW5fisRkTrtodmf8vuv3g86iHTBTffQr3WHsJzvUHER/zftA55ZNJP9RaY4X9N6DfjVoBHcPXSUFg8UkYQQEwXNRGLBfxbNDJqEJNk2Lyz+OmyJSHpyCg+PvJj7h5/H6p1bSwekttJYChGRAPTpKHXapty9QbeX+Hxs3Bf+olz1klPKy7qL6d55Z9Ui9hcW0LVJCy7v0Z+M1DS3wxKRGKBEROq0hmnp7D6UH3C7x7JpWq9BFCNKLIeKixj7/ou8s2oRHsvGtixKfF7u/Oxtnv3Z1VzVa6DbIYqIy9RhLXXa2BMGl6/54o/X8XFVT10MI+Xa91/kvdWLAfNaF/u8OMDB4iLGTPovn61f6UpcjuMQw8PjRBKKEhGp0+4cNILM1DS/yYjHshma3YkzO3d3IbK6b/XOrby9alHAMTqWZXH/jI+iFo/jOLy9ciFDXniIpD//guQ//5IzXnnMtWRIRAwlIlKnZWc1ZtZ1v6Frk+aAKbNuldZEPbdrTz6+8rYq64hIzby3enHQ1iif4zD3p+/Zuj/0VY5rynEcxn/2Dpe9+xzzN2/E5zh4HR/TNq5l1Gv/4tE5UyMeg4j4pzEiUucd37w1K395H7Nz1rNgyw+keJIY1fl4Ojdu7nZodVpeYQG2ZeGtogckr/AQrTKyIhrLZxtW8tj8LwEqtdCU1Zb59dR3OaNTN3q1aBvROETkaEpEJCFYlsVJ7btwUvsuboeSMI5t0oISX+C1agDSkpJom9ko4rE8MX8aHsv2W9QOzDTupxfM4OmfXRXxWESkMrVJi0jYOI5DflEhXp+Py3r0o16QVXyTbJtreg2mfkpoK/3WxoItPwRMQsBM456/eWPE4xCRo6lFRERqbc+hfB7++nOeWTSTvQUHSfF4uLLHAB4Yfi6//vw9LKtyl4jHsmmT0ZAHhp8XlfhCKSiXnpQchUhE5EhKRESkVnbk5zHkhb/zw77d5a0ORV4vr66YT8qqJB4fdSlvfruQOT9tACAtKZlreg3igeHn0aJBdJZuuOC43vxn0UxKfP5bRWzL4vzjekclFhGpTImIiNTKXZ+/y48VkpAyJT4fjlPMP+Z9wYbb/8KO/P3sLyygdUbDqHTHVHTbwNN4dvEsLCwcKo+etS2LzNQ0rj9xaFRjEhFDY0REpMZ2HzzAm98uoCTA+Auv4/DDvt188f0aWjbIokuTFlFPQgC6NmnB5Mt/SXpyMmUTuMv+3zA1nc+uvkMVdkVcohYREamxNbu2BezuKOOxbJZv/4mRndwtHDeqcw82/epvTFwyhzk/bcC2LEZ0PI6rew2kQYrWvRFxixIREamx9OSUKvdxcEiLkYGgjdPrc9eQM7iLM9wOJeY5jsNXG9fwyXffUuQtoW/r9lx6fD/qhfA7F6kOJSIiUmMntGhL64wstgSpjuo4Dj/r2jOKUUltbc7byzmvP8my7T+RZNtYWBQvmM6vPnubdy65mdOP6eZ2iFKHaIyIiNSYx7b5/bCzAm+3LC47vj8dGjaNYlRSG8VeL6e/8hgrd24BzKDj4tLCdHmFBfzs9SdZuWOLmyFKHaNERERq5Zf9Ty1PRjyWjW1ZJNnmo2Vkp+48f94YN8OTanp/zdKAY3/K1uh5dK7W5pHwUdeMiNSKZVk8OGI01/YezMSlc9i4bzdN0utzZc8BDG57DJZluR2iVINZrNDCG2DV5BKfj7dXLuS/54+NcmRSVykREZGw6NKkBX8dcYHbYUgtHSgqDJiElDlUUozjOEoyJSzUNSMiIuW6N2uFxwp8abCAro1bKAmRsFEiIiIi5W7qMwxfkAUCAcYNODU6wUhCUCIiIiLlujRpwYTSLjb7iFYP27IY3vE4bup7khuhSR2lMSIiYVZQUsw7KxexaOuPpHiSOLtLD05p31VN2RI37h42ik6Nm/HXWVNYsm0TAM3rZ3DbgOH8ZsjIkFYzFgmV5ThVjEpyUV5eHllZWeTm5pKZGZ1VOkVq46uNa7jk7WfYU3CQZNuDg0OJz0ffVu348IpxtMrIcjtEkWrZmb+fIm8JLRtk4bHViC6hqc71W+8qkTBZtXML57z+BPsKDwFQ7POW12JYtv0nznjlMYq9XjdDlAjZffAAK3dsYfuBPLdDCbtm9TNok9lISYhEjNrXRMLk4TlTKfH58PlpZCzx+Vi5cwsfrlvGhd36uBCdRMKaXdu458tJfLB2Wfnv/fSOx/HgiNEMaNPR5ehE4oNSXJEweWflwqAr0Xosm3dWLY5iRBJJK3dsYeDzE/hw7fJKyee0H9Yx7L8PM/2HtS5GJxI/lIiIhIHjOBwqKQ66j9fxcaCwIEoRSaT94uPXyC8qwnvEVFev48Pr+Lh+8ktVToMVESUiImFhWRadGzUj2LwYj2XTrVmrqMUkkfPd7u3Myll/VBJSxuc4bNy3m+k/rItyZCLxJ6KJyNNPP02vXr3IzMwkMzOTwYMHM2XKlEieUsQ1v+x/KgRJRbyOj5v6DItaPBI53+3ZEdp+u0PbL9ZtztvL6p1b2a8WPYmAiA5Wbdu2LX/729/o3LkzAC+99BLnn38+S5Ys4fjjj4/kqUWi7pZ+JzNpzVJm5XxXacyAjYUPh7+eNpouTVq4GKGES1Zqekj7ZaamRTiSyPps/Ur+NP1D5m/eCECqJ4krew7gryNG07KBpqJLeES9jkjjxo15+OGHueGGG6rcV3VEJN4UlBQzYdYUnlo4g10HDwDQs3kb7j3pLC7r0d/l6CRcSnxe2v3zHrYeyA24T1pSMtvuepistNCSlljz+opvuPp/L2BZVqXE2mPZtM7IYv6N96gujgRUnet31Kbver1e3nnnHfLz8xk8eLDffQoLCyksLCy/n5dX9+bkS92WlpTM/cPP44+nnMOW/bmkeDy0qJ+pqqp1TJLt4YHh53HTh68E3Oe3Q0bGbRJyoKiAmz58BQczELsir+Nj6/5c/jBtMi+cd407AUqdEvFEZMWKFQwePJiCggIaNGjApEmT6N69u999J0yYwP333x/pkCSO5RYc4umFM3hu0Sy2HNhH0/QGXHfiUG4bMJxm9TPcDq9cku2hXVZjt8OQCLqxzzDyCg9xz5eTKPb6SLJtvI4PC4u7Bp/On079mdsh1thb3y7kUHFRwO0ljo/Xls/nsTMvJSPOu5/EfRHvmikqKiInJ4d9+/bx3nvv8fzzzzNjxgy/yYi/FpHs7Gx1zQgAO/LzOGniI6zfs+OIpmKLFg0y+fr639KhYVMXI4wlBYAPSCfYAFqpvT2H8nnz2wVsyt1L8/oZXNajH60zGrodVq3cPfU9/jnvS4p9wSsBr771fo5r2jLs59+Zv58P1y1nf2EBxzVtyenHdFNl1zgTU10zKSkp5YNV+/Xrx4IFC3j88cd55plnjto3NTWV1NTUSIckceqXH7/Bhj07j6pc6nUcduTvZ8z//sus63/rUnSxYjHwGfBD6f2mwOnAKcTfbH0vsBLYDqQBJwCx94WkcXr90hlTdUdWWrrfCsFHCvdg3BKfl998/h5PLphGic+HXTo+pW1mI14efR3DOx4b1vNJbIj6J5PjOJVaPURCsWX/PiatWRKwbkOJz8fsTRv4dsfmKEcWSz4BngF+rPDYLuBN4AVMC0lt7QQ+BF4vPd+eMBzTn1XA74B/A+8BrwJ3A29hEhSJpIu69Qn4twZgWxaD2nYMe8vPbVPe5PH5X5ZXKC5Lhrbs38eZrz7Ogs0/hPV8Ehsimoj8/ve/Z9asWfzwww+sWLGCe++9l+nTp3PVVVdF8rRSBy3Zuimkb2iJ+0G1GZhc+rO/12lh6a2mfMAbwB8wCchsTELye+B/Ac5ZUxuAJ4D9pffLju0DpmESK4mkY5u25Ioe/bH9DLK2MF8o7z/1vLCe8/u9O3lm4Uy/7ySf4+BzHP40/YOwnlNiQ0S7ZrZv386YMWPYunUrWVlZ9OrVi08//ZQzzjgjkqeVOigpxP7hZI8nwpHEqhmY7xWBvsVamIv4gBoe/wNgeunPR57jM6A+cGbIR8vJ3cMzC2fy2YaVeB2HU9p34Rf9TuHYpi1Lz+XgP7lxgJml59J4oEj67/ljAXjj2wV4LBvbsijxeamXnMpz517NyE7+Jx3U1JvfLsC27IAtMV7Hx6frV7LnUD6N0+uH9dzirogmIi+88EIkDy8JZEh2J9KTkoOu5+KxLE7reFwUo4olPxG868UBttTw2IeAL6rY51PgNCC5yqN98t0KLnzrP5T4fOUXnW93bOaJb6bx2oWXcHmPNSHEdD/QGjgZk1xVfV6pnrSkZF6/6EbuO/Vc3l21iLzCAro2acGlx/elQUr4Z8rsOngA27LwBmlcc4C9hw4qEaljolZHRKQ2MlLTGDdgOI/MmYrj55uyx7K4sufAuJ+tUHOplDaaB9mnphfrVUDwBf3gIPAdEPxb8qbcPVz41n8o8pZUirRsTMB909/m8h6hxFSEGQvzMvA1cAfmNZBw69qkBb8/6eyIn6d9VpOg41IAkm0PzWNomr6ER7wNo5cE9uBpo7mw24nA4a4aj2X+f3L7rjx9zpWuxea+EwmehNhA3xoeO9TB5VXv98yimZT4vAEj3ZFvUeILdbpx2VG+xwxolXh2Zc8BeIIU/kuybS7v0U91S+ogJSISN5I9Ht655OdMH3sXV/YcwKntu3Lp8X2ZctVtfHHNndRPSeRvxAOAhvj/k7YAD6brpCZCXTG46v2mfr8ab5BBx3sLHCavSaJ6H00OplXkUDWeI7GmWf0M/nb6hX63eSybrNR0Hhge3gGyEhvUNSNxxbIsTunQlVM6dHU7lBiTBowH/oWZslt2IfeVbvsFUNMF9zoAbTBjTPwlETZwDFB1YSufr+rZNX+bncJF3cEkFqFOOS4BNgF6X8Sz8YPPoFFaPf40/UM25e0FTBp9Zqfu/Ousy1WwsI5SIiJSZ7QAHgCWAasx9TaOAfpTu/ETFnAt8AhmrEjF5MDGJDpjQjrSKR26smTbpoBjAZJsm06NuwGjMTVDviX0qcFq4K0LrjtxKGN7D2bx1hzyCgvo0rg52VouoU5TIiJSp3iAPqW3cGoH3AN8DCzCJCMeTJfQOUCzkI5yS7+TeWzelwG3l/h83D7wtNLjjQP2AmuAF6s4ciqQHVIMofseM+V5PSbJ6QmcSigtP1I7tmXTr3UHt8OQKFEiIglr18EDfPH9agpKijmhRVtObNXO7ZBiXCvgRkzrx0FM7ZCUah2hc+PmvHzBdYyZ9N/SuhSmZSTJtinx+Xh05MUMye5U4RmNgMHAfGAt/rtqLEyCEM4xQp9jBsBWrM0yo/R2M9A7jOcSSWxKRCThFHlLuOvzd3lm4cxKi3r1bdWOVy64nm7NQh2cmahSqc1F/8qeA+jZvA1PfPMVU9Z/i89xOKV9V24bMJzBlZKQim4A/oEZp1I2TbksSegJhHMQ4zoOz8KpmPiU/fws8CAmSRKR2or46ru1UZ3V+0RCdcW7z/H2qkVHlYw3I/PTWHLLH2mnPukYVIwpUz8PyMN035wEHE94x4c8BawgeJXaswlv8iNSt8TU6rsisWTB5h94c6X/NVe8jo+8wgIemv0p/07omiSxKhnTTTM4wudZR9VVatdGOAaRxKFh5pJQXl0+P+i6NSWOjxeXzSWGGwol4kIpqBZq0TURqYoSEUko2/PzqlzF92BxUdA1baSuO47gH41W6T4iEg5KRCShtMlo6Hdp84oyU9NIT9IiajXnADnAEsz6M6EWJYsVpxN8fEgSZmyKiISDxohIQrm29xD+MS/wSrIey+bGE4dhVZGsSCDfAa9TeaXfhsCFwEA3AqqBTsDlwJtUnr5rl95uAbLcCU2kDlIiIgmlZ4s23Nz3ZJ5dNPOoep0ey6Z5/Qx+M3SkK7HFv/XAPzm6NWEf8F9MGfahUY6ppoYDXYDpmOTKA/QATgGauBeWSB2kREQSzr/PvoKWDTL5x9yp7C8yK8ZawOnHHMez546hZQN9262ZtzFJSKAxOO9gys1Xrwiae9oCV7sdhNQpDvADsByTmGdjVs5O7K5g1RGRhHWwuIjZOespKCmmZ/M2dGykBbVqbhvwpxD2+znQN8KxiMSiA8B/MC1sNubrjxeoh/m76OZeaBGgOiIiRygsKWb3oXyyUtOpn2KqgtZLTmFkp+4uR1ZX7AthHwuzdoxIovEBT2AGcZfdL3MIeBKzllPbKMcVG5SISJ22OW8vf575CS8tm0tBSTG2ZTH62N783ynncELLcC+SlshCabF00CBPSUyrMF0y/jiYxOQzzFIGiUfTd6XOysndQ7/n/soLS2ZTUFoXxOc4TF67jEEv/I3ZOetdjrAuaYX5NhdstlEq0Cs64YjElMUEv9z6MKtax+xIiYhSIiJ11u1T3mTXwQPlK7yW8To+irxervrfC/iceKtxEass4OIKP/szmvCukCsSLwqoOsnwlt4SjxIRqZO27s/lg7XLj0pCyvgch5zcPXzx/ZooR1aXdQPGcfSqtPWAK4DToh6RSGxoTtXLAjSkeqMlHGAXsBUoqllYMUJjRKROWrt7G04V30Bsy2LVzi0asBpWPYAHMTMDdgENgO4k+vTEqvmAlcA3mNkVTYFhQHs3g5KwGQZMCbLdAk6txvG+AT7GzFYDMyV+GGZF6PQaxOcuJSJSJ9VPrroLwOc4Ie0n1WUDx5bepGoHMbMmNnC4kqsNzMQUULscNV7Hu6aY6sL/wyQdFb8kWUA7YESIx/oUmHTEY0WY4nvrgN8AabWINfr07pY6qU+rdrTJaBh0H49lc+6xGjwpbpsIbCz92XfE/2cAU6MekUTCmcCNmIHdZdKAM4DxhFbobzfwfoBtPmAz8fh+UYuI1Eke2+b/TjmHmz96ze9227K4qe8wVVEVl23DVNkM5nPMQnyeyIcjEdYf6Iepu1OMGU9VnW7Lrzm6RaUiB9OS9jOqHpMSO9QiInXWTX1O4i/Dz8e2LDyWRbLtIck2b/krewzg8VGXuRyhyCqqvmAcADZFIRaJDguTgDSn+mOntlP17Js8TJITP9QiInWWZVnce/LZXNt7MK8sn8+P+3bTpF59ruw5gO7NWrsdnghmvZFQJOa0TjlSOsFbRMC0nMXXpT2+ohWpgTaZjfjdsFFuhyHiR3uq/oabROVxBZK4+gKzgmy3S/eJr86O+IpWRKRO6Qq0IPBHsQ0MwtRiETkO6IT/94tV+viZUY0oHJSIiIi4xgJuxsyeOPLj2MK0hFwU7aAkZlnArRyeGm9zeBBzfeA24nHhPHXNiEgQJcC3mGmD9YETiMeCSbGtDfBH4AtgHmY11kaYGiKnEG81ISTS6gN3YgYwL8MMTG0LnEi8XtLjM2oRiYLFwGuYWRtlA+SSgbOBs4in6YGxrzFwaelNJBTZpbf4F9GumQkTJtC/f38yMjJo3rw5o0ePZu3atZE8pYiExQrgGUwSAocHVBYDkwlerlpEJHQRTURmzJjBrbfeyrx585g6dSolJSWMHDmS/Pz8SJ5WRGrFAd4jeIvHx5guBBGR2olo18ynn35a6f7EiRNp3rw5ixYt4uSTT47kqUWkxraW3oIpAZYCgyMejYjUbVEdI5KbmwtA48aN/W4vLCyksLCw/H5eXl5U4hKRig5UvQt2iPuJiAQXtem7juMwfvx4hg0bRo8ePfzuM2HCBLKysspv2dl1YyCOSHzx/0WhMl+I+4mIBBe1RGTcuHEsX76cN954I+A+99xzD7m5ueW3TZu0voJI9DXFFNoKNkakHqCVi0Wk9qLSNXPbbbfxwQcfMHPmTNq2DVxsJTU1ldTU1GiEJCJBXQL8HbPGic/P9iuo/oJdIhIbHOA7TLn4rZgvFgNKbylRjyaiiYjjONx2221MmjSJ6dOn07Fjx0ieTkTCph3wW+AtYH2Fx1sAFwK9XYhJam4vZnn4lZjEsgumWFpLN4NKEA5mhpmDueC7XX/Hh6kPNBvTKeLDxLQWMy3/LqLd7RrRROTWW2/l9ddfZ/LkyWRkZLBt2zYAsrKySE9XdUaR2NYO+A2wE9gFNMBUcHT7g1SqZyXwFKZ1q6wezGZgGnANMMSluOo6B1Mp93NgS+ljLYDTgWG4t8LKV5gkBA63dpa9L/Zg3iv3Es2/c8txnKqWfqz5wS3//5CJEydy7bXXVvn8vLw8srKyyM3NJTMzM8zRiYjUdfswF5WKSUhFFnAPZhVgCa93MGX7y6oSVzQUGEP0k3of5ve9r4r9fgN0rtWZqnP9jnjXjIhE2kFMs2oJpuSzmtulzEwCJyFgLoRfAtdHLaLEsA6ThID/1/5rzNowPaMWkbGTqpMQG1hNbROR6tBaMyJxywv8D5iOSULKdAGuxcx+kcS2msBJCJhvyKv8PO4APwI/YC5M3dH7qTpmcnj8hT825u822olIoHhqul94KBERiVsTgYUcfaHZADwE/AHIinZQMcbBfDvdgPnwPw7o4GZAURbKBeXI98924Hkg54jH+2DGlGh8X9U2Efy19wE/RSmWipphVu8NtsyKD+gUnXBKKRERiUsbgQUBtvkwVU+nAhdHLaLYsw14uvT/ZQMDJwHHALeQGElaV0xCEeybedcK93OBh/F/oVoC5GFmVbg10DJehFKGwo1SFUnAqcAn+G8pszEzZrpHMSa9m0Ti1FyC//n6MP3QiSoPeATYUXrfx+GL8Q/Ao0BR9MOKuqrW9PIBp1W4/xUmCfGXuDiYqdwrwxNandaX4ANRrdJ93HA2hxONijHamNauXxLt1ECJiEhcyqXqZveDmHEkiWgGplXI32vkw3Q/LIxqRO5oBlyH+aiv+HFf9vOFmDFFZeYS/H1lA/PDGWAdNRRTM8TfJdbCtIa4tfBrEnAr5n3REdNV0xQ4C/gT0MaViEQk7mQRfDAcmA9CT3TCiTnzCT5I0yrdJxFqaAwAWmNaOyoWNDuNo2dGBBs7QOlztRhp1RpgurD+hZmlUpaQ+Eq3jQMauRKZ4QEGld7cp0REJC4NwXzrD8TGfCuryiFMy0ED6tYgxINVbHeo+qJbl7TFDDStSiPMFM9AbDR7JlRtgL9ixtasxbznumAG/Wp5hIqUiIjEpQ5Af/zPmrExicUZQZ6/BfgQWIr5lmZjyrafi/n2HCn7MQnUPEyy0AzTRD2Q8H4cNSs9fqBWERtT5VIqOwkzoDfQ6+YjtARXDA/Qr/QmgSgREYlb1wENMfUIiis83gXz7TfQrJAczEDOYg537fgwSclKTFXF7HAHixmX8QgmGSm70B0EXsYkJrcRvgW3Ti49biA+zEU3WrxAAZBGbHeXnYL5XWzDf7ffQMyso9rKw3QVzcG0yGVhyp4Px3QpSiKJaIn32lKJd5FQHKJyZdWqvun/BVPDIFDJ77aYGiTh5AD3Y5IRfxc4C7MGR7imG3uBxzE1RPz9OwdiErlIl9jeg1lIbC4m8UvCjNk4G9NqE4vyMYsdLuDw7yoNGAH8jNrPcdiFWdl5P5XfCxam2+e3gD7v413MlHgXkWhIJ/TVcHMwxZYCcUq3byK8rSLfYZYbD3bemcB5hKdVxINpYfmg9LgFpY+XdVmNJPJJyA5MYbmDHL7glmBaHJZgWp6iP0OhavUxJd8vxSSsHsxaNOFqrZrI0UkImPfAbuB1TJ0XSRRKREQSyvYQ99tGeBOR76l6lk8hZuxKhzCdMxm4CDPupayoWSui1zXyCpWTkDI+zL/1RcyCdLGqAaYSbThtxtQiCaSsi3Av7s4qkWhSHRGRhJIW5v1CFWrrQyQ+klKAdpgup2glIdsx3UKBEi8fpnXqyDLqdd2PIezjkHivS2JTi4hIQjkWk2QUBNknrXS/6jiEGXi4ANMK0AozGPR4TBLSDbNAXzD1ieyMnWjaHOJ+WzBJUqII9ZITywN6JdyUiIgklBRMBcVJQfY5i+qNB9iJmQ2z74jHlmIGhV6Ludh2xnTRBGolOJ2685EU6uuXaPUkjqXqLrpkorkEvbhPXTMiCedMYBSmpcLCfPss+3lU6fZQOcC/ObraZtmFZj7wZenPPweal/5c1lVT9hE0oPTcdUVXql7ULIloLy7mvixMNc9AXXUWZlG2cHcNSiyrK18/RCRkFnAB5gP/G8y6NVmYZKC6AwTXEHw2DJhVgEeUnuNeYBEmQTmAmWo8DDMoMtKzWKIpBZPQfRBkn9OoW9VsQ3UFZjDqag63jpT9/0TMe1MSiRIRkag7AKzCzJxojSkQ5cZFuBHVa/3wZx1VN7XnYrpqWmAu0INLb3XdWZhpqtOo3Pjsw5ToH+1CTLEgBbgdk8TOw7w/GmNek87UrYRUQqFERCRqvJgBm9OovCpuS+AG4nPQYszWQ4wBNnA5plroXMwYmkxM10RdGZRbUzamWyrRuqbEHyUiIlHzKuaCdOTFewdmsOfvMUlJPOmCqRwaTAaJvVBaC2Kv9WMvZuzOXEwl1YaYWU6J2l0kbtJgVZGo2IKZ3uqvBcGHKf/9cVQjCo9umFLlwT5KRqDpmLFkG6bM/5eYbkIHk5h8CEwofUwkepSIiETFNwT/c/NhVtItDrJPLLKBcZgaINYRj4MZfDgy2kFJQA7wPP4rvjqYsTxvRjsoSXDqmhGJiv0h7OPDFAaLt9oSLYH7gFmY2TCHSh87BbMGjr7vxI4fCL7WkA8zq+lSqr/wXDEmmQnXmjSSKJSIiERFwxD2SSJ+l0BvgJklcpbbgUhQoZRY92Eqw4aaiCwGPgc2lt5vhVlYcAg1mwGzHvgC+BaT2HTAdO+dWMPjSaxTIiISFYOBj4Jst0v30Z+kRFK4S6x/jKmVUjFB2Aa8DGwAxlC95GEWZlB3xSnhGzDJyWmYlholI3WNPvVEoqIppnLop3622ZgxFmdXcYx8zIDXFZjpv8cAJ2MGi4qEojvmQh5s2nU60DGEY+VwuGBbxeOV/fw10AvTPReKHcBrpT9XHL9SdryvMIXvTgjxeBIvlIiIRM1oTBfGFExSUeY44EpMUadANgKPYxarK/tg/h5TtXQMMDTMsUrd1BjohxkYHSgZOZ3QxinNIHgxOxuYTuiJyEyCJ0k2pgaPEpG6RomISNRYmL7z4Zjm5iJMf3pVNTYOcnQSAocvAC9jBod2CmewUmddjRk8vYajS6wPpuqWuTI/Eryiro/gA2OPtDGE420Msl3ilRIRkahLwqxCGqq5mJkogdiYwX1KRCQUacAdmERkPiYpaYJpVetQjeNUtagfVG8GWCjjUlSPpi5SIiIS81ZWsd0Xwj4iFYWjxPqJmJa9YF0pfapxvJ6YtYuCHU/dMnWRJviLxLxgzdXV2UcknIZgBln7u4xYmNaL4dU8XhrBZ8WcVo3jSbxQIiIS86pandcu3UckmuoB4zFrCYF5H5ZdUlKB26jejK76mC6jI9e6KUtqbgSyaxqsxDB1zYjEvJMw0369Abb70DdFcUcb4EFMUbPVmG6VTsAATOtGdXUE/grMw3Q3+jBJ9jBCKwoo8SiiLSIzZ87k3HPPpXXr1liWxfvvvx/J04nUUY2A66j8jZMKP5+O+s7FPcnAQOBioDWm1s3fgZcwJeWrKx3TpTMOuB34GUpC6raItojk5+dzwgkncN1113HRRRdF8lQidVx/zBTdL4HlmG+KHTClr3tQdbXJsrLdhUBzqr+OiEgwOcA/MbO7ygabbsUkJecA57kUl8SDiCYiZ511FmedpbUnRMIjG7i2Bs+bjSkvv7f0vo2Z8XAp0fum6cOU6c4rPecxaIhaXVEM/IvAdW4+BtpSvRk0kkhiaoxIYWEhhYWF5ffz8vJcjEakLvgEmHzEYz5gCaYy6z1AVoRjWAy8zeFECEzdissxJcBDkYtJqH7EDFw8HjMOQSu9um8RwVeXtjCL4ikREf9i6ivJhAkTyMrKKr9lZ2uEtEjN7eXwWiBH8mEu7p9EOIZFwDNUTkIAdgNPYbqZqrIQkzB9CCzDJFGvAPdiupvEXWUVWgNxMBVRi6MTjsSdmEpE7rnnHnJzc8tvmzZVpzywiFQ2t4rtPkwffqDZOLXlA94Kst0p3R5sAbYfgRcwMZbtV/b/A5hxCQW1C1NqKdjvryb7SaKJqUQkNTWVzMzMSjcRqandVD2ItYjKC/CF01pMq0swuzBdRIF8EWSbD9Ml8E0145Lw6kTwgnoWZoyIutHEv5hKREQknOqFsI9Nzeo9hGJfGPZbRtUXuVC6dyRyBmCm3AZKeh3MFHMR/yKaiBw4cIClS5eydOlSADZu3MjSpUvJycmJ5GlFBDAXiGAXcRuzRHukvqmGOgg22H5VdRs5QEmI55HISAN+iakn4q/OzcnAoGgHJXEkorNmFi5cyPDhh9caGD9+PABjx47lxRdfjOSpRYRsoC9m1sqR/fMW5kIR6pLvNXEspl5JsNlvjQlenr4dZqBjsIXQ2tcoOgmnrsCfgOmY91sx5v03nNDq3Egii2gicuqpp+I4GqAk4p7rMOt+zMVczG1MK0lD4Hoiu3aHB7gEM9g0kMsI3jB7GvB8kO0OpgS+uK8pprrq+Zjfi8aESGhiqo6IiIRbMjAWOBczlqIIU4a7O5EfIlaAWX+kLPmpKAtTR6R3FcfoB6zCzO6xONwyUnbMqzEXQDGKge8wFXRbYarxRssiTL2QH0rvtwHOwHTLqEVEAlMiIpIQGgOnRvF8xZiptTkcnYRYmItk7xCOYwHXAMdhytvnYJKQHpiLXJfwhBv3HOAzzOKIhyo83hkYQ+QTksmYmjQVE44twIuYWVFXomREAlEiIiIRMJ/AC545mCJYyzCl5qtiYRZVG1j6XF3QjjYJk4gcaQPwAGYMR3tMN1a4W5A2crgwXsWu+LKfZ2Iq6PYM83mlrtD0XRGJgFkETxhsTMn26vJ3TC+wDlhKYlZa3YX/JARMMuDFdJF9DvyB4LVZamI6wS8lduk+Iv6pRUREImAPwStp+jAF12prNqZboOLMnHbAVZjViRPBfPyPwzlS2fZ3MK0ivcN0fn/db0eeVyUbJDC1iIhIBGRUsd2i9ovtfYVZc+bI6cGbgEdK/58I9lG97ioLM5YkXEKZHaMZNBKYEhERiYAhBL84OsDgWhz/EPC/IMf2Au/V4vjxJJPqreNStghduEr796HqbjitvCuBKRERkQgYimn+9/cRY2PWHulbi+MvIvhqrj7MuIh9tThHvBhI1d0y/oSrIu1QTIl3f79rCzMC4NQwnUvqIiUiIhIB6cBvMLM1jtQDGI+pcVJT+zAF00LZr65rDpxSzedkUnX3WagaYH6fDUrv2xy+tKQBdwBNwnQuqYs0WFVEIiQL+BWwDViP+XbcFWgWhmNnUvU6NGX7JYLLMYscfkHwliIwv4fhhPd7aDbwV0xL1RpM909nzHpHqWE8j9RFSkREJMJaEv6CWn2ANwmcjFiY5ekbh/m8scoGRgNnYrqkNmAG80LlbpuyZPCMCMSQjKmiqgXupHqUiIhIHGoAnAN84GebVXq7MKoRxYZ0TJLWB5MQTMW0UpRgunCGY1bD1Ue/xA69G0XqJAdT5Gtd6f0umNVw61JV0rMxH2EfY9ZWKdMEUxa+kxtBxZBszMKG12NaRTQkUGKTEhGRuHAAUzn0AGY2ygkEHuy5E3gKs9ZH2cXHh+ke+SXQIpKBRpGF6YoYDqwEDmLGn3ShbiVc4aAkRGKXEhGRmObDdD98jhkPUVZBsx5mIbH+R+x/CHgUyK3w/DI7Srf9CagfuZCjLoXQ1qwRkVikNFkkpn0ATOHwoMyyxOIg8Dyw/Ij952CmrPqrK+HDVCGtyRovIiKRoUREJGYdwLSEBGJhVl2tWFXzG4JX2XRK9xERiQ1KRERi1lKC18pwMONAtlV4LJSy3QdrEZOISHgpERGJWfmE9idaMfloWcVzbOrOYFURqQuUiIjErKaEtoZIxaJdp1TxHB+mjoSISGxQIiISs3phZscEYgPdqJyIHA/0C7C/hZld0jscwYmIhIUSEZGYlYyZogtH18WwMdNWL/Xz+A3ABVRe1KwBcC5wE/qzl9orxow1qsmqvyKVqY6ISEzrj1nB9H+YgalljgMuAVr7eY4NjMKsJ7IDM6i1BaGtViumSusizGtXH+hL4qxZU5UNwCeYAnIOJtk9BRiJFreTmlIiIhLzegI9gO2YKb1NgEYhPM8DtIpgXGU2Az9hWnCOI3h3UqybB7yOSUY8mG/87wHDgCtI7GRuMfAspnWubIr4fkyJ/RXAeEzSLFI9SkRE4oJF+Fewra3twIvA9xUeS8KUXL+A+LtoLwcmVrhfcer0bMzv4KqoRhQ7DmFeG4ej69Q4QA7wKWYFYJHqUWexiNTAHuAh4IcjHi8BvgBejnZAYTCZwGvUOMAsYG/0wokp3wBFQbY7wAyC170R8U8tIiJSA59hviX7G6zoYLo4TsesABtue4CZwOrScx2LmZLcrBbH3InpXqrKYmBELc4TrzZjWriCJRoHMV01DaMRkNQhSkREpJp8mDVtgs2YsIG5hD8RWQY8g0lAys6/CdMKcwOBpy5XJZRqszYm+UpEKQRfOqBMoBWhRQJT14yIVFMxwZvpwVy08sJ83l2YJMRL5STIV3p7gcozi6qjCVV/HHqB5jU8frzrTfDE0wI6UbdWdZZoUSIiItWUTGhTNYsx3SjhMoOqv5VPr+GxG2CKvQX7SEwncYvBdSq9BXp9HODs6IUjdYoSERGpJhsYQvCPDwezaN89wJOEJyFZSdXl67+txfEvxHyjP/LfZZXexmC6KBKRBfwSaF963y69WZixI2MwU8xFqk9jRESkBs4EFmIW3KuquuZK4G/AvUBWLc4ZShXPUMYxBNIUkzj9DzMotex8HYDzgO61OHZd0AC4G1gLLMHUWmkFDAYyXYxL4p0SERGpgUaYi9LLwLoq9vVhZlN8xtEl6aujK6Z2SaCExAa61OL4YMaK3IRJsPZhumNUVfUwC1O07ji3A5E6RF0zIlJDzYC7gPuBEwhcgwNM8vA1tVub5FSCt3j4gNNqcfyK6gNtUBIiEnlRSUSeeuopOnbsSFpaGn379mXWrFnROK2IREVLQhu8WkDVs22CaQ1cjUl4Kn50lf18GaYbRUTiScQTkbfeeos777yTe++9lyVLlnDSSSdx1llnkZOTE+lTi0jUNCB4iwiY2Ta1Hew5DDOOoz9mXEIG0Af4LeFrDRGRaLIcx6nN6K4qDRw4kD59+vD000+XP9atWzdGjx7NhAkTgj43Ly+PrKwscnNzyczUYCiR2PUj8Ncg28tm2oyJTjgi4qrqXL8j2iJSVFTEokWLGDlyZKXHR44cyZw5c47av7CwkLy8vEo3EYkH7TFVTf21itiYrptRUY1IROJDRBORXbt24fV6adGiRaXHW7RowbZt247af8KECWRlZZXfsrMjsU6FiETGtcBJHP2x0gr4NbVbC0ZE6qqoTN+1rMrfkhzHOeoxgHvuuYfx48eX38/Ly1MyIhI3koGrgHOBVZiBqdmYAaRVjR8RkUQV0USkadOmeDyeo1o/duzYcVQrCUBqaiqpqaGMvheR2JUJDHI7CIkrPkyBtFRUVSLxRDQRSUlJoW/fvkydOpULLrig/PGpU6dy/vnnR/LUIiJ1hANsxbQyHcLMUOqNKSoX73YDn2JWai7GzKoaDJxF3fj3SSgi3jUzfvx4xowZQ79+/Rg8eDDPPvssOTk53HLLLZE+tYhInFsAvIup8lrRW8BQ4Arit0D2NuAhTH2ZskJ3RcAsTIn9u9G4osQQ8XfwZZddxu7du3nggQfYunUrPXr04JNPPqF9+/ZVP1lEJGF9CbwdYJuDqVTrxQwSjkcvUjkJKePDlNh/GVO5V+q6iNcRqQ3VERGR2OBguhEcTNl3T4TPl4dpEQilJP4DwNFj7mLbT8CfQ9jvfkzlXok31bl+x2ubnohIFDiYroLPgZ2ljzUAhmPqokTqI3QuoSUhNqb75mcRiiNSfgpxvy0oEan7lIiIiAT0LvDFEY8dAD4CvgduJTKtIzsxSUYoyUh+BM4faaGW+k+OaBQSGzRPSkTEr40cnYSUcYCVwPwInTud4CsNV4wjHgd0HkfV34NTgK5RiEXcpkRERMSvWQT/iLSA6RE6d39CS0RsYECEYoikephFCoMVujuD0FZ1lninRERExK+tBO8acYDtETp3O6BXCPtdghmzEo9Gc7jwnY1JSsouSScRf+NepKY0RkRExK90zMUxWMtEWgTPfxPwErDQz7Ys4GLiszWkjAcz9fgMzODcXKAhpqBZa9eikuhTIiIi4lc/zDiQQGxMF0qkpGCSkfOApcB+TJdGD8waPnVl/Z42mKRKEpUSERERv/oBn2DqhxzZRWNhEoXTohBHC+DMKJxHxB0aIyIi4lcKMJ7D3QQ2h6fqZgK/whQ3E5HaUIuIiMS5A5hy6F9jui8ygGGY1oraDuRsDPwBWAesxpRUPwYzkDTS1VVFEoMSERGJY3uAv2MGOpZ1n+RiulTmAr+l9qu4WsCxpTcRCTd1zYhIHHuJyklIGQezYu3L0Q5IRKpJiYiIxKntwBoC1/rwAas4vEaMiMQiJSIiEqd+DHG/nIhGISK1o0REROJUqEPcNKhUJJYpERGRONWVqpOMJLRwmkhsUyIiIsAW4CvMNNgf3A0lZA0w03QDVRi1MGuW1ItaRCJSfZq+K5LQ9gPPYwZ9ll3QHaA98HOgqUtxheoSYC+wHPO9ylfh/yeg0uEisU+JiEjCKgb+AWwrvV9xcbdNwMPA/wH1oxxXdSQDvwS+A+ZQeeG0LtSd9VhE6i4lIiIJayGmS8YfH+aiPgsYFbWIasbCjAPRWJDgVmO6377HtBr1xFSfbetmUCIaIyKSuOYRvMXAwbQySPybDDwGfIspiZ+HqTz7ILDIvbBEUCIiksD2U7k7xp/8aAQiEfUtpuQ9VC7+5iu9vYAplS/iDiUiIgmrOcE/Aixif7CqVO1Lgv+efcDsKMUicjQlIiIJaxiBy6ODaS05KUqxSORsoOrf83dRikXkaEpERBJWd+BE/I8TsYBOwMCoRiSREMrMIVWfFfcoERFJWDZwE2ZWTFqFx5OBU4A7Sn+W+HY8VXfBdYtSLCJH0/RdkYTmAUYDZ2NqhzhAGyDdxZgkvEYQeGaMBaQAQ6MXjsgR1CIiIpiLUSegM0pC6ppOwNWYpKPiR35ZEnIbply+iDvUIiIiUuedhCn4NgMzeNUD9MAMWM50MS4RJSIiIgmiBXCp20GIHEVdMyIiIuIaJSIiIiLiGiUiIiIi4pqIJiIPPvggQ4YMoV69ejRs2DCSpxIREZE4FNFEpKioiEsuuYRf/OIXkTyNiIiIxKmIzpq5//77AXjxxRcjeRoRERGJUzE1fbewsJDCwsLy+3l5eS5GIyIiIpEWU4NVJ0yYQFZWVvktOzvb7ZBEREQkgqqdiNx3331YlhX0tnDhwhoFc88995Cbm1t+27RpU42OIyIiIvGh2l0z48aN4/LLLw+6T4cOHWoUTGpqKqmpqTV6roiIiMSfaiciTZs2pWnTppGIRURERBJMRAer5uTksGfPHnJycvB6vSxduhSAzp0706CBVnsUERFJdBFNRP7v//6Pl156qfz+iSeeCMC0adM49dRTI3lqERERiQOW4ziO20EEkpeXR1ZWFrm5uWRmaqlqERGReFCd63dMTd8VERGRxKJERERERFwTU5VVRSQRbAJ+AlKAbkA9d8MREVcpERGRKNkCTARyKjyWBAwHLgA8bgQlIi5TIiIiUbAL+DtQeMTjJcAXQD4wNtpBiUgM0BgREYmCKZgkxOdnmwPMwbSYiEiiUSIiIhHmBebhPwkpYwNzoxOOiMQUJSIiEmEFmC6YquRFOhARiUFKREQkwtKA5BD2axjhOEQkFikREZEI8wBDCP5x4wMGRyccEYkpSkREJApGYeqFBPrIOQVoGb1wRCRmKBERkShoDPwO6HzE46nAucDlUY9IRGKD6oiISJQ0A+4CtmOm6iYDXTEVVkUkUSkREZEoa1F6ExFR14yIiIi4SImIiIiIuEaJiIiIiLhGiYiIiIi4RomIiIiIuEaJiIiIiLhGiYiIiIi4RomIiIiIuEaJiIiIiLgmpiurOo4DQF5ensuRiIiISKjKrttl1/FgYjoR2b9/PwDZ2dkuRyIiIiLVtX//frKysoLuYzmhpCsu8fl8bNmyhYyMDCzLcjsc1+Tl5ZGdnc2mTZvIzMx0O5yYptcqdHqtQqfXKnR6rUJXl18rx3HYv38/rVu3xraDjwKJ6RYR27Zp27at22HEjMzMzDr3Zo0UvVah02sVOr1WodNrFbq6+lpV1RJSRoNVRURExDVKRERERMQ1SkTiQGpqKn/6059ITU11O5SYp9cqdHqtQqfXKnR6rUKn18qI6cGqIiIiUrepRURERERco0REREREXKNERERERFyjRERERERco0Qkzjz44IMMGTKEevXq0bBhQ7fDiSlPPfUUHTt2JC0tjb59+zJr1iy3Q4pJM2fO5Nxzz6V169ZYlsX777/vdkgxacKECfTv35+MjAyaN2/O6NGjWbt2rdthxaSnn36aXr16lRfmGjx4MFOmTHE7rLgwYcIELMvizjvvdDsU1ygRiTNFRUVccskl/OIXv3A7lJjy1ltvceedd3LvvfeyZMkSTjrpJM466yxycnLcDi3m5Ofnc8IJJ/Dkk0+6HUpMmzFjBrfeeivz5s1j6tSplJSUMHLkSPLz890OLea0bduWv/3tbyxcuJCFCxdy2mmncf7557Ny5Uq3Q4tpCxYs4Nlnn6VXr15uh+IqTd+NUy+++CJ33nkn+/btczuUmDBw4ED69OnD008/Xf5Yt27dGD16NBMmTHAxsthmWRaTJk1i9OjRbocS83bu3Enz5s2ZMWMGJ598stvhxLzGjRvz8MMPc8MNN7gdSkw6cOAAffr04amnnuIvf/kLvXv35rHHHnM7LFeoRUTiXlFREYsWLWLkyJGVHh85ciRz5sxxKSqpa3JzcwFzgZXAvF4vb775Jvn5+QwePNjtcGLWrbfeyjnnnMPpp5/udiiui+lF70RCsWvXLrxeLy1atKj0eIsWLdi2bZtLUUld4jgO48ePZ9iwYfTo0cPtcGLSihUrGDx4MAUFBTRo0IBJkybRvXt3t8OKSW+++SaLFy9mwYIFbocSE9QiEgPuu+8+LMsKelu4cKHbYcY8y7Iq3Xcc56jHRGpi3LhxLF++nDfeeMPtUGLWsccey9KlS5k3bx6/+MUvGDt2LKtWrXI7rJizadMm7rjjDl599VXS0tLcDicmqEUkBowbN47LL7886D4dOnSITjBxqGnTpng8nqNaP3bs2HFUK4lIdd1222188MEHzJw5k7Zt27odTsxKSUmhc+fOAPTr148FCxbw+OOP88wzz7gcWWxZtGgRO3bsoG/fvuWPeb1eZs6cyZNPPklhYSEej8fFCKNPiUgMaNq0KU2bNnU7jLiVkpJC3759mTp1KhdccEH541OnTuX88893MTKJZ47jcNtttzFp0iSmT59Ox44d3Q4prjiOQ2FhodthxJwRI0awYsWKSo9dd911HHfccdx9990Jl4SAEpG4k5OTw549e8jJycHr9bJ06VIAOnfuTIMGDdwNzkXjx49nzJgx9OvXj8GDB/Pss8+Sk5PDLbfc4nZoMefAgQOsX7++/P7GjRtZunQpjRs3pl27di5GFltuvfVWXn/9dSZPnkxGRkZ5i1tWVhbp6ekuRxdbfv/733PWWWeRnZ3N/v37efPNN5k+fTqffvqp26HFnIyMjKPGGdWvX58mTZok7vgjR+LK2LFjHeCo27Rp09wOzXX//ve/nfbt2zspKSlOnz59nBkzZrgdUkyaNm2a3/fQ2LFj3Q4tpvh7jQBn4sSJbocWc66//vryv71mzZo5I0aMcD7//HO3w4obp5xyinPHHXe4HYZrVEdEREREXKNZMyIiIuIaJSIiIiLiGiUiIiIi4holIiIiIuIaJSIiIiLiGiUiIiIi4holIiIiIuIaJSIiIiLiGiUiIiIi4holIiIiIuIaJSIiIiLiGiUiIiIi4pr/Bzu4NK5wBZXiAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#Génération du dataset\n", + "X, y=make_blobs(n_samples= 100, n_features=2, centers=2, random_state=0)\n", + "y = y.reshape((y.shape[0], 1))\n", + "\n", + "#Affichage des dimension du dataset\n", + "print(\"dimension de X:\", X.shape)\n", + "print(\"dimension de y:\", y.shape)\n", + "\n", + "#Mise en graphique du dataset\n", + "plt.scatter(X[:,0], X[:,1], c=y, cmap=\"summer\")\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 1050, + "metadata": {}, + "outputs": [], + "source": [ + "#Création de la fonction d'initialisation de la matrice \"W\" et de l'entier \"b\"\n", + "def Initialisation(X):\n", + " W = np.random.randn(X.shape[1], 1)\n", + " b = np.random.randn(1)\n", + " return (W, b)" + ] + }, + { + "cell_type": "code", + "execution_count": 1051, + "metadata": {}, + "outputs": [], + "source": [ + "#initialisation de la fonction de création du model linéaire\n", + "def Model(X, W, b):\n", + " Z = X.dot(W) + b\n", + " A = 1 / (1 + np.exp(-Z))\n", + " return A" + ] + }, + { + "cell_type": "code", + "execution_count": 1052, + "metadata": {}, + "outputs": [], + "source": [ + "#initialisation de la fonction cout (logloss) afin de determiner la marge d'erreur de notre model linéaire\n", + "def Log_loss(A, y):\n", + " return 1 / len(y) * np.sum(-y * np.log(A) - (1 - y) * np.log(1 - A))" + ] + }, + { + "cell_type": "code", + "execution_count": 1053, + "metadata": {}, + "outputs": [], + "source": [ + "#initialisation des valeurs des gradient de W et b\n", + "def Gradients(A, X, y):\n", + " dW = 1 / len(y) * np.dot(X.T, A - y)\n", + " db = 1 /len(y) * np.sum(A - y)\n", + " return (dW, db)" + ] + }, + { + "cell_type": "code", + "execution_count": 1054, + "metadata": {}, + "outputs": [], + "source": [ + "#initialisation de la fonction d'update servant a mettre a jour les valeur de W en fonction de dW et de b en fonction de db afin de miniùmiser la marge d'erreur\n", + "def Update(W, b, dW, db, LearningRate):\n", + " W = W - LearningRate * dW\n", + " b = b - LearningRate * db\n", + " return (W, b)" + ] + }, + { + "cell_type": "code", + "execution_count": 1055, + "metadata": {}, + "outputs": [], + "source": [ + "#initialisation de la fonction permettant de prédire à quelle classe appartiendrat un nouveaux cas selon \"x\" variable (2)\n", + "def Predict(X, W, b):\n", + " A = Model(X, W, b)\n", + " print(A)\n", + " return A >= 0.5" + ] + }, + { + "cell_type": "code", + "execution_count": 1056, + "metadata": {}, + "outputs": [], + "source": [ + "#initialisation de la fonction rassemblant toutes les autre pour former un neurone artificiel\n", + "def ArtificialNeuron(X, y, LearningRate = 0.1, NbIter = 100):\n", + " #initialisation W, b\n", + " W, b = Initialisation(X)\n", + "\n", + " #création d'une liste de suivit de la marge d'erreur du neurone en fonction du nombre d'itération\n", + " Loss = []\n", + "\n", + " #Aprentissage: Répétition de la descente de grdient pour minimiser la marge d'erreure \n", + " for i in range(NbIter):\n", + " A=Model(X, W, b)\n", + " Loss.append(Log_loss(A, y))\n", + " dW, db = Gradients(A, X, y)\n", + " W, b = Update(W, b, dW, db, LearningRate)\n", + "\n", + " #prédiction du dataset selon notre neurone après aprentissage\n", + " y_pred = Predict(X, W, b)\n", + "\n", + " #comparaison avec les vrai réponse\n", + " print(accuracy_score(y, y_pred))\n", + " \n", + " \n", + " \n", + " #affichage de la liste de suivit de la marge d'erreur\n", + " plt.plot(Loss)\n", + " plt.show()\n", + "\n", + " #renvoi des paramètre finaux après aprentissage\n", + " return (W, b)" + ] + }, + { + "cell_type": "code", + "execution_count": 1057, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[9.79688138e-01]\n", + " [6.22791607e-01]\n", + " [5.18082049e-03]\n", + " [8.88739676e-02]\n", + " [9.64849669e-01]\n", + " [3.30771238e-01]\n", + " [7.61475671e-02]\n", + " [9.67544074e-01]\n", + " [4.57105461e-02]\n", + " [7.73783334e-01]\n", + " [3.30105495e-02]\n", + " [8.15190806e-01]\n", + " [3.68744341e-02]\n", + " [1.60359382e-02]\n", + " [6.75235745e-01]\n", + " [9.89457701e-01]\n", + " [9.88236894e-01]\n", + " [3.19214556e-02]\n", + " [5.67615062e-01]\n", + " [5.53629690e-01]\n", + " [5.60677414e-02]\n", + " [3.78090404e-02]\n", + " [3.52313676e-01]\n", + " [5.30181359e-03]\n", + " [9.39871220e-01]\n", + " [3.78858770e-02]\n", + " [8.07734208e-01]\n", + " [1.39690586e-02]\n", + " [8.65599153e-02]\n", + " [7.53658384e-01]\n", + " [9.65607891e-01]\n", + " [5.26937372e-02]\n", + " [5.35192277e-01]\n", + " [9.66381696e-01]\n", + " [3.95912523e-01]\n", + " [3.05464666e-01]\n", + " [6.89238507e-01]\n", + " [5.59582898e-01]\n", + " [5.08428441e-01]\n", + " [3.16860896e-01]\n", + " [4.51492407e-02]\n", + " [1.51285886e-01]\n", + " [9.61208671e-04]\n", + " [1.77121842e-01]\n", + " [1.68126301e-01]\n", + " [8.20798139e-01]\n", + " [9.41461262e-01]\n", + " [9.23440007e-01]\n", + " [3.89208057e-03]\n", + " [1.23389526e-02]\n", + " [9.04906833e-01]\n", + " [4.19536712e-01]\n", + " [1.03402487e-01]\n", + " [5.68340945e-02]\n", + " [8.69963723e-01]\n", + " [5.28641961e-02]\n", + " [7.74660620e-01]\n", + " [7.56496114e-01]\n", + " [9.48556791e-01]\n", + " [9.84316161e-01]\n", + " [5.73324815e-01]\n", + " [2.34083446e-01]\n", + " [5.33881791e-03]\n", + " [9.21932085e-01]\n", + " [2.24979024e-02]\n", + " [3.57710691e-01]\n", + " [2.88507806e-02]\n", + " [7.09065742e-01]\n", + " [9.47263130e-01]\n", + " [3.09850898e-01]\n", + " [1.79196482e-01]\n", + " [8.65083643e-01]\n", + " [9.78336202e-01]\n", + " [1.47291503e-01]\n", + " [8.03834871e-02]\n", + " [3.38069095e-02]\n", + " [4.25549261e-01]\n", + " [8.73996450e-01]\n", + " [4.30033780e-02]\n", + " [4.15428194e-02]\n", + " [2.48388164e-01]\n", + " [1.07674416e-01]\n", + " [4.27780057e-03]\n", + " [1.54167179e-01]\n", + " [7.86249419e-02]\n", + " [1.22575801e-02]\n", + " [9.66556144e-01]\n", + " [1.25420806e-01]\n", + " [7.15793882e-01]\n", + " [9.45841986e-01]\n", + " [9.05183630e-01]\n", + " [9.74895565e-01]\n", + " [3.78248543e-01]\n", + " [8.42701951e-01]\n", + " [4.17794856e-01]\n", + " [8.41845869e-04]\n", + " [9.42413229e-01]\n", + " [9.59184874e-01]\n", + " [7.13395316e-03]\n", + " [3.26378301e-01]]\n", + "0.86\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#execution de la fonction d'entrainement du neurone artificiel\n", + "W, b = ArtificialNeuron(X, y)" + ] + }, + { + "cell_type": "code", + "execution_count": 1058, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/q1/84vf8ynd79g502ds_gw52x580000gp/T/ipykernel_80509/3911570722.py:12: UserWarning: No data for colormapping provided via 'c'. Parameters 'cmap' will be ignored\n", + " plt.scatter(new_plant[0], new_plant[1], c='red', cmap=\"summer\")\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.83940979]\n" + ] + }, + { + "data": { + "text/plain": [ + "array([ True])" + ] + }, + "execution_count": 1058, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#création d'une nouvelle plante\n", + "new_plant = np.array([2,1])\n", + "\n", + "#calcul de la frontière de déscision\n", + "x0 = np.linspace(-2, 5, 100)\n", + "x1 = ( -W[0] * x0 -b) / W[1]\n", + "\n", + "#affichage du dataset de base\n", + "plt.scatter(X[:,0], X[:,1], c=y, cmap=\"summer\")\n", + "\n", + "#ajout de la nouvelle plante en rouge dans le dataset\n", + "plt.scatter(new_plant[0], new_plant[1], c='red', cmap=\"summer\")\n", + "\n", + "\n", + "#affichage de la frontière de déscision\n", + "plt.plot(x0, x1, 'b', lw=2)\n", + "plt.show()\n", + "\n", + "#prédiction sur le type de la nouvelle plante\n", + "Predict(new_plant, W, b)\n", + "\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/ruty/img/agenda.png b/ruty/img/agenda.png new file mode 100644 index 0000000..977d7fd Binary files /dev/null and b/ruty/img/agenda.png differ diff --git a/ruty/img/home.png b/ruty/img/home.png new file mode 100644 index 0000000..0d9a1e6 Binary files /dev/null and b/ruty/img/home.png differ diff --git a/ruty/img/logo.png b/ruty/img/logo.png new file mode 100644 index 0000000..f361b63 Binary files /dev/null and b/ruty/img/logo.png differ diff --git a/ruty/img/logout.png b/ruty/img/logout.png new file mode 100644 index 0000000..e376e76 Binary files /dev/null and b/ruty/img/logout.png differ diff --git a/ruty/img/mails.png b/ruty/img/mails.png new file mode 100644 index 0000000..3eb4e73 Binary files /dev/null and b/ruty/img/mails.png differ diff --git a/ruty/img/notepad.png b/ruty/img/notepad.png new file mode 100644 index 0000000..15e80b1 Binary files /dev/null and b/ruty/img/notepad.png differ diff --git a/ruty/img/todo.png b/ruty/img/todo.png new file mode 100644 index 0000000..28c4c51 Binary files /dev/null and b/ruty/img/todo.png differ diff --git a/ruty/js/node_modules/.bin/mime b/ruty/js/node_modules/.bin/mime new file mode 100644 index 0000000..0a62a1b --- /dev/null +++ b/ruty/js/node_modules/.bin/mime @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../mime/cli.js" "$@" +else + exec node "$basedir/../mime/cli.js" "$@" +fi diff --git a/ruty/js/node_modules/.bin/mime.cmd b/ruty/js/node_modules/.bin/mime.cmd new file mode 100644 index 0000000..54491f1 --- /dev/null +++ b/ruty/js/node_modules/.bin/mime.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\mime\cli.js" %* diff --git a/ruty/js/node_modules/.bin/mime.ps1 b/ruty/js/node_modules/.bin/mime.ps1 new file mode 100644 index 0000000..2222f40 --- /dev/null +++ b/ruty/js/node_modules/.bin/mime.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../mime/cli.js" $args + } else { + & "$basedir/node$exe" "$basedir/../mime/cli.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../mime/cli.js" $args + } else { + & "node$exe" "$basedir/../mime/cli.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/ruty/js/node_modules/.package-lock.json b/ruty/js/node_modules/.package-lock.json new file mode 100644 index 0000000..5e7f140 --- /dev/null +++ b/ruty/js/node_modules/.package-lock.json @@ -0,0 +1,595 @@ +{ + "name": "ruty", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + } + } +} diff --git a/ruty/js/node_modules/accepts/HISTORY.md b/ruty/js/node_modules/accepts/HISTORY.md new file mode 100644 index 0000000..cb5990c --- /dev/null +++ b/ruty/js/node_modules/accepts/HISTORY.md @@ -0,0 +1,243 @@ +1.3.8 / 2022-02-02 +================== + + * deps: mime-types@~2.1.34 + - deps: mime-db@~1.51.0 + * deps: negotiator@0.6.3 + +1.3.7 / 2019-04-29 +================== + + * deps: negotiator@0.6.2 + - Fix sorting charset, encoding, and language with extra parameters + +1.3.6 / 2019-04-28 +================== + + * deps: mime-types@~2.1.24 + - deps: mime-db@~1.40.0 + +1.3.5 / 2018-02-28 +================== + + * deps: mime-types@~2.1.18 + - deps: mime-db@~1.33.0 + +1.3.4 / 2017-08-22 +================== + + * deps: mime-types@~2.1.16 + - deps: mime-db@~1.29.0 + +1.3.3 / 2016-05-02 +================== + + * deps: mime-types@~2.1.11 + - deps: mime-db@~1.23.0 + * deps: negotiator@0.6.1 + - perf: improve `Accept` parsing speed + - perf: improve `Accept-Charset` parsing speed + - perf: improve `Accept-Encoding` parsing speed + - perf: improve `Accept-Language` parsing speed + +1.3.2 / 2016-03-08 +================== + + * deps: mime-types@~2.1.10 + - Fix extension of `application/dash+xml` + - Update primary extension for `audio/mp4` + - deps: mime-db@~1.22.0 + +1.3.1 / 2016-01-19 +================== + + * deps: mime-types@~2.1.9 + - deps: mime-db@~1.21.0 + +1.3.0 / 2015-09-29 +================== + + * deps: mime-types@~2.1.7 + - deps: mime-db@~1.19.0 + * deps: negotiator@0.6.0 + - Fix including type extensions in parameters in `Accept` parsing + - Fix parsing `Accept` parameters with quoted equals + - Fix parsing `Accept` parameters with quoted semicolons + - Lazy-load modules from main entry point + - perf: delay type concatenation until needed + - perf: enable strict mode + - perf: hoist regular expressions + - perf: remove closures getting spec properties + - perf: remove a closure from media type parsing + - perf: remove property delete from media type parsing + +1.2.13 / 2015-09-06 +=================== + + * deps: mime-types@~2.1.6 + - deps: mime-db@~1.18.0 + +1.2.12 / 2015-07-30 +=================== + + * deps: mime-types@~2.1.4 + - deps: mime-db@~1.16.0 + +1.2.11 / 2015-07-16 +=================== + + * deps: mime-types@~2.1.3 + - deps: mime-db@~1.15.0 + +1.2.10 / 2015-07-01 +=================== + + * deps: mime-types@~2.1.2 + - deps: mime-db@~1.14.0 + +1.2.9 / 2015-06-08 +================== + + * deps: mime-types@~2.1.1 + - perf: fix deopt during mapping + +1.2.8 / 2015-06-07 +================== + + * deps: mime-types@~2.1.0 + - deps: mime-db@~1.13.0 + * perf: avoid argument reassignment & argument slice + * perf: avoid negotiator recursive construction + * perf: enable strict mode + * perf: remove unnecessary bitwise operator + +1.2.7 / 2015-05-10 +================== + + * deps: negotiator@0.5.3 + - Fix media type parameter matching to be case-insensitive + +1.2.6 / 2015-05-07 +================== + + * deps: mime-types@~2.0.11 + - deps: mime-db@~1.9.1 + * deps: negotiator@0.5.2 + - Fix comparing media types with quoted values + - Fix splitting media types with quoted commas + +1.2.5 / 2015-03-13 +================== + + * deps: mime-types@~2.0.10 + - deps: mime-db@~1.8.0 + +1.2.4 / 2015-02-14 +================== + + * Support Node.js 0.6 + * deps: mime-types@~2.0.9 + - deps: mime-db@~1.7.0 + * deps: negotiator@0.5.1 + - Fix preference sorting to be stable for long acceptable lists + +1.2.3 / 2015-01-31 +================== + + * deps: mime-types@~2.0.8 + - deps: mime-db@~1.6.0 + +1.2.2 / 2014-12-30 +================== + + * deps: mime-types@~2.0.7 + - deps: mime-db@~1.5.0 + +1.2.1 / 2014-12-30 +================== + + * deps: mime-types@~2.0.5 + - deps: mime-db@~1.3.1 + +1.2.0 / 2014-12-19 +================== + + * deps: negotiator@0.5.0 + - Fix list return order when large accepted list + - Fix missing identity encoding when q=0 exists + - Remove dynamic building of Negotiator class + +1.1.4 / 2014-12-10 +================== + + * deps: mime-types@~2.0.4 + - deps: mime-db@~1.3.0 + +1.1.3 / 2014-11-09 +================== + + * deps: mime-types@~2.0.3 + - deps: mime-db@~1.2.0 + +1.1.2 / 2014-10-14 +================== + + * deps: negotiator@0.4.9 + - Fix error when media type has invalid parameter + +1.1.1 / 2014-09-28 +================== + + * deps: mime-types@~2.0.2 + - deps: mime-db@~1.1.0 + * deps: negotiator@0.4.8 + - Fix all negotiations to be case-insensitive + - Stable sort preferences of same quality according to client order + +1.1.0 / 2014-09-02 +================== + + * update `mime-types` + +1.0.7 / 2014-07-04 +================== + + * Fix wrong type returned from `type` when match after unknown extension + +1.0.6 / 2014-06-24 +================== + + * deps: negotiator@0.4.7 + +1.0.5 / 2014-06-20 +================== + + * fix crash when unknown extension given + +1.0.4 / 2014-06-19 +================== + + * use `mime-types` + +1.0.3 / 2014-06-11 +================== + + * deps: negotiator@0.4.6 + - Order by specificity when quality is the same + +1.0.2 / 2014-05-29 +================== + + * Fix interpretation when header not in request + * deps: pin negotiator@0.4.5 + +1.0.1 / 2014-01-18 +================== + + * Identity encoding isn't always acceptable + * deps: negotiator@~0.4.0 + +1.0.0 / 2013-12-27 +================== + + * Genesis diff --git a/ruty/js/node_modules/accepts/LICENSE b/ruty/js/node_modules/accepts/LICENSE new file mode 100644 index 0000000..0616607 --- /dev/null +++ b/ruty/js/node_modules/accepts/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/ruty/js/node_modules/accepts/README.md b/ruty/js/node_modules/accepts/README.md new file mode 100644 index 0000000..82680c5 --- /dev/null +++ b/ruty/js/node_modules/accepts/README.md @@ -0,0 +1,140 @@ +# accepts + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][github-actions-ci-image]][github-actions-ci-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator). +Extracted from [koa](https://www.npmjs.com/package/koa) for general use. + +In addition to negotiator, it allows: + +- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` + as well as `('text/html', 'application/json')`. +- Allows type shorthands such as `json`. +- Returns `false` when no types match +- Treats non-existent headers as `*` + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install accepts +``` + +## API + +```js +var accepts = require('accepts') +``` + +### accepts(req) + +Create a new `Accepts` object for the given `req`. + +#### .charset(charsets) + +Return the first accepted charset. If nothing in `charsets` is accepted, +then `false` is returned. + +#### .charsets() + +Return the charsets that the request accepts, in the order of the client's +preference (most preferred first). + +#### .encoding(encodings) + +Return the first accepted encoding. If nothing in `encodings` is accepted, +then `false` is returned. + +#### .encodings() + +Return the encodings that the request accepts, in the order of the client's +preference (most preferred first). + +#### .language(languages) + +Return the first accepted language. If nothing in `languages` is accepted, +then `false` is returned. + +#### .languages() + +Return the languages that the request accepts, in the order of the client's +preference (most preferred first). + +#### .type(types) + +Return the first accepted type (and it is returned as the same text as what +appears in the `types` array). If nothing in `types` is accepted, then `false` +is returned. + +The `types` array can contain full MIME types or file extensions. Any value +that is not a full MIME types is passed to `require('mime-types').lookup`. + +#### .types() + +Return the types that the request accepts, in the order of the client's +preference (most preferred first). + +## Examples + +### Simple type negotiation + +This simple example shows how to use `accepts` to return a different typed +respond body based on what the client wants to accept. The server lists it's +preferences in order and will get back the best match between the client and +server. + +```js +var accepts = require('accepts') +var http = require('http') + +function app (req, res) { + var accept = accepts(req) + + // the order of this list is significant; should be server preferred order + switch (accept.type(['json', 'html'])) { + case 'json': + res.setHeader('Content-Type', 'application/json') + res.write('{"hello":"world!"}') + break + case 'html': + res.setHeader('Content-Type', 'text/html') + res.write('hello, world!') + break + default: + // the fallback is text/plain, so no need to specify it above + res.setHeader('Content-Type', 'text/plain') + res.write('hello, world!') + break + } + + res.end() +} + +http.createServer(app).listen(3000) +``` + +You can test this out with the cURL program: +```sh +curl -I -H'Accept: text/html' http://localhost:3000/ +``` + +## License + +[MIT](LICENSE) + +[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master +[coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master +[github-actions-ci-image]: https://badgen.net/github/checks/jshttp/accepts/master?label=ci +[github-actions-ci-url]: https://github.com/jshttp/accepts/actions/workflows/ci.yml +[node-version-image]: https://badgen.net/npm/node/accepts +[node-version-url]: https://nodejs.org/en/download +[npm-downloads-image]: https://badgen.net/npm/dm/accepts +[npm-url]: https://npmjs.org/package/accepts +[npm-version-image]: https://badgen.net/npm/v/accepts diff --git a/ruty/js/node_modules/accepts/index.js b/ruty/js/node_modules/accepts/index.js new file mode 100644 index 0000000..e9b2f63 --- /dev/null +++ b/ruty/js/node_modules/accepts/index.js @@ -0,0 +1,238 @@ +/*! + * accepts + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var Negotiator = require('negotiator') +var mime = require('mime-types') + +/** + * Module exports. + * @public + */ + +module.exports = Accepts + +/** + * Create a new Accepts object for the given req. + * + * @param {object} req + * @public + */ + +function Accepts (req) { + if (!(this instanceof Accepts)) { + return new Accepts(req) + } + + this.headers = req.headers + this.negotiator = new Negotiator(req) +} + +/** + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json" or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * this.types('html'); + * // => "html" + * + * // Accept: text/*, application/json + * this.types('html'); + * // => "html" + * this.types('text/html'); + * // => "text/html" + * this.types('json', 'text'); + * // => "json" + * this.types('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * this.types('image/png'); + * this.types('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * this.types(['html', 'json']); + * this.types('html', 'json'); + * // => "json" + * + * @param {String|Array} types... + * @return {String|Array|Boolean} + * @public + */ + +Accepts.prototype.type = +Accepts.prototype.types = function (types_) { + var types = types_ + + // support flattened arguments + if (types && !Array.isArray(types)) { + types = new Array(arguments.length) + for (var i = 0; i < types.length; i++) { + types[i] = arguments[i] + } + } + + // no types, return all requested types + if (!types || types.length === 0) { + return this.negotiator.mediaTypes() + } + + // no accept header, return first given type + if (!this.headers.accept) { + return types[0] + } + + var mimes = types.map(extToMime) + var accepts = this.negotiator.mediaTypes(mimes.filter(validMime)) + var first = accepts[0] + + return first + ? types[mimes.indexOf(first)] + : false +} + +/** + * Return accepted encodings or best fit based on `encodings`. + * + * Given `Accept-Encoding: gzip, deflate` + * an array sorted by quality is returned: + * + * ['gzip', 'deflate'] + * + * @param {String|Array} encodings... + * @return {String|Array} + * @public + */ + +Accepts.prototype.encoding = +Accepts.prototype.encodings = function (encodings_) { + var encodings = encodings_ + + // support flattened arguments + if (encodings && !Array.isArray(encodings)) { + encodings = new Array(arguments.length) + for (var i = 0; i < encodings.length; i++) { + encodings[i] = arguments[i] + } + } + + // no encodings, return all requested encodings + if (!encodings || encodings.length === 0) { + return this.negotiator.encodings() + } + + return this.negotiator.encodings(encodings)[0] || false +} + +/** + * Return accepted charsets or best fit based on `charsets`. + * + * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5` + * an array sorted by quality is returned: + * + * ['utf-8', 'utf-7', 'iso-8859-1'] + * + * @param {String|Array} charsets... + * @return {String|Array} + * @public + */ + +Accepts.prototype.charset = +Accepts.prototype.charsets = function (charsets_) { + var charsets = charsets_ + + // support flattened arguments + if (charsets && !Array.isArray(charsets)) { + charsets = new Array(arguments.length) + for (var i = 0; i < charsets.length; i++) { + charsets[i] = arguments[i] + } + } + + // no charsets, return all requested charsets + if (!charsets || charsets.length === 0) { + return this.negotiator.charsets() + } + + return this.negotiator.charsets(charsets)[0] || false +} + +/** + * Return accepted languages or best fit based on `langs`. + * + * Given `Accept-Language: en;q=0.8, es, pt` + * an array sorted by quality is returned: + * + * ['es', 'pt', 'en'] + * + * @param {String|Array} langs... + * @return {Array|String} + * @public + */ + +Accepts.prototype.lang = +Accepts.prototype.langs = +Accepts.prototype.language = +Accepts.prototype.languages = function (languages_) { + var languages = languages_ + + // support flattened arguments + if (languages && !Array.isArray(languages)) { + languages = new Array(arguments.length) + for (var i = 0; i < languages.length; i++) { + languages[i] = arguments[i] + } + } + + // no languages, return all requested languages + if (!languages || languages.length === 0) { + return this.negotiator.languages() + } + + return this.negotiator.languages(languages)[0] || false +} + +/** + * Convert extnames to mime. + * + * @param {String} type + * @return {String} + * @private + */ + +function extToMime (type) { + return type.indexOf('/') === -1 + ? mime.lookup(type) + : type +} + +/** + * Check if mime is valid. + * + * @param {String} type + * @return {String} + * @private + */ + +function validMime (type) { + return typeof type === 'string' +} diff --git a/ruty/js/node_modules/accepts/package.json b/ruty/js/node_modules/accepts/package.json new file mode 100644 index 0000000..0f2d15d --- /dev/null +++ b/ruty/js/node_modules/accepts/package.json @@ -0,0 +1,47 @@ +{ + "name": "accepts", + "description": "Higher-level content negotiation", + "version": "1.3.8", + "contributors": [ + "Douglas Christopher Wilson ", + "Jonathan Ong (http://jongleberry.com)" + ], + "license": "MIT", + "repository": "jshttp/accepts", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "devDependencies": { + "deep-equal": "1.0.1", + "eslint": "7.32.0", + "eslint-config-standard": "14.1.1", + "eslint-plugin-import": "2.25.4", + "eslint-plugin-markdown": "2.2.1", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-promise": "4.3.1", + "eslint-plugin-standard": "4.1.0", + "mocha": "9.2.0", + "nyc": "15.1.0" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "index.js" + ], + "engines": { + "node": ">= 0.6" + }, + "scripts": { + "lint": "eslint .", + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-ci": "nyc --reporter=lcov --reporter=text npm test", + "test-cov": "nyc --reporter=html --reporter=text npm test" + }, + "keywords": [ + "content", + "negotiation", + "accept", + "accepts" + ] +} diff --git a/ruty/js/node_modules/array-flatten/LICENSE b/ruty/js/node_modules/array-flatten/LICENSE new file mode 100644 index 0000000..983fbe8 --- /dev/null +++ b/ruty/js/node_modules/array-flatten/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/ruty/js/node_modules/array-flatten/README.md b/ruty/js/node_modules/array-flatten/README.md new file mode 100644 index 0000000..91fa5b6 --- /dev/null +++ b/ruty/js/node_modules/array-flatten/README.md @@ -0,0 +1,43 @@ +# Array Flatten + +[![NPM version][npm-image]][npm-url] +[![NPM downloads][downloads-image]][downloads-url] +[![Build status][travis-image]][travis-url] +[![Test coverage][coveralls-image]][coveralls-url] + +> Flatten an array of nested arrays into a single flat array. Accepts an optional depth. + +## Installation + +``` +npm install array-flatten --save +``` + +## Usage + +```javascript +var flatten = require('array-flatten') + +flatten([1, [2, [3, [4, [5], 6], 7], 8], 9]) +//=> [1, 2, 3, 4, 5, 6, 7, 8, 9] + +flatten([1, [2, [3, [4, [5], 6], 7], 8], 9], 2) +//=> [1, 2, 3, [4, [5], 6], 7, 8, 9] + +(function () { + flatten(arguments) //=> [1, 2, 3] +})(1, [2, 3]) +``` + +## License + +MIT + +[npm-image]: https://img.shields.io/npm/v/array-flatten.svg?style=flat +[npm-url]: https://npmjs.org/package/array-flatten +[downloads-image]: https://img.shields.io/npm/dm/array-flatten.svg?style=flat +[downloads-url]: https://npmjs.org/package/array-flatten +[travis-image]: https://img.shields.io/travis/blakeembrey/array-flatten.svg?style=flat +[travis-url]: https://travis-ci.org/blakeembrey/array-flatten +[coveralls-image]: https://img.shields.io/coveralls/blakeembrey/array-flatten.svg?style=flat +[coveralls-url]: https://coveralls.io/r/blakeembrey/array-flatten?branch=master diff --git a/ruty/js/node_modules/array-flatten/array-flatten.js b/ruty/js/node_modules/array-flatten/array-flatten.js new file mode 100644 index 0000000..089117b --- /dev/null +++ b/ruty/js/node_modules/array-flatten/array-flatten.js @@ -0,0 +1,64 @@ +'use strict' + +/** + * Expose `arrayFlatten`. + */ +module.exports = arrayFlatten + +/** + * Recursive flatten function with depth. + * + * @param {Array} array + * @param {Array} result + * @param {Number} depth + * @return {Array} + */ +function flattenWithDepth (array, result, depth) { + for (var i = 0; i < array.length; i++) { + var value = array[i] + + if (depth > 0 && Array.isArray(value)) { + flattenWithDepth(value, result, depth - 1) + } else { + result.push(value) + } + } + + return result +} + +/** + * Recursive flatten function. Omitting depth is slightly faster. + * + * @param {Array} array + * @param {Array} result + * @return {Array} + */ +function flattenForever (array, result) { + for (var i = 0; i < array.length; i++) { + var value = array[i] + + if (Array.isArray(value)) { + flattenForever(value, result) + } else { + result.push(value) + } + } + + return result +} + +/** + * Flatten an array, with the ability to define a depth. + * + * @param {Array} array + * @param {Number} depth + * @return {Array} + */ +function arrayFlatten (array, depth) { + if (depth == null) { + return flattenForever(array, []) + } + + return flattenWithDepth(array, [], depth) +} diff --git a/ruty/js/node_modules/array-flatten/package.json b/ruty/js/node_modules/array-flatten/package.json new file mode 100644 index 0000000..1a24e2a --- /dev/null +++ b/ruty/js/node_modules/array-flatten/package.json @@ -0,0 +1,39 @@ +{ + "name": "array-flatten", + "version": "1.1.1", + "description": "Flatten an array of nested arrays into a single flat array", + "main": "array-flatten.js", + "files": [ + "array-flatten.js", + "LICENSE" + ], + "scripts": { + "test": "istanbul cover _mocha -- -R spec" + }, + "repository": { + "type": "git", + "url": "git://github.com/blakeembrey/array-flatten.git" + }, + "keywords": [ + "array", + "flatten", + "arguments", + "depth" + ], + "author": { + "name": "Blake Embrey", + "email": "hello@blakeembrey.com", + "url": "http://blakeembrey.me" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/blakeembrey/array-flatten/issues" + }, + "homepage": "https://github.com/blakeembrey/array-flatten", + "devDependencies": { + "istanbul": "^0.3.13", + "mocha": "^2.2.4", + "pre-commit": "^1.0.7", + "standard": "^3.7.3" + } +} diff --git a/ruty/js/node_modules/async/.travis.yml b/ruty/js/node_modules/async/.travis.yml new file mode 100644 index 0000000..6064ca0 --- /dev/null +++ b/ruty/js/node_modules/async/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "0.10" + - "0.12" + - "iojs" diff --git a/ruty/js/node_modules/async/LICENSE b/ruty/js/node_modules/async/LICENSE new file mode 100644 index 0000000..8f29698 --- /dev/null +++ b/ruty/js/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010-2014 Caolan McMahon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/ruty/js/node_modules/async/README.md b/ruty/js/node_modules/async/README.md new file mode 100644 index 0000000..6cfb922 --- /dev/null +++ b/ruty/js/node_modules/async/README.md @@ -0,0 +1,1647 @@ +# Async.js + +[![Build Status via Travis CI](https://travis-ci.org/caolan/async.svg?branch=master)](https://travis-ci.org/caolan/async) + + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [Node.js](http://nodejs.org) and installable via `npm install async`, +it can also be used directly in the browser. + +Async is also installable via: + +- [bower](http://bower.io/): `bower install async` +- [component](https://github.com/component/component): `component install + caolan/async` +- [jam](http://jamjs.org/): `jam install async` +- [spm](http://spmjs.io/): `spm install async` + +Async provides around 20 functions that include the usual 'functional' +suspects (`map`, `reduce`, `filter`, `each`…) as well as some common patterns +for asynchronous control flow (`parallel`, `series`, `waterfall`…). All these +functions assume you follow the Node.js convention of providing a single +callback as the last argument of your `async` function. + + +## Quick Examples + +```javascript +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); + +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); + +async.parallel([ + function(){ ... }, + function(){ ... } +], callback); + +async.series([ + function(){ ... }, + function(){ ... } +]); +``` + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + +## Common Pitfalls + +### Binding a context to an iterator + +This section is really about `bind`, not about `async`. If you are wondering how to +make `async` execute your iterators in a given context, or are confused as to why +a method of another library isn't working as an iterator, study this example: + +```js +// Here is a simple object with an (unnecessarily roundabout) squaring method +var AsyncSquaringLibrary = { + squareExponent: 2, + square: function(number, callback){ + var result = Math.pow(number, this.squareExponent); + setTimeout(function(){ + callback(null, result); + }, 200); + } +}; + +async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){ + // result is [NaN, NaN, NaN] + // This fails because the `this.squareExponent` expression in the square + // function is not evaluated in the context of AsyncSquaringLibrary, and is + // therefore undefined. +}); + +async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){ + // result is [1, 4, 9] + // With the help of bind we can attach a context to the iterator before + // passing it to async. Now the square function will be executed in its + // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent` + // will be as expected. +}); +``` + +## Download + +The source is available for download from +[GitHub](http://github.com/caolan/async). +Alternatively, you can install using Node Package Manager (`npm`): + + npm install async + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed + +## In the Browser + +So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. + +Usage: + +```html + + +``` + +## Documentation + +### Collections + +* [`each`](#each) +* [`eachSeries`](#eachSeries) +* [`eachLimit`](#eachLimit) +* [`map`](#map) +* [`mapSeries`](#mapSeries) +* [`mapLimit`](#mapLimit) +* [`filter`](#filter) +* [`filterSeries`](#filterSeries) +* [`reject`](#reject) +* [`rejectSeries`](#rejectSeries) +* [`reduce`](#reduce) +* [`reduceRight`](#reduceRight) +* [`detect`](#detect) +* [`detectSeries`](#detectSeries) +* [`sortBy`](#sortBy) +* [`some`](#some) +* [`every`](#every) +* [`concat`](#concat) +* [`concatSeries`](#concatSeries) + +### Control Flow + +* [`series`](#seriestasks-callback) +* [`parallel`](#parallel) +* [`parallelLimit`](#parallellimittasks-limit-callback) +* [`whilst`](#whilst) +* [`doWhilst`](#doWhilst) +* [`until`](#until) +* [`doUntil`](#doUntil) +* [`forever`](#forever) +* [`waterfall`](#waterfall) +* [`compose`](#compose) +* [`seq`](#seq) +* [`applyEach`](#applyEach) +* [`applyEachSeries`](#applyEachSeries) +* [`queue`](#queue) +* [`priorityQueue`](#priorityQueue) +* [`cargo`](#cargo) +* [`auto`](#auto) +* [`retry`](#retry) +* [`iterator`](#iterator) +* [`apply`](#apply) +* [`nextTick`](#nextTick) +* [`times`](#times) +* [`timesSeries`](#timesSeries) + +### Utils + +* [`memoize`](#memoize) +* [`unmemoize`](#unmemoize) +* [`log`](#log) +* [`dir`](#dir) +* [`noConflict`](#noConflict) + + +## Collections + + + +### each(arr, iterator, callback) + +Applies the function `iterator` to each item in `arr`, in parallel. +The `iterator` is called with an item from the list, and a callback for when it +has finished. If the `iterator` passes an error to its `callback`, the main +`callback` (for the `each` function) is immediately called with the error. + +Note, that since this function applies `iterator` to each item in parallel, +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err)` which must be called once it has + completed. If no error has occurred, the `callback` should be run without + arguments or with an explicit `null` argument. +* `callback(err)` - A callback which is called when all `iterator` functions + have finished, or an error occurs. + +__Examples__ + + +```js +// assuming openFiles is an array of file names and saveFile is a function +// to save the modified contents of that file: + +async.each(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +```js +// assuming openFiles is an array of file names + +async.each(openFiles, function(file, callback) { + + // Perform operation on file here. + console.log('Processing file ' + file); + + if( file.length > 32 ) { + console.log('This file name is too long'); + callback('File name too long'); + } else { + // Do work to process file here + console.log('File processed'); + callback(); + } +}, function(err){ + // if any of the file processing produced an error, err would equal that error + if( err ) { + // One of the iterations produced an error. + // All processing will now stop. + console.log('A file failed to process'); + } else { + console.log('All files have been processed successfully'); + } +}); +``` + +--------------------------------------- + + + +### eachSeries(arr, iterator, callback) + +The same as [`each`](#each), only `iterator` is applied to each item in `arr` in +series. The next `iterator` is only called once the current one has completed. +This means the `iterator` functions will complete in order. + + +--------------------------------------- + + + +### eachLimit(arr, limit, iterator, callback) + +The same as [`each`](#each), only no more than `limit` `iterator`s will be simultaneously +running at any time. + +Note that the items in `arr` are not processed in batches, so there is no guarantee that +the first `limit` `iterator` functions will complete before any others are started. + +__Arguments__ + +* `arr` - An array to iterate over. +* `limit` - The maximum number of `iterator`s to run at any time. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err)` which must be called once it has + completed. If no error has occurred, the callback should be run without + arguments or with an explicit `null` argument. +* `callback(err)` - A callback which is called when all `iterator` functions + have finished, or an error occurs. + +__Example__ + +```js +// Assume documents is an array of JSON objects and requestApi is a +// function that interacts with a rate-limited REST api. + +async.eachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in `arr` through +the `iterator` function. The `iterator` is called with an item from `arr` and a +callback for when it has finished processing. Each of these callback takes 2 arguments: +an `error`, and the transformed item from `arr`. If `iterator` passes an error to his +callback, the main `callback` (for the `map` function) is immediately called with the error. + +Note, that since this function applies the `iterator` to each item in parallel, +there is no guarantee that the `iterator` functions will complete in order. +However, the results array will be in the same order as the original `arr`. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err, transformed)` which must be called once + it has completed with an error (which can be `null`) and a transformed item. +* `callback(err, results)` - A callback which is called when all `iterator` + functions have finished, or an error occurs. Results is an array of the + transformed items from the `arr`. + +__Example__ + +```js +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as [`map`](#map), only the `iterator` is applied to each item in `arr` in +series. The next `iterator` is only called once the current one has completed. +The results array will be in the same order as the original. + + +--------------------------------------- + + +### mapLimit(arr, limit, iterator, callback) + +The same as [`map`](#map), only no more than `limit` `iterator`s will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that +the first `limit` `iterator` functions will complete before any others are started. + +__Arguments__ + +* `arr` - An array to iterate over. +* `limit` - The maximum number of `iterator`s to run at any time. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err, transformed)` which must be called once + it has completed with an error (which can be `null`) and a transformed item. +* `callback(err, results)` - A callback which is called when all `iterator` + calls have finished, or an error occurs. The result is an array of the + transformed items from the original `arr`. + +__Example__ + +```js +async.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + + +### filter(arr, iterator, callback) + +__Alias:__ `select` + +Returns a new array of all the values in `arr` which pass an async truth test. +_The callback for each `iterator` call only accepts a single argument of `true` or +`false`; it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like `fs.exists`. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A truth test to apply to each item in `arr`. + The `iterator` is passed a `callback(truthValue)`, which must be called with a + boolean argument once it has completed. +* `callback(results)` - A callback which is called after all the `iterator` + functions have finished. + +__Example__ + +```js +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); +``` + +--------------------------------------- + + + +### filterSeries(arr, iterator, callback) + +__Alias:__ `selectSeries` + +The same as [`filter`](#filter) only the `iterator` is applied to each item in `arr` in +series. The next `iterator` is only called once the current one has completed. +The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of [`filter`](#filter). Removes values that pass an `async` truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as [`reject`](#reject), only the `iterator` is applied to each item in `arr` +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__Aliases:__ `inject`, `foldl` + +Reduces `arr` into a single value using an async `iterator` to return +each successive step. `memo` is the initial state of the reduction. +This function only operates in series. + +For performance reasons, it may make sense to split a call to this function into +a parallel map, and then use the normal `Array.prototype.reduce` on the results. +This function is for situations where each step in the reduction needs to be async; +if you can get the data before reducing it, then it's probably a good idea to do so. + +__Arguments__ + +* `arr` - An array to iterate over. +* `memo` - The initial state of the reduction. +* `iterator(memo, item, callback)` - A function applied to each item in the + array to produce the next step in the reduction. The `iterator` is passed a + `callback(err, reduction)` which accepts an optional error as its first + argument, and the state of the reduction as the second. If an error is + passed to the callback, the reduction is stopped and the main `callback` is + immediately called with the error. +* `callback(err, result)` - A callback which is called after all the `iterator` + functions have finished. Result is the reduced value. + +__Example__ + +```js +async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); +}, function(err, result){ + // result is now equal to the last value of memo, which is 6 +}); +``` + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ `foldr` + +Same as [`reduce`](#reduce), only operates on `arr` in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in `arr` that passes an async truth test. The +`iterator` is applied in parallel, meaning the first iterator to return `true` will +fire the detect `callback` with that result. That means the result might not be +the first item in the original `arr` (in terms of order) that passes the test. + +If order within the original `arr` is important, then look at [`detectSeries`](#detectSeries). + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A truth test to apply to each item in `arr`. + The iterator is passed a `callback(truthValue)` which must be called with a + boolean argument once it has completed. +* `callback(result)` - A callback which is called as soon as any iterator returns + `true`, or after all the `iterator` functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value `undefined` if none passed. + +__Example__ + +```js +async.detect(['file1','file2','file3'], fs.exists, function(result){ + // result now equals the first file in the list that exists +}); +``` + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as [`detect`](#detect), only the `iterator` is applied to each item in `arr` +in series. This means the result is always the first in the original `arr` (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each `arr` value through an async `iterator`. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err, sortValue)` which must be called once it + has completed with an error (which can be `null`) and a value to use as the sort + criteria. +* `callback(err, results)` - A callback which is called after all the `iterator` + functions have finished, or an error occurs. Results is the items from + the original `arr` sorted by the values returned by the `iterator` calls. + +__Example__ + +```js +async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); +}, function(err, results){ + // results is now the original array of files sorted by + // modified date +}); +``` + +__Sort Order__ + +By modifying the callback parameter the sorting order can be influenced: + +```js +//ascending order +async.sortBy([1,9,3,5], function(x, callback){ + callback(null, x); +}, function(err,result){ + //result callback +} ); + +//descending order +async.sortBy([1,9,3,5], function(x, callback){ + callback(null, x*-1); //<- x*-1 instead of x, turns the order around +}, function(err,result){ + //result callback +} ); +``` + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ `any` + +Returns `true` if at least one element in the `arr` satisfies an async test. +_The callback for each iterator call only accepts a single argument of `true` or +`false`; it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like `fs.exists`. Once any iterator +call returns `true`, the main `callback` is immediately called. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A truth test to apply to each item in the array + in parallel. The iterator is passed a callback(truthValue) which must be + called with a boolean argument once it has completed. +* `callback(result)` - A callback which is called as soon as any iterator returns + `true`, or after all the iterator functions have finished. Result will be + either `true` or `false` depending on the values of the async tests. + +__Example__ + +```js +async.some(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then at least one of the files exists +}); +``` + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ `all` + +Returns `true` if every element in `arr` satisfies an async test. +_The callback for each `iterator` call only accepts a single argument of `true` or +`false`; it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like `fs.exists`. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A truth test to apply to each item in the array + in parallel. The iterator is passed a callback(truthValue) which must be + called with a boolean argument once it has completed. +* `callback(result)` - A callback which is called after all the `iterator` + functions have finished. Result will be either `true` or `false` depending on + the values of the async tests. + +__Example__ + +```js +async.every(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then every file exists +}); +``` + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies `iterator` to each item in `arr`, concatenating the results. Returns the +concatenated list. The `iterator`s are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of `arr` passed to the `iterator` function. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err, results)` which must be called once it + has completed with an error (which can be `null`) and an array of results. +* `callback(err, results)` - A callback which is called after all the `iterator` + functions have finished, or an error occurs. Results is an array containing + the concatenated results of the `iterator` function. + +__Example__ + +```js +async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories +}); +``` + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as [`concat`](#concat), but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run the functions in the `tasks` array in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run, and `callback` is immediately called with the value of the error. +Otherwise, `callback` receives an array of results when `tasks` have completed. + +It is also possible to use an object instead of an array. Each property will be +run as a function, and the results will be passed to the final `callback` as an object +instead of an array. This can be a more readable way of handling results from +[`series`](#series). + +**Note** that while many implementations preserve the order of object properties, the +[ECMAScript Language Specifcation](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) +explicitly states that + +> The mechanics and order of enumerating the properties is not specified. + +So if you rely on the order in which your series of functions are executed, and want +this to work on all platforms, consider using an array. + +__Arguments__ + +* `tasks` - An array or object containing functions to run, each function is passed + a `callback(err, result)` it must call on completion with an error `err` (which can + be `null`) and an optional `result` value. +* `callback(err, results)` - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the `task` callbacks. + +__Example__ + +```js +async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + } +], +// optional callback +function(err, results){ + // results is now equal to ['one', 'two'] +}); + + +// an example using an object instead of an array +async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equal to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run the `tasks` array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main `callback` is immediately called with the value of the error. +Once the `tasks` have completed, the results are passed to the final `callback` as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final `callback` as an object +instead of an array. This can be a more readable way of handling results from +[`parallel`](#parallel). + + +__Arguments__ + +* `tasks` - An array or object containing functions to run. Each function is passed + a `callback(err, result)` which it must call on completion with an error `err` + (which can be `null`) and an optional `result` value. +* `callback(err, results)` - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + } +], +// optional callback +function(err, results){ + // the results array will equal ['one','two'] even though + // the second function had a shorter timeout. +}); + + +// an example using an object instead of an array +async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equals to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallelLimit(tasks, limit, [callback]) + +The same as [`parallel`](#parallel), only `tasks` are executed in parallel +with a maximum of `limit` tasks executing at any time. + +Note that the `tasks` are not executed in batches, so there is no guarantee that +the first `limit` tasks will complete before any others are started. + +__Arguments__ + +* `tasks` - An array or object containing functions to run, each function is passed + a `callback(err, result)` it must call on completion with an error `err` (which can + be `null`) and an optional `result` value. +* `limit` - The maximum number of `tasks` to run at any time. +* `callback(err, results)` - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the `task` callbacks. + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call `fn`, while `test` returns `true`. Calls `callback` when stopped, +or an error occurs. + +__Arguments__ + +* `test()` - synchronous truth test to perform before each execution of `fn`. +* `fn(callback)` - A function which is called each time `test` passes. The function is + passed a `callback(err)`, which must be called once it has completed with an + optional `err` argument. +* `callback(err)` - A callback which is called after the test fails and repeated + execution of `fn` has stopped. + +__Example__ + +```js +var count = 0; + +async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } +); +``` + +--------------------------------------- + + +### doWhilst(fn, test, callback) + +The post-check version of [`whilst`](#whilst). To reflect the difference in +the order of operations, the arguments `test` and `fn` are switched. + +`doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call `fn` until `test` returns `true`. Calls `callback` when stopped, +or an error occurs. + +The inverse of [`whilst`](#whilst). + +--------------------------------------- + + +### doUntil(fn, test, callback) + +Like [`doWhilst`](#doWhilst), except the `test` is inverted. Note the argument ordering differs from `until`. + +--------------------------------------- + + +### forever(fn, errback) + +Calls the asynchronous function `fn` with a callback parameter that allows it to +call itself again, in series, indefinitely. + +If an error is passed to the callback then `errback` is called with the +error, and execution stops, otherwise it will never be called. + +```js +async.forever( + function(next) { + // next is suitable for passing to things that need a callback(err [, whatever]); + // it will result in this function being called again. + }, + function(err) { + // if next is called with a value in its first parameter, it will appear + // in here as 'err', and execution will stop. + } +); +``` + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs the `tasks` array of functions in series, each passing their results to the next in +the array. However, if any of the `tasks` pass an error to their own callback, the +next function is not executed, and the main `callback` is immediately called with +the error. + +__Arguments__ + +* `tasks` - An array of functions to run, each function is passed a + `callback(err, result1, result2, ...)` it must call on completion. The first + argument is an error (which can be `null`) and any further arguments will be + passed as arguments in order to the next task. +* `callback(err, [results])` - An optional callback to run once all the functions + have completed. This will be passed the results of the last task's callback. + + + +__Example__ + +```js +async.waterfall([ + function(callback) { + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback) { + // arg1 now equals 'one' and arg2 now equals 'two' + callback(null, 'three'); + }, + function(arg1, callback) { + // arg1 now equals 'three' + callback(null, 'done'); + } +], function (err, result) { + // result now equals 'done' +}); +``` + +--------------------------------------- + +### compose(fn1, fn2...) + +Creates a function which is a composition of the passed asynchronous +functions. Each function consumes the return value of the function that +follows. Composing functions `f()`, `g()`, and `h()` would produce the result of +`f(g(h()))`, only this version uses callbacks to obtain the return values. + +Each function is executed with the `this` binding of the composed function. + +__Arguments__ + +* `functions...` - the asynchronous functions to compose + + +__Example__ + +```js +function add1(n, callback) { + setTimeout(function () { + callback(null, n + 1); + }, 10); +} + +function mul3(n, callback) { + setTimeout(function () { + callback(null, n * 3); + }, 10); +} + +var add1mul3 = async.compose(mul3, add1); + +add1mul3(4, function (err, result) { + // result now equals 15 +}); +``` + +--------------------------------------- + +### seq(fn1, fn2...) + +Version of the compose function that is more natural to read. +Each function consumes the return value of the previous function. +It is the equivalent of [`compose`](#compose) with the arguments reversed. + +Each function is executed with the `this` binding of the composed function. + +__Arguments__ + +* functions... - the asynchronous functions to compose + + +__Example__ + +```js +// Requires lodash (or underscore), express3 and dresende's orm2. +// Part of an app, that fetches cats of the logged user. +// This example uses `seq` function to avoid overnesting and error +// handling clutter. +app.get('/cats', function(request, response) { + var User = request.models.User; + async.seq( + _.bind(User.get, User), // 'User.get' has signature (id, callback(err, data)) + function(user, fn) { + user.getCats(fn); // 'getCats' has signature (callback(err, data)) + } + )(req.session.user_id, function (err, cats) { + if (err) { + console.error(err); + response.json({ status: 'error', message: err.message }); + } else { + response.json({ status: 'ok', message: 'Cats found', data: cats }); + } + }); +}); +``` + +--------------------------------------- + +### applyEach(fns, args..., callback) + +Applies the provided arguments to each function in the array, calling +`callback` after all functions have completed. If you only provide the first +argument, then it will return a function which lets you pass in the +arguments as if it were a single function call. + +__Arguments__ + +* `fns` - the asynchronous functions to all call with the same arguments +* `args...` - any number of separate arguments to pass to the function +* `callback` - the final argument should be the callback, called when all + functions have completed processing + + +__Example__ + +```js +async.applyEach([enableSearch, updateSchema], 'bucket', callback); + +// partial application example: +async.each( + buckets, + async.applyEach([enableSearch, updateSchema]), + callback +); +``` + +--------------------------------------- + + +### applyEachSeries(arr, iterator, callback) + +The same as [`applyEach`](#applyEach) only the functions are applied in series. + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a `queue` object with the specified `concurrency`. Tasks added to the +`queue` are processed in parallel (up to the `concurrency` limit). If all +`worker`s are in progress, the task is queued until one becomes available. +Once a `worker` completes a `task`, that `task`'s callback is called. + +__Arguments__ + +* `worker(task, callback)` - An asynchronous function for processing a queued + task, which must call its `callback(err)` argument when finished, with an + optional `error` as an argument. +* `concurrency` - An `integer` for determining how many `worker` functions should be + run in parallel. + +__Queue objects__ + +The `queue` object returned by this function has the following properties and +methods: + +* `length()` - a function returning the number of items waiting to be processed. +* `started` - a function returning whether or not any items have been pushed and processed by the queue +* `running()` - a function returning the number of items currently being processed. +* `idle()` - a function returning false if there are items waiting or being processed, or true if not. +* `concurrency` - an integer for determining how many `worker` functions should be + run in parallel. This property can be changed after a `queue` is created to + alter the concurrency on-the-fly. +* `push(task, [callback])` - add a new task to the `queue`. Calls `callback` once + the `worker` has finished processing the task. Instead of a single task, a `tasks` array + can be submitted. The respective callback is used for every task in the list. +* `unshift(task, [callback])` - add a new task to the front of the `queue`. +* `saturated` - a callback that is called when the `queue` length hits the `concurrency` limit, + and further tasks will be queued. +* `empty` - a callback that is called when the last item from the `queue` is given to a `worker`. +* `drain` - a callback that is called when the last item from the `queue` has returned from the `worker`. +* `paused` - a boolean for determining whether the queue is in a paused state +* `pause()` - a function that pauses the processing of tasks until `resume()` is called. +* `resume()` - a function that resumes the processing of queued tasks when the queue is paused. +* `kill()` - a function that removes the `drain` callback and empties remaining tasks from the queue forcing it to go idle. + +__Example__ + +```js +// create a queue object with concurrency 2 + +var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); +}, 2); + + +// assign a callback +q.drain = function() { + console.log('all items have been processed'); +} + +// add some items to the queue + +q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); +}); +q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); + +// add some items to the queue (batch-wise) + +q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { + console.log('finished processing item'); +}); + +// add some items to the front of the queue + +q.unshift({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); +``` + + +--------------------------------------- + + +### priorityQueue(worker, concurrency) + +The same as [`queue`](#queue) only tasks are assigned a priority and completed in ascending priority order. There are two differences between `queue` and `priorityQueue` objects: + +* `push(task, priority, [callback])` - `priority` should be a number. If an array of + `tasks` is given, all tasks will be assigned the same priority. +* The `unshift` method was removed. + +--------------------------------------- + + +### cargo(worker, [payload]) + +Creates a `cargo` object with the specified payload. Tasks added to the +cargo will be processed altogether (up to the `payload` limit). If the +`worker` is in progress, the task is queued until it becomes available. Once +the `worker` has completed some tasks, each callback of those tasks is called. +Check out [this animation](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) for how `cargo` and `queue` work. + +While [queue](#queue) passes only one task to one of a group of workers +at a time, cargo passes an array of tasks to a single worker, repeating +when the worker is finished. + +__Arguments__ + +* `worker(tasks, callback)` - An asynchronous function for processing an array of + queued tasks, which must call its `callback(err)` argument when finished, with + an optional `err` argument. +* `payload` - An optional `integer` for determining how many tasks should be + processed per round; if omitted, the default is unlimited. + +__Cargo objects__ + +The `cargo` object returned by this function has the following properties and +methods: + +* `length()` - A function returning the number of items waiting to be processed. +* `payload` - An `integer` for determining how many tasks should be + process per round. This property can be changed after a `cargo` is created to + alter the payload on-the-fly. +* `push(task, [callback])` - Adds `task` to the `queue`. The callback is called + once the `worker` has finished processing the task. Instead of a single task, an array of `tasks` + can be submitted. The respective callback is used for every task in the list. +* `saturated` - A callback that is called when the `queue.length()` hits the concurrency and further tasks will be queued. +* `empty` - A callback that is called when the last item from the `queue` is given to a `worker`. +* `drain` - A callback that is called when the last item from the `queue` has returned from the `worker`. + +__Example__ + +```js +// create a cargo object with payload 2 + +var cargo = async.cargo(function (tasks, callback) { + for(var i=0; i +### auto(tasks, [callback]) + +Determines the best order for running the functions in `tasks`, based on their +requirements. Each function can optionally depend on other functions being completed +first, and each function is run as soon as its requirements are satisfied. + +If any of the functions pass an error to their callback, it will not +complete (so any other functions depending on it will not run), and the main +`callback` is immediately called with the error. Functions also receive an +object containing the results of functions which have completed so far. + +Note, all functions are called with a `results` object as a second argument, +so it is unsafe to pass functions in the `tasks` object which cannot handle the +extra argument. + +For example, this snippet of code: + +```js +async.auto({ + readData: async.apply(fs.readFile, 'data.txt', 'utf-8') +}, callback); +``` + +will have the effect of calling `readFile` with the results object as the last +argument, which will fail: + +```js +fs.readFile('data.txt', 'utf-8', cb, {}); +``` + +Instead, wrap the call to `readFile` in a function which does not forward the +`results` object: + +```js +async.auto({ + readData: function(cb, results){ + fs.readFile('data.txt', 'utf-8', cb); + } +}, callback); +``` + +__Arguments__ + +* `tasks` - An object. Each of its properties is either a function or an array of + requirements, with the function itself the last item in the array. The object's key + of a property serves as the name of the task defined by that property, + i.e. can be used when specifying requirements for other tasks. + The function receives two arguments: (1) a `callback(err, result)` which must be + called when finished, passing an `error` (which can be `null`) and the result of + the function's execution, and (2) a `results` object, containing the results of + the previously executed functions. +* `callback(err, results)` - An optional callback which is called when all the + tasks have been completed. It receives the `err` argument if any `tasks` + pass an error to their callback. Results are always returned; however, if + an error occurs, no further `tasks` will be performed, and the results + object will only contain partial results. + + +__Example__ + +```js +async.auto({ + get_data: function(callback){ + console.log('in get_data'); + // async code to get some data + callback(null, 'data', 'converted to array'); + }, + make_folder: function(callback){ + console.log('in make_folder'); + // async code to create a directory to store a file in + // this is run at the same time as getting the data + callback(null, 'folder'); + }, + write_file: ['get_data', 'make_folder', function(callback, results){ + console.log('in write_file', JSON.stringify(results)); + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, 'filename'); + }], + email_link: ['write_file', function(callback, results){ + console.log('in email_link', JSON.stringify(results)); + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + callback(null, {'file':results.write_file, 'email':'user@example.com'}); + }] +}, function(err, results) { + console.log('err = ', err); + console.log('results = ', results); +}); +``` + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + +```js +async.parallel([ + function(callback){ + console.log('in get_data'); + // async code to get some data + callback(null, 'data', 'converted to array'); + }, + function(callback){ + console.log('in make_folder'); + // async code to create a directory to store a file in + // this is run at the same time as getting the data + callback(null, 'folder'); + } +], +function(err, results){ + async.series([ + function(callback){ + console.log('in write_file', JSON.stringify(results)); + // once there is some data and the directory exists, + // write the data to a file in the directory + results.push('filename'); + callback(null); + }, + function(callback){ + console.log('in email_link', JSON.stringify(results)); + // once the file is written let's email a link to it... + callback(null, {'file':results.pop(), 'email':'user@example.com'}); + } + ]); +}); +``` + +For a complicated series of `async` tasks, using the [`auto`](#auto) function makes adding +new tasks much easier (and the code more readable). + + +--------------------------------------- + + +### retry([times = 5], task, [callback]) + +Attempts to get a successful response from `task` no more than `times` times before +returning an error. If the task is successful, the `callback` will be passed the result +of the successful task. If all attempts fail, the callback will be passed the error and +result (if any) of the final attempt. + +__Arguments__ + +* `times` - An integer indicating how many times to attempt the `task` before giving up. Defaults to 5. +* `task(callback, results)` - A function which receives two arguments: (1) a `callback(err, result)` + which must be called when finished, passing `err` (which can be `null`) and the `result` of + the function's execution, and (2) a `results` object, containing the results of + the previously executed functions (if nested inside another control flow). +* `callback(err, results)` - An optional callback which is called when the + task has succeeded, or after the final failed attempt. It receives the `err` and `result` arguments of the last attempt at completing the `task`. + +The [`retry`](#retry) function can be used as a stand-alone control flow by passing a +callback, as shown below: + +```js +async.retry(3, apiMethod, function(err, result) { + // do something with the result +}); +``` + +It can also be embeded within other control flow functions to retry individual methods +that are not as reliable, like this: + +```js +async.auto({ + users: api.getUsers.bind(api), + payments: async.retry(3, api.getPayments.bind(api)) +}, function(err, results) { + // do something with the results +}); +``` + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the `tasks` array, +returning a continuation to call the next one after that. It's also possible to +“peek” at the next iterator with `iterator.next()`. + +This function is used internally by the `async` module, but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* `tasks` - An array of functions to run. + +__Example__ + +```js +var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } +]); + +node> var iterator2 = iterator(); +'one' +node> var iterator3 = iterator2(); +'two' +node> iterator3(); +'three' +node> var nextfn = iterator2.next(); +node> nextfn(); +'three' +``` + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied. + +Useful as a shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* `function` - The function you want to eventually apply all arguments to. +* `arguments...` - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + +```js +// using apply + +async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), +]); + + +// the same process without using apply + +async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + } +]); +``` + +It's possible to pass any number of additional arguments when calling the +continuation: + +```js +node> var fn = async.apply(sys.puts, 'one'); +node> fn('two', 'three'); +one +two +three +``` + +--------------------------------------- + + +### nextTick(callback), setImmediate(callback) + +Calls `callback` on a later loop around the event loop. In Node.js this just +calls `process.nextTick`; in the browser it falls back to `setImmediate(callback)` +if available, otherwise `setTimeout(callback, 0)`, which means other higher priority +events may precede the execution of `callback`. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* `callback` - The function to call on a later loop around the event loop. + +__Example__ + +```js +var call_order = []; +async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two'] +}); +call_order.push('one') +``` + + +### times(n, callback) + +Calls the `callback` function `n` times, and accumulates results in the same manner +you would use with [`map`](#map). + +__Arguments__ + +* `n` - The number of times to run the function. +* `callback` - The function to call `n` times. + +__Example__ + +```js +// Pretend this is some complicated async factory +var createUser = function(id, callback) { + callback(null, { + id: 'user' + id + }) +} +// generate 5 users +async.times(5, function(n, next){ + createUser(n, function(err, user) { + next(err, user) + }) +}, function(err, users) { + // we should now have 5 users +}); +``` + + +### timesSeries(n, callback) + +The same as [`times`](#times), only the iterator is applied to each item in `arr` in +series. The next `iterator` is only called once the current one has completed. +The results array will be in the same order as the original. + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an `async` function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +The cache of results is exposed as the `memo` property of the function returned +by `memoize`. + +__Arguments__ + +* `fn` - The function to proxy and cache results from. +* `hasher` - Tn optional function for generating a custom hash for storing + results. It has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + +```js +var slow_fn = function (name, callback) { + // do something + callback(null, result); +}; +var fn = async.memoize(slow_fn); + +// fn can now be used as if it were slow_fn +fn('some name', function () { + // callback +}); +``` + + +### unmemoize(fn) + +Undoes a [`memoize`](#memoize)d function, reverting it to the original, unmemoized +form. Handy for testing. + +__Arguments__ + +* `fn` - the memoized function + + +### log(function, arguments) + +Logs the result of an `async` function to the `console`. Only works in Node.js or +in browsers that support `console.log` and `console.error` (such as FF and Chrome). +If multiple arguments are returned from the async function, `console.log` is +called on each argument in order. + +__Arguments__ + +* `function` - The function you want to eventually apply all arguments to. +* `arguments...` - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); +}; +``` +```js +node> async.log(hello, 'world'); +'hello world' +``` + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an `async` function to the `console` using `console.dir` to +display the properties of the resulting object. Only works in Node.js or +in browsers that support `console.dir` and `console.error` (such as FF and Chrome). +If multiple arguments are returned from the async function, `console.dir` is +called on each argument in order. + +__Arguments__ + +* `function` - The function you want to eventually apply all arguments to. +* `arguments...` - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); +}; +``` +```js +node> async.dir(hello, 'world'); +{hello: 'world'} +``` + +--------------------------------------- + + +### noConflict() + +Changes the value of `async` back to its original value, returning a reference to the +`async` object. diff --git a/ruty/js/node_modules/async/bower.json b/ruty/js/node_modules/async/bower.json new file mode 100644 index 0000000..1817688 --- /dev/null +++ b/ruty/js/node_modules/async/bower.json @@ -0,0 +1,38 @@ +{ + "name": "async", + "description": "Higher-order functions and common patterns for asynchronous code", + "version": "0.9.2", + "main": "lib/async.js", + "keywords": [ + "async", + "callback", + "utility", + "module" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/caolan/async.git" + }, + "devDependencies": { + "nodeunit": ">0.0.0", + "uglify-js": "1.2.x", + "nodelint": ">0.0.0", + "lodash": ">=2.4.1" + }, + "moduleType": [ + "amd", + "globals", + "node" + ], + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "authors": [ + "Caolan McMahon" + ] +} \ No newline at end of file diff --git a/ruty/js/node_modules/async/component.json b/ruty/js/node_modules/async/component.json new file mode 100644 index 0000000..5003a7c --- /dev/null +++ b/ruty/js/node_modules/async/component.json @@ -0,0 +1,16 @@ +{ + "name": "async", + "description": "Higher-order functions and common patterns for asynchronous code", + "version": "0.9.2", + "keywords": [ + "async", + "callback", + "utility", + "module" + ], + "license": "MIT", + "repository": "caolan/async", + "scripts": [ + "lib/async.js" + ] +} \ No newline at end of file diff --git a/ruty/js/node_modules/async/lib/async.js b/ruty/js/node_modules/async/lib/async.js new file mode 100644 index 0000000..394c41c --- /dev/null +++ b/ruty/js/node_modules/async/lib/async.js @@ -0,0 +1,1123 @@ +/*! + * async + * https://github.com/caolan/async + * + * Copyright 2010-2014 Caolan McMahon + * Released under the MIT license + */ +/*jshint onevar: false, indent:4 */ +/*global setImmediate: false, setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root, previous_async; + + root = this; + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + var called = false; + return function() { + if (called) throw new Error("Callback was already called."); + called = true; + fn.apply(root, arguments); + } + } + + //// cross-browser compatiblity functions //// + + var _toString = Object.prototype.toString; + + var _isArray = Array.isArray || function (obj) { + return _toString.call(obj) === '[object Array]'; + }; + + var _each = function (arr, iterator) { + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _each(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _each(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + if (typeof setImmediate === 'function') { + async.nextTick = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + async.setImmediate = async.nextTick; + } + else { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + async.setImmediate = async.nextTick; + } + } + else { + async.nextTick = process.nextTick; + if (typeof setImmediate !== 'undefined') { + async.setImmediate = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + } + else { + async.setImmediate = async.nextTick; + } + } + + async.each = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _each(arr, function (x) { + iterator(x, only_once(done) ); + }); + function done(err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(); + } + } + } + }; + async.forEach = async.each; + + async.eachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + async.forEachSeries = async.eachSeries; + + async.eachLimit = function (arr, limit, iterator, callback) { + var fn = _eachLimit(limit); + fn.apply(null, [arr, iterator, callback]); + }; + async.forEachLimit = async.eachLimit; + + var _eachLimit = function (limit) { + + return function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed >= arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed >= arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.each].concat(args)); + }; + }; + var doParallelLimit = function(limit, fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [_eachLimit(limit)].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.eachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + if (!callback) { + eachfn(arr, function (x, callback) { + iterator(x.value, function (err) { + callback(err); + }); + }); + } else { + var results = []; + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = function (arr, limit, iterator, callback) { + return _mapLimit(limit)(arr, iterator, callback); + }; + + var _mapLimit = function(limit) { + return doParallelLimit(limit, _asyncMap); + }; + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.eachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + var remainingTasks = keys.length + if (!remainingTasks) { + return callback(); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + remainingTasks-- + _each(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (!remainingTasks) { + var theCallback = callback; + // prevent final callback from calling itself if it errors + callback = function () {}; + + theCallback(null, results); + } + }); + + _each(keys, function (k) { + var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; + var taskCallback = function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _each(_keys(results), function(rkey) { + safeResults[rkey] = results[rkey]; + }); + safeResults[k] = args; + callback(err, safeResults); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + results[k] = args; + async.setImmediate(taskComplete); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.retry = function(times, task, callback) { + var DEFAULT_TIMES = 5; + var attempts = []; + // Use defaults if times not passed + if (typeof times === 'function') { + callback = task; + task = times; + times = DEFAULT_TIMES; + } + // Make sure times is a number + times = parseInt(times, 10) || DEFAULT_TIMES; + var wrappedTask = function(wrappedCallback, wrappedResults) { + var retryAttempt = function(task, finalAttempt) { + return function(seriesCallback) { + task(function(err, result){ + seriesCallback(!err || finalAttempt, {err: err, result: result}); + }, wrappedResults); + }; + }; + while (times) { + attempts.push(retryAttempt(task, !(times-=1))); + } + async.series(attempts, function(done, data){ + data = data[data.length - 1]; + (wrappedCallback || callback)(data.err, data.result); + }); + } + // If a callback is passed, run this as a controll flow + return callback ? wrappedTask() : wrappedTask + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (!_isArray(tasks)) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback.apply(null, arguments); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.setImmediate(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + var _parallel = function(eachfn, tasks, callback) { + callback = callback || function () {}; + if (_isArray(tasks)) { + eachfn.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + eachfn.each(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.parallel = function (tasks, callback) { + _parallel({ map: async.map, each: async.each }, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (_isArray(tasks)) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.eachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doWhilst = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + var args = Array.prototype.slice.call(arguments, 1); + if (test.apply(null, args)) { + async.doWhilst(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doUntil = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + var args = Array.prototype.slice.call(arguments, 1); + if (!test.apply(null, args)) { + async.doUntil(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.queue = function (worker, concurrency) { + if (concurrency === undefined) { + concurrency = 1; + } + function _insert(q, data, pos, callback) { + if (!q.started){ + q.started = true; + } + if (!_isArray(data)) { + data = [data]; + } + if(data.length == 0) { + // call drain immediately if there are no tasks + return async.setImmediate(function() { + if (q.drain) { + q.drain(); + } + }); + } + _each(data, function(task) { + var item = { + data: task, + callback: typeof callback === 'function' ? callback : null + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.saturated && q.tasks.length === q.concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + started: false, + paused: false, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + kill: function () { + q.drain = null; + q.tasks = []; + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + if (!q.paused && workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if (q.empty && q.tasks.length === 0) { + q.empty(); + } + workers += 1; + var next = function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if (q.drain && q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + var cb = only_once(next); + worker(task.data, cb); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + }, + idle: function() { + return q.tasks.length + workers === 0; + }, + pause: function () { + if (q.paused === true) { return; } + q.paused = true; + }, + resume: function () { + if (q.paused === false) { return; } + q.paused = false; + // Need to call q.process once per concurrent + // worker to preserve full concurrency after pause + for (var w = 1; w <= q.concurrency; w++) { + async.setImmediate(q.process); + } + } + }; + return q; + }; + + async.priorityQueue = function (worker, concurrency) { + + function _compareTasks(a, b){ + return a.priority - b.priority; + }; + + function _binarySearch(sequence, item, compare) { + var beg = -1, + end = sequence.length - 1; + while (beg < end) { + var mid = beg + ((end - beg + 1) >>> 1); + if (compare(item, sequence[mid]) >= 0) { + beg = mid; + } else { + end = mid - 1; + } + } + return beg; + } + + function _insert(q, data, priority, callback) { + if (!q.started){ + q.started = true; + } + if (!_isArray(data)) { + data = [data]; + } + if(data.length == 0) { + // call drain immediately if there are no tasks + return async.setImmediate(function() { + if (q.drain) { + q.drain(); + } + }); + } + _each(data, function(task) { + var item = { + data: task, + priority: priority, + callback: typeof callback === 'function' ? callback : null + }; + + q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item); + + if (q.saturated && q.tasks.length === q.concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + // Start with a normal queue + var q = async.queue(worker, concurrency); + + // Override push to accept second parameter representing priority + q.push = function (data, priority, callback) { + _insert(q, data, priority, callback); + }; + + // Remove unshift function + delete q.unshift; + + return q; + }; + + async.cargo = function (worker, payload) { + var working = false, + tasks = []; + + var cargo = { + tasks: tasks, + payload: payload, + saturated: null, + empty: null, + drain: null, + drained: true, + push: function (data, callback) { + if (!_isArray(data)) { + data = [data]; + } + _each(data, function(task) { + tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + cargo.drained = false; + if (cargo.saturated && tasks.length === payload) { + cargo.saturated(); + } + }); + async.setImmediate(cargo.process); + }, + process: function process() { + if (working) return; + if (tasks.length === 0) { + if(cargo.drain && !cargo.drained) cargo.drain(); + cargo.drained = true; + return; + } + + var ts = typeof payload === 'number' + ? tasks.splice(0, payload) + : tasks.splice(0, tasks.length); + + var ds = _map(ts, function (task) { + return task.data; + }); + + if(cargo.empty) cargo.empty(); + working = true; + worker(ds, function () { + working = false; + + var args = arguments; + _each(ts, function (data) { + if (data.callback) { + data.callback.apply(null, args); + } + }); + + process(); + }); + }, + length: function () { + return tasks.length; + }, + running: function () { + return working; + } + }; + return cargo; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _each(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + async.nextTick(function () { + callback.apply(null, memo[key]); + }); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + async.times = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.map(counter, iterator, callback); + }; + + async.timesSeries = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.mapSeries(counter, iterator, callback); + }; + + async.seq = function (/* functions... */) { + var fns = arguments; + return function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([function () { + var err = arguments[0]; + var nextargs = Array.prototype.slice.call(arguments, 1); + cb(err, nextargs); + }])) + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }; + }; + + async.compose = function (/* functions... */) { + return async.seq.apply(null, Array.prototype.reverse.call(arguments)); + }; + + var _applyEach = function (eachfn, fns /*args...*/) { + var go = function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + return eachfn(fns, function (fn, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }; + if (arguments.length > 2) { + var args = Array.prototype.slice.call(arguments, 2); + return go.apply(this, args); + } + else { + return go; + } + }; + async.applyEach = doParallel(_applyEach); + async.applyEachSeries = doSeries(_applyEach); + + async.forever = function (fn, callback) { + function next(err) { + if (err) { + if (callback) { + return callback(err); + } + throw err; + } + fn(next); + } + next(); + }; + + // Node.js + if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + // AMD / RequireJS + else if (typeof define !== 'undefined' && define.amd) { + define([], function () { + return async; + }); + } + // included directly via