{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d31d8850",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-18T02:42:48.498319Z",
     "start_time": "2024-01-18T02:42:48.496832Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:22:06.162764Z",
     "iopub.status.busy": "2025-01-14T00:22:06.162624Z",
     "iopub.status.idle": "2025-01-14T00:22:06.167027Z",
     "shell.execute_reply": "2025-01-14T00:22:06.166610Z",
     "shell.execute_reply.started": "2025-01-14T00:22:06.162748Z"
    }
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7cd4c0dd",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-18T02:42:53.666867Z",
     "start_time": "2024-01-18T02:42:48.821513Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:22:06.167729Z",
     "iopub.status.busy": "2025-01-14T00:22:06.167600Z",
     "iopub.status.idle": "2025-01-14T00:22:12.274113Z",
     "shell.execute_reply": "2025-01-14T00:22:12.273582Z",
     "shell.execute_reply.started": "2025-01-14T00:22:06.167715Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/tony/anaconda3/envs/suno_env_dev/lib/python3.10/site-packages/transformers/tokenization_utils_base.py:1601: FutureWarning: `clean_up_tokenization_spaces` was not set. It will be set to `True` by default. This behavior will be depracted in transformers v4.45, and will be then set to `False` by default. For more details check this issue: https://github.com/huggingface/transformers/issues/31884\n",
      "  warnings.warn(\n"
     ]
    }
   ],
   "source": [
    "import tqdm\n",
    "import math\n",
    "import torch\n",
    "import random\n",
    "import funcy\n",
    "import copy\n",
    "import gc\n",
    "import re\n",
    "import json\n",
    "import tempfile\n",
    "import collections\n",
    "from collections import Counter\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import fasttext\n",
    "from joblib import Parallel, delayed\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from suno_utils.audio import Audio\n",
    "from suno_utils.utils.text import (\n",
    "    write_jsonl,\n",
    "    read_jsonl,\n",
    "    write_json,\n",
    "    read_json,\n",
    "    normalize_whitespace,\n",
    ")\n",
    "from suno_utils.utils.lyrics import remove_speakers\n",
    "from suno_utils.utils.s3 import read_from_s3, check_s3_file_exists, open_from_s3\n",
    "from suno_utils.utils.tokenizers import tokenize\n",
    "from suno_utils.harvest.youtube.constants.text_lang import BASE_TO_FASTTEXT_REMAP\n",
    "from suno_utils.utils.metrics import get_cer\n",
    "from suno_utils.tasks.hoot import (\n",
    "    parse_lyrics,\n",
    "    legacy_parse_lyrics,\n",
    "    EMBEDDING_RATE as HOOT_EMBEDDING_RATE,\n",
    ")\n",
    "from suno_utils.utils.lyrics import remove_speakers"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d9d50793",
   "metadata": {},
   "source": [
    "## load genius_hq info"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "2cd505d5",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:09:50.716502Z",
     "start_time": "2024-01-09T15:08:04.096829Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:22:12.277994Z",
     "iopub.status.busy": "2025-01-14T00:22:12.277868Z",
     "iopub.status.idle": "2025-01-14T00:23:25.412046Z",
     "shell.execute_reply": "2025-01-14T00:23:25.411243Z",
     "shell.execute_reply.started": "2025-01-14T00:22:12.277980Z"
    }
   },
   "outputs": [],
   "source": [
    "# takes ~ 2 mins\n",
    "base_metas = read_jsonl(\"/app/suno/tmp/clean_deezer_v0_metas.jsonl\")\n",
    "# TODO: original IDs are already unique here, but did we resolve correctly by highest genius views?\n",
    "#   could be a way to filter translations that don't contain the word 'translation'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f04753e2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dict_keys(['id', 'duration_s', 's3_filepath', 'text_lines', 'lang'])\n"
     ]
    }
   ],
   "source": [
    "print(base_metas[100].keys())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "3946b51f",
   "metadata": {},
   "outputs": [],
   "source": [
    "for meta in base_metas:\n",
    "    meta[\"text\"] = \"\\n\".join(text_line[\"text\"] for text_line in meta[\"text_lines\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "251edcf4",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:09:54.750823Z",
     "start_time": "2024-01-09T15:09:50.718362Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:25.413069Z",
     "iopub.status.busy": "2025-01-14T00:23:25.412912Z",
     "iopub.status.idle": "2025-01-14T00:23:31.877797Z",
     "shell.execute_reply": "2025-01-14T00:23:31.877220Z",
     "shell.execute_reply.started": "2025-01-14T00:23:25.413054Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total, 768515\n",
      "lang cut, 0 (0.0%)\n",
      "duration cut, 6794 (0.88%)\n",
      "lyrics cut, 115 (0.01%)\n"
     ]
    }
   ],
   "source": [
    "total_base_metas = len(base_metas)\n",
    "n_genius_view_cut = 5\n",
    "n_youtube_view_cut = 50\n",
    "max_duration = 8 * 60\n",
    "min_duration = 1 * 60\n",
    "max_len_lyrics = 9128\n",
    "min_len_lyrics = 12\n",
    "n_total_base_metas = len(base_metas)\n",
    "print(f\"total, {n_total_base_metas}\")\n",
    "lang_cut_count = sum(1 if m.get(\"lang\") is None else 0 for m in base_metas)\n",
    "duration_cut_count = sum(\n",
    "    1\n",
    "    if (m.get(\"duration_s\", 0) > max_duration or m.get(\"duration_s\", 0) < min_duration)\n",
    "    else 0\n",
    "    for m in base_metas\n",
    ")\n",
    "lyrics_cut_count = sum(\n",
    "    1\n",
    "    if (\n",
    "        len(m.get(\"text\", \"\")) > max_len_lyrics\n",
    "        or len(m.get(\"text\", \"\")) < min_len_lyrics\n",
    "    )\n",
    "    else 0\n",
    "    for m in base_metas\n",
    ")\n",
    "\n",
    "print(\n",
    "    f\"lang cut, {lang_cut_count} ({round(lang_cut_count / n_total_base_metas * 100, 2)}%)\"\n",
    ")\n",
    "print(\n",
    "    f\"duration cut, {duration_cut_count} ({round(duration_cut_count / n_total_base_metas * 100, 2)}%)\"\n",
    ")\n",
    "print(\n",
    "    f\"lyrics cut, {lyrics_cut_count} ({round(lyrics_cut_count / n_total_base_metas * 100, 2)}%)\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "6ac295a0",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:10:01.309149Z",
     "start_time": "2024-01-09T15:09:54.752976Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:31.879727Z",
     "iopub.status.busy": "2025-01-14T00:23:31.879303Z",
     "iopub.status.idle": "2025-01-14T00:23:39.048856Z",
     "shell.execute_reply": "2025-01-14T00:23:39.048248Z",
     "shell.execute_reply.started": "2025-01-14T00:23:31.879710Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "768515 clips\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 768515/768515 [00:01<00:00, 394834.85it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "761670 filtered clips\n",
      "42470 hours\n"
     ]
    }
   ],
   "source": [
    "print(len(base_metas), \"clips\")\n",
    "metas = []\n",
    "seen_id = set()\n",
    "seen_path = set()\n",
    "for m in tqdm.tqdm(base_metas):\n",
    "    # guessed_lang = _get_text_lang(m[\"lyrics\"])[1]\n",
    "    if (\n",
    "        #  m[\"genius_views\"] < n_genius_view_cut\n",
    "        # or m[\"youtube_views\"] < n_youtube_view_cut\n",
    "        m.get(\"lang\") is None\n",
    "        # or \"translation\" in m[\"genius_slug\"].lower()\n",
    "        # or any(\"translation\" in tag.lower() for tag in m[\"tags_text\"])\n",
    "        # or m[\"lang\"].lower()[:2] != \"en\"\n",
    "        or m.get(\"duration_s\", 0) < min_duration\n",
    "        or m.get(\"duration_s\", 0) > max_duration\n",
    "        or len(m.get(\"text\", \"\")) < min_len_lyrics\n",
    "        # or len(m.get(\"text\", \"\")) > max_len_lyrics\n",
    "        or m[\"id\"] in seen_id\n",
    "        or m[\"s3_filepath\"] in seen_path\n",
    "        # or _get_text_lang(m[\"lyrics\"])[1] != \"en\"\n",
    "    ):\n",
    "        continue\n",
    "    seen_id.add(m[\"id\"])\n",
    "    seen_path.add(m[\"s3_filepath\"])\n",
    "    new_m = {\n",
    "        \"id\": m[\"id\"],\n",
    "        \"lyrics\": m[\"text\"].strip(),\n",
    "        \"duration_s\": m[\"duration_s\"],\n",
    "        \"lang\": m[\"lang\"],\n",
    "        # \"guess_lang\": guessed_lang,\n",
    "        \"audio_filepath\": m[\"s3_filepath\"],\n",
    "        # \"original_id\": m[\"original_id\"],\n",
    "        # \"genius_slug\": m[\"genius_slug\"],\n",
    "        # \"genius_views\": m[\"genius_views\"],\n",
    "        # \"youtube_views\": m[\"youtube_views\"],\n",
    "    }\n",
    "    metas.append(new_m)\n",
    "print(len(metas), \"filtered clips\")\n",
    "print(round(sum(m[\"duration_s\"] for m in metas) / 60 / 60), \"hours\")\n",
    "metas_map = {m[\"id\"]: m for m in metas}\n",
    "# Discogs\n",
    "# 2154863 filtered clips\n",
    "# 136385 hours"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "710eb01c",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:10:01.313613Z",
     "start_time": "2024-01-09T15:10:01.311434Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:39.049576Z",
     "iopub.status.busy": "2025-01-14T00:23:39.049427Z",
     "iopub.status.idle": "2025-01-14T00:23:39.051784Z",
     "shell.execute_reply": "2025-01-14T00:23:39.051377Z",
     "shell.execute_reply.started": "2025-01-14T00:23:39.049560Z"
    }
   },
   "outputs": [],
   "source": [
    "# # only need to save this json once -- or you need to update\n",
    "# with open(\"/home/tony/Data/Hoot/deezer_metas.json\", \"w\") as fp:\n",
    "#     json.dump(metas, fp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "aa66a026",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:10:02.592483Z",
     "start_time": "2024-01-09T15:10:01.314852Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:39.052404Z",
     "iopub.status.busy": "2025-01-14T00:23:39.052272Z",
     "iopub.status.idle": "2025-01-14T00:23:40.445874Z",
     "shell.execute_reply": "2025-01-14T00:23:40.445288Z",
     "shell.execute_reply.started": "2025-01-14T00:23:39.052391Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[('en', 1048844), ('es', 282036), ('pt', 127906), ('ja', 76236), ('fr', 74855), ('ru', 62426), ('de', 59326), ('it', 41398), ('tr', 39284), ('ko', 38938)]\n"
     ]
    }
   ],
   "source": [
    "# check language counts\n",
    "c = Counter([m[\"lang\"] for m in metas])\n",
    "print(c.most_common(10))\n",
    "# filter out languages with less than 50 clips\n",
    "metas_map = {m[\"id\"]: m for m in metas if c[m[\"lang\"]] > 50}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "2b486253",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:10:19.399035Z",
     "start_time": "2024-01-09T15:10:02.594795Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:40.446601Z",
     "iopub.status.busy": "2025-01-14T00:23:40.446446Z",
     "iopub.status.idle": "2025-01-14T00:23:43.203204Z",
     "shell.execute_reply": "2025-01-14T00:23:43.202628Z",
     "shell.execute_reply.started": "2025-01-14T00:23:40.446584Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2153940 filtered clips\n",
      "en 1048844 66921 hours\n",
      "es 282036 17264 hours\n",
      "pt 127906 7858 hours\n",
      "ja 76236 5362 hours\n",
      "fr 74855 4487 hours\n",
      "ru 62426 3561 hours\n",
      "de 59326 3477 hours\n",
      "it 41398 2567 hours\n",
      "tr 39284 2589 hours\n",
      "ko 38938 2400 hours\n"
     ]
    }
   ],
   "source": [
    "print(len(metas_map), \"filtered clips\")\n",
    "c = Counter([m[\"lang\"] for m in metas_map.values()])\n",
    "for k, v in c.most_common(10):\n",
    "    print(\n",
    "        k,\n",
    "        c[k],\n",
    "        round(sum(m[\"duration_s\"] for m in metas if m[\"lang\"] == k) / 60 / 60),\n",
    "        \"hours\",\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "c2ce5d00",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:10:19.404006Z",
     "start_time": "2024-01-09T15:10:19.401076Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:43.203888Z",
     "iopub.status.busy": "2025-01-14T00:23:43.203738Z",
     "iopub.status.idle": "2025-01-14T00:23:43.206949Z",
     "shell.execute_reply": "2025-01-14T00:23:43.206498Z",
     "shell.execute_reply.started": "2025-01-14T00:23:43.203872Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'id': 'DEJm1igan2Y', 'lyrics': '怎樣去率直理解甜蜜故事\\n才明白 才明白毋用曲折\\n誰待我過於優異\\n愈令我想起某次\\n情感的風險\\n傷害易忘記不易\\n連累共你哪樣發展\\n現時亦不知\\n\\n還未了解 自己可否愛更多\\n想接受你 卻害怕再失陷那後果\\n徘徊在我對你溫馨多單薄\\n你對我不減熾燙\\n怕甚麼 人愛多一趟 會錯多一趟\\n\\n請讓我充分理解緣分兩字\\n而明白 而明白無下一次\\n情共愛那點區別\\n愈令我分清界線\\n停於交叉點\\n等候著完美體現\\n難道共你繼續進展\\n便全部可知\\n\\n還未了解 自己可否愛更多\\n想接受你 卻害怕再失陷那後果\\n徘徊在我對你溫馨多單薄\\n你對我不減熾燙\\n有甚麼 能痛苦得過 要你多等我\\n\\n若是下個他一雙手彷彿都總更好\\n為甚在這刻雙手想與你盡力去抱\\n承認怪在我不好\\n胡亂製造太多苦惱\\n\\n還在了解 自己怎可愛更多\\n因有著你 我沒法了解尚欠甚麼\\n無疑問 你與我雙方都肯定\\n有了最佳的答案\\n發現得 時間多準確 最了解一個', 'duration_s': 245, 'lang': 'zh', 'audio_filepath': 's3://suno-data/shared/nfdg/DEJm1igan2Y/artists/songs/audio/DEJm1igan2Y/audio.webm'}\n"
     ]
    }
   ],
   "source": [
    "for m in metas:\n",
    "    if m[\"lang\"] == \"zh\":\n",
    "        print(m)\n",
    "        break"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "346cc768",
   "metadata": {},
   "source": [
    "# Pack the data\n",
    "format to save to:\n",
    "{\"audio_filepath\": \"./an4/wav/an4_clstk/fash/an251-fash-b.wav\", \"duration\": 1.0, \"text\": \"yes\"}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "71df5d56",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:10:20.258192Z",
     "start_time": "2024-01-09T15:10:19.486945Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:43.207648Z",
     "iopub.status.busy": "2025-01-14T00:23:43.207505Z",
     "iopub.status.idle": "2025-01-14T00:23:43.244969Z",
     "shell.execute_reply": "2025-01-14T00:23:43.244585Z",
     "shell.execute_reply.started": "2025-01-14T00:23:43.207634Z"
    }
   },
   "outputs": [],
   "source": [
    "# # this will also take 2 min...\n",
    "# pre_download_val_metas = read_jsonl(\"/app/suno/data/audio_2ch_48khz_lg/metas_val.jsonl\")\n",
    "# pre_download_train_metas = read_jsonl(\n",
    "#     \"/app/suno/data/audio_2ch_48khz_lg/metas_tr.jsonl\"\n",
    "# )\n",
    "# downloaded_ids_to_info = {}\n",
    "# for download_meta in pre_download_train_metas:\n",
    "#     if download_meta[\"original_id\"] not in downloaded_ids_to_info:\n",
    "#         downloaded_ids_to_info[download_meta[\"original_id\"]] = download_meta\n",
    "# for download_meta in pre_download_val_metas:\n",
    "#     if download_meta[\"original_id\"] not in downloaded_ids_to_info:\n",
    "#         downloaded_ids_to_info[download_meta[\"original_id\"]] = download_meta\n",
    "# downloaded_ids = set(downloaded_ids_to_info.keys())\n",
    "# print(len(downloaded_ids))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "9870b504",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:43.245543Z",
     "iopub.status.busy": "2025-01-14T00:23:43.245415Z",
     "iopub.status.idle": "2025-01-14T00:23:43.278868Z",
     "shell.execute_reply": "2025-01-14T00:23:43.278489Z",
     "shell.execute_reply.started": "2025-01-14T00:23:43.245530Z"
    }
   },
   "outputs": [],
   "source": [
    "# sum(\n",
    "#     download_meta[\"dataset\"] == \"genius_hq\"\n",
    "#     for download_meta in pre_download_train_metas\n",
    "# )\n",
    "# subset_meta = [\n",
    "#     m for m in metas if (m[\"id\"] in downloaded_ids)\n",
    "# ]  # and m[\"lang\"] == \"en\")]\n",
    "# print(len(subset_meta))\n",
    "# 986464"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "c8227733",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:10:20.872851Z",
     "start_time": "2024-01-09T15:10:20.261963Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:43.279446Z",
     "iopub.status.busy": "2025-01-14T00:23:43.279310Z",
     "iopub.status.idle": "2025-01-14T00:23:43.323282Z",
     "shell.execute_reply": "2025-01-14T00:23:43.322846Z",
     "shell.execute_reply.started": "2025-01-14T00:23:43.279433Z"
    }
   },
   "outputs": [],
   "source": [
    "subset_meta = metas.copy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "2f9e4207",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:10:21.009129Z",
     "start_time": "2024-01-09T15:10:20.874879Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:43.324006Z",
     "iopub.status.busy": "2025-01-14T00:23:43.323874Z",
     "iopub.status.idle": "2025-01-14T00:23:43.360124Z",
     "shell.execute_reply": "2025-01-14T00:23:43.359705Z",
     "shell.execute_reply.started": "2025-01-14T00:23:43.323993Z"
    }
   },
   "outputs": [],
   "source": [
    "RE_EMOJI = re.compile(\"[\\U00010000-\\U0010ffff]\", flags=re.UNICODE)\n",
    "\n",
    "\n",
    "def clean_text(text):\n",
    "    \"\"\"General text cleaning. A bit tight but makes the content very clean.\"\"\"\n",
    "    text = \"\\n\" + text\n",
    "    text = RE_EMOJI.sub(r\"\", text)  # remove emojis\n",
    "    text = text.replace(\"’\", \"'\").lower()\n",
    "    text = text.replace('\"', \"\").lower()\n",
    "    text = re.sub(r\"\\[.+?\\]\", \" \", text)  # tags\n",
    "    text = re.sub(r\"\\n.+?\\:\", \" \", text)  # new line ends with :\n",
    "    text = re.sub(r\"\\n.+?\\：\", \" \", text)  # new line ends with :\n",
    "    text = re.sub(r\"\\n\\(.+?\\)\", \" \", text)  # new line with ()\n",
    "    text = re.sub(r\"[\\d]\", \" \", text)  # digits\n",
    "    text = re.sub(r\"▁\", \"\", text)  # special stuff\n",
    "    text = remove_speakers(text)\n",
    "    text = re.sub(r\"[^\\w\\'\\s]\", \" \", text)  # keep only the words\n",
    "    text = normalize_whitespace(text)\n",
    "    return text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "0d2555e3",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:10:21.070547Z",
     "start_time": "2024-01-09T15:10:21.011397Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:43.360753Z",
     "iopub.status.busy": "2025-01-14T00:23:43.360609Z",
     "iopub.status.idle": "2025-01-14T00:23:43.396751Z",
     "shell.execute_reply": "2025-01-14T00:23:43.396322Z",
     "shell.execute_reply.started": "2025-01-14T00:23:43.360738Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Letra  de \"Calor\" ft. Lara91k]\n",
      "\n",
      "[Intro: Lara91k]\n",
      "Yeah, uh\n",
      "Ey, yeah, yeah\n",
      "Uh, yeah, yeah, ey\n",
      "Ey, ey, ey\n",
      "Préndelo, yeah\n",
      "\n",
      "[Estribillo: Lara91k]\n",
      "Préndelo, se ponen en fila por un blunt (Agítalo)\n",
      "Todo' venden su culo, mi amor (Acércalo)\n",
      "Ellos se prenden fuego en la Calor (Y así es como)\n",
      "Se dan vuelta como Courtney Love (Préndelo)\n",
      "Se ponen en fila por un blunt (Agítalo)\n",
      "Todo' venden su culo, mi amor (Acércalo)\n",
      "Ellos se prenden fuego en la Calor (Y así es como)\n",
      "Van dando vuelta' como Courtney Love\n",
      "Se ponen en fila por un blunt\n",
      "Todo' venden su culo, mi amor\n",
      "Ellos se prenden fuego en la Calor\n",
      "Se dan vuelta como Courtney Love\n",
      "\n",
      "[Verso 1: Neo Pistéa]\n",
      "Préndelo, mientras movémelo\n",
      "En lo oscuro, pegado al muro, ey\n",
      "Beba, vos prendémelo, que me agarra la calor\n",
      "Tu culo es ciencia ficción, quiero ver tu peliculón\n",
      "Si me acerco, prendo un blunt, no vas a decir que no\n",
      "Si te agarra la calor, causa una buena situación\n",
      "Qué rica satisfacción\n",
      "Prenderte aunque me meta en un lío más\n",
      "Si eso llama mi atención\n",
      "La plata y tu toto, esto es amor de verdad\n",
      "Ey, sí, que\n",
      "Dame, quiero chispa, girl\n",
      "Lo voy a prender y te voy a prender también\n",
      "¿Por qué no te prendés, bebé, y lo prendés?\n",
      "Después te pienso comer, te voy a comer\n",
      "Bebé, voy a comer pero-pero primero prendé\n",
      "¿Por qué no te prendés, bebé, y lo prendés?\n",
      "Desde que te vi bailando, la calor me está pegando\n",
      "Si veo que nadie nos mira, bebé, meto mano\n",
      "Si veo que nadie nos mira, traémelo\n",
      "Acércalo, agítalo, rolámelo y\n",
      "\n",
      "\n",
      "[Estribillo: Lara91k, Neo Pistéa & Ambos]\n",
      "Préndelo, se ponen en fila por un blunt (Agítalo)\n",
      "Todo' venden su culo, mi amor (Acércalo)\n",
      "Ellos se prenden fuego en la Calor (Y así es como)\n",
      "Se dan vuelta como Courtney Love (Préndelo)\n",
      "Se ponen en fila por un blunt (Agítalo, agítalo)\n",
      "Todo' venden su culo, mi amor (Acércalo, ey)\n",
      "Ellos se prenden fuego en la Calor (Y así es como, hace calor, babe)\n",
      "Van dando vuelta' como Courtney Love (Préndelo)\n",
      "Se ponen en fila por un blunt (Agítalo, babe)\n",
      "Todo' venden su culo, mi amor\n",
      "Ellos se prenden fuego en la Calor (Hace calor, babe)\n",
      "Se dan vuelta como Courtney Love\n",
      "\n",
      "[Verso 2: Lara91k]\n",
      "Hace calor, subió la tensión\n",
      "Tomamo' vitamina' para sentirno' mejor\n",
      "Hace calor, decís que no\n",
      "Sabe lo que quiere, pero llama mi atención\n",
      "Caigo con las pibas y siempre me voy con vos\n",
      "Ya sé que es temprano pero quiero irme con vos\n",
      "Y te lo juro, en lo oscuro, lo juro, no puedo\n",
      "Decirte que no, aunque siempre lo dude primero\n",
      "Baby, ya sabemo', esto fue siempre así\n",
      "Vos me enamoraste, por eso mentí\n",
      "Pero cuando juego pongo el on a mil\n",
      "Ansiando con tenerte y préndelo\n",
      "\n",
      "\n",
      "[Estribillo: Lara91k]\n",
      "Se ponen en fila por un blunt\n",
      "Todo' venden su culo, mi amor\n",
      "Ellos se prenden fuego en la Calor\n",
      "Se dan vuelta como Courtney Love (Préndelo)\n",
      "Se ponen en fila por un blunt (Agítalo)\n",
      "Todo' venden su culo, mi amor (Acércalo)\n",
      "Ellos se prenden fuego en la Calor (Y así es como)\n",
      "Dando una vuelta como Courtney Love\n",
      "-------\n",
      "yeah uh ey yeah yeah uh yeah yeah ey ey ey ey préndelo yeah préndelo se ponen en fila por un blunt agítalo todo' venden su culo mi amor acércalo ellos se prenden fuego en la calor y así es como se dan vuelta como courtney love préndelo se ponen en fila por un blunt agítalo todo' venden su culo mi amor acércalo ellos se prenden fuego en la calor y así es como van dando vuelta' como courtney love se ponen en fila por un blunt todo' venden su culo mi amor ellos se prenden fuego en la calor se dan vuelta como courtney love préndelo mientras movémelo en lo oscuro pegado al muro ey beba vos prendémelo que me agarra la calor tu culo es ciencia ficción quiero ver tu peliculón si me acerco prendo un blunt no vas a decir que no si te agarra la calor causa una buena situación qué rica satisfacción prenderte aunque me meta en un lío más si eso llama mi atención la plata y tu toto esto es amor de verdad ey sí que dame quiero chispa girl lo voy a prender y te voy a prender también por qué no te prendés bebé y lo prendés después te pienso comer te voy a comer bebé voy a comer pero pero primero prendé por qué no te prendés bebé y lo prendés desde que te vi bailando la calor me está pegando si veo que nadie nos mira bebé meto mano si veo que nadie nos mira traémelo acércalo agítalo rolámelo y préndelo se ponen en fila por un blunt agítalo todo' venden su culo mi amor acércalo ellos se prenden fuego en la calor y así es como se dan vuelta como courtney love préndelo se ponen en fila por un blunt agítalo agítalo todo' venden su culo mi amor acércalo ey ellos se prenden fuego en la calor y así es como hace calor babe van dando vuelta' como courtney love préndelo se ponen en fila por un blunt agítalo babe todo' venden su culo mi amor ellos se prenden fuego en la calor hace calor babe se dan vuelta como courtney love hace calor subió la tensión tomamo' vitamina' para sentirno' mejor hace calor decís que no sabe lo que quiere pero llama mi atención caigo con las pibas y siempre me voy con vos ya sé que es temprano pero quiero irme con vos y te lo juro en lo oscuro lo juro no puedo decirte que no aunque siempre lo dude primero baby ya sabemo' esto fue siempre así vos me enamoraste por eso mentí pero cuando juego pongo el on a mil ansiando con tenerte y préndelo se ponen en fila por un blunt todo' venden su culo mi amor ellos se prenden fuego en la calor se dan vuelta como courtney love préndelo se ponen en fila por un blunt agítalo todo' venden su culo mi amor acércalo ellos se prenden fuego en la calor y así es como dando una vuelta como courtney love\n"
     ]
    }
   ],
   "source": [
    "# Quality checks\n",
    "n_c = 0\n",
    "for m in metas:\n",
    "    if m[\"lang\"] == \"en\":\n",
    "        n_c += 1\n",
    "        if n_c == 1:\n",
    "            text = m[\"lyrics\"]\n",
    "            print(text)\n",
    "            print(\"-------\")\n",
    "            print(clean_text(text))\n",
    "            break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "e8b679e7",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:10:21.167632Z",
     "start_time": "2024-01-09T15:10:21.072528Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:43.397353Z",
     "iopub.status.busy": "2025-01-14T00:23:43.397215Z",
     "iopub.status.idle": "2025-01-14T00:23:43.455604Z",
     "shell.execute_reply": "2025-01-14T00:23:43.455194Z",
     "shell.execute_reply.started": "2025-01-14T00:23:43.397338Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# TODO: swap to larger tokenizer\n",
    "import sentencepiece\n",
    "\n",
    "tokenizer = sentencepiece.SentencePieceProcessor()\n",
    "tokenizer.load(\"tokenizer_spe_bpe_v20480/tokenizer.model\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "feacb5f1",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T15:10:22.487284Z",
     "start_time": "2024-01-09T15:10:21.169512Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:43.456202Z",
     "iopub.status.busy": "2025-01-14T00:23:43.456070Z",
     "iopub.status.idle": "2025-01-14T00:23:44.817495Z",
     "shell.execute_reply": "2025-01-14T00:23:44.816908Z",
     "shell.execute_reply.started": "2025-01-14T00:23:43.456189Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1835250 1835250\n"
     ]
    }
   ],
   "source": [
    "print(len(subset_meta), len(set(m[\"original_id\"] for m in subset_meta)))\n",
    "random.shuffle(subset_meta)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "8d3fa27d-c422-444d-8fbf-149274636627",
   "metadata": {
    "execution": {
     "iopub.status.busy": "2025-01-15T01:20:39.231764Z",
     "iopub.status.idle": "2025-01-15T01:20:39.231945Z",
     "shell.execute_reply": "2025-01-15T01:20:39.231859Z",
     "shell.execute_reply.started": "2025-01-15T01:20:39.231851Z"
    }
   },
   "outputs": [],
   "source": [
    "## two nodes 35 hrs to download"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "3a3246ca",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:53.367719Z",
     "start_time": "2024-01-09T15:10:22.489702Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T00:23:44.818238Z",
     "iopub.status.busy": "2025-01-14T00:23:44.818090Z",
     "iopub.status.idle": "2025-01-14T01:36:38.514831Z",
     "shell.execute_reply": "2025-01-14T01:36:38.514272Z",
     "shell.execute_reply.started": "2025-01-14T00:23:44.818222Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 1835250/1835250 [1:05:19<00:00, 468.25it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total 1808484, too long: 19821, text too short: 587, text too long: 191, text bad: 6167\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "total_infos = []\n",
    "n_text_too_short = 0\n",
    "n_text_too_long = 0\n",
    "n_audio_too_long = 0\n",
    "n_lang = collections.defaultdict(int)\n",
    "n_repeat_ratio_too_high = 0\n",
    "n_lang_max_cut = 5_000_000  # 10k songs :D, 2_000_000 is max\n",
    "bad_meta_ids = []\n",
    "for meta in tqdm.tqdm(subset_meta):\n",
    "    output_path = os.path.join(\n",
    "        \"/app/suno/data/hoot/audios/genius\", f\"{meta['original_id']}.mp3\"\n",
    "    )\n",
    "    if not os.path.exists(output_path):\n",
    "        continue\n",
    "    # output_path = downloaded_ids_to_info[meta[\"id\"]][\"filepath\"]\n",
    "    if (\n",
    "        meta[\"duration_s\"] > 400\n",
    "    ):  # this cut is mainly for batching purposes...X.x, but...we probably shouldn't have this.\n",
    "        n_audio_too_long += 1\n",
    "        continue\n",
    "    n_lang[meta[\"lang\"]] += 1\n",
    "    # if n_lang[meta[\"lang\"]] > n_lang_max_cut:\n",
    "    #     continue\n",
    "    cleaned_text = clean_text(meta[\"lyrics\"])\n",
    "    # cleaned_text = meta[\"lyrics\"].lower() # clean_text(meta[\"lyrics\"])\n",
    "    #     cleaned_tokens = tokenizer.encode(cleaned_text)\n",
    "    #     decoded_tokens = tokenizer.decode(cleaned_tokens)\n",
    "    #     if decoded_tokens != cleaned_text:\n",
    "    #         print(cleaned_text)\n",
    "    #         print(decoded_tokens)\n",
    "    if len(cleaned_text) < 20:\n",
    "        n_text_too_short += 1\n",
    "        continue\n",
    "    # check the high freq token frequency\n",
    "    encoded_array = np.array(tokenizer.encode(cleaned_text))\n",
    "    if len(encoded_array) > meta[\"duration_s\"] * 12:\n",
    "        n_text_too_long += 1\n",
    "        continue\n",
    "    repeat_ratio = max(np.bincount(encoded_array)) / (encoded_array.shape[0] + 1)\n",
    "    if repeat_ratio > 0.3:\n",
    "        n_repeat_ratio_too_high += 1\n",
    "        bad_meta_ids.append(meta[\"id\"])\n",
    "        continue\n",
    "    total_infos.append(\n",
    "        {\n",
    "            \"audio_filepath\": output_path,\n",
    "            \"duration\": meta[\"duration_s\"],\n",
    "            \"text\": cleaned_text,\n",
    "            \"lyrics\": meta[\"lyrics\"],\n",
    "            \"lang\": meta[\"lang\"],\n",
    "            \"id\": meta[\"id\"],\n",
    "            \"genius_views\": meta.get(\"genius_views\", 0),\n",
    "            \"youtube_views\": meta.get(\"youtube_views\", 0),\n",
    "        }\n",
    "    )\n",
    "    if not os.path.exists(output_path):\n",
    "        # print(\"WTF\", output_path)\n",
    "        continue\n",
    "#     audio = Audio.from_s3(meta[\"audio_filepath\"])\n",
    "#     audio = audio.convert(16_000, audio.byte_width, n_channels=1)\n",
    "#     audio.to_wav(output_path)\n",
    "print(\n",
    "    f\"total {len(total_infos)}, too long: {n_audio_too_long}, text too short: {n_text_too_short}, text too long: {n_text_too_long}, text bad: {n_repeat_ratio_too_high}\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "618075a0",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:54.930054Z",
     "start_time": "2024-01-09T16:37:53.368988Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:38.515547Z",
     "iopub.status.busy": "2025-01-14T01:36:38.515398Z",
     "iopub.status.idle": "2025-01-14T01:36:40.077169Z",
     "shell.execute_reply": "2025-01-14T01:36:40.076608Z",
     "shell.execute_reply.started": "2025-01-14T01:36:38.515532Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total duration khr 104.18152833333333 60 400 20 8941\n"
     ]
    }
   ],
   "source": [
    "print(\n",
    "    \"total duration khr\",\n",
    "    sum(m[\"duration\"] for m in total_infos) / 3600000,\n",
    "    min(m[\"duration\"] for m in total_infos),\n",
    "    max(m[\"duration\"] for m in total_infos),\n",
    "    min(len(m[\"text\"]) for m in total_infos),\n",
    "    max(len(m[\"text\"]) for m in total_infos),\n",
    ")\n",
    "# 29.15879888888889 120 100 2879\n",
    "# cut on durations 400: total duration khr 88.80962305555556 60 480 100 5616\n",
    "# cut on 240: total duration khr 54.709809444444446 60 240 100 2880"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "76dcc2f9-777f-476e-b190-fddced599117",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-15T01:20:50.635781Z",
     "iopub.status.busy": "2025-01-15T01:20:50.635598Z",
     "iopub.status.idle": "2025-01-15T01:20:50.638227Z",
     "shell.execute_reply": "2025-01-15T01:20:50.637805Z",
     "shell.execute_reply.started": "2025-01-15T01:20:50.635766Z"
    }
   },
   "outputs": [],
   "source": [
    "# exist_info = []\n",
    "# for test_input in test_info:\n",
    "#     if os.path.exists(test_input[\"audio_filepath\"]):\n",
    "#         exist_info.append(test_input)\n",
    "# print(len(info), len(exist_info))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "d8eb67a9",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:55.757800Z",
     "start_time": "2024-01-09T16:37:54.931303Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-15T00:53:38.889667Z",
     "iopub.status.busy": "2025-01-15T00:53:38.889229Z",
     "iopub.status.idle": "2025-01-15T00:53:38.893159Z",
     "shell.execute_reply": "2025-01-15T00:53:38.892581Z",
     "shell.execute_reply.started": "2025-01-15T00:53:38.889646Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1808484 0\n"
     ]
    }
   ],
   "source": [
    "# cutoff = -2000\n",
    "# random.shuffle(info)\n",
    "# train_info = info[:cutoff]\n",
    "# test_info = info[cutoff:]\n",
    "# print(len(train_info), len(test_info))\n",
    "# # 545838 1000\n",
    "train_info = total_infos.copy()\n",
    "test_info = []\n",
    "print(len(train_info), len(test_info))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "72bc9539",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:40.832617Z",
     "iopub.status.busy": "2025-01-14T01:36:40.832218Z",
     "iopub.status.idle": "2025-01-14T01:36:40.834572Z",
     "shell.execute_reply": "2025-01-14T01:36:40.834176Z",
     "shell.execute_reply.started": "2025-01-14T01:36:40.832599Z"
    }
   },
   "outputs": [],
   "source": [
    "# BREAK"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "a48b2d77",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:55.761119Z",
     "start_time": "2024-01-09T16:37:55.759035Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:40.835146Z",
     "iopub.status.busy": "2025-01-14T01:36:40.835018Z",
     "iopub.status.idle": "2025-01-14T01:36:40.870228Z",
     "shell.execute_reply": "2025-01-14T01:36:40.869844Z",
     "shell.execute_reply.started": "2025-01-14T01:36:40.835132Z"
    }
   },
   "outputs": [],
   "source": [
    "# with open(\"/home/tony/Data/Hoot/all_train_manifest_fast.json\", \"w\") as fp:\n",
    "#     # for l in train_info[:80]:\n",
    "#     for l in train_info[:80]:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write('\\n')\n",
    "# with open(\"/home/tony/Data/Hoot/all_test_manifest_fast.json\", \"w\") as fp:\n",
    "#     for l in test_info[:8]:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write('\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "4a7003ff",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:55.836785Z",
     "start_time": "2024-01-09T16:37:55.762070Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:40.870803Z",
     "iopub.status.busy": "2025-01-14T01:36:40.870669Z",
     "iopub.status.idle": "2025-01-14T01:36:40.906745Z",
     "shell.execute_reply": "2025-01-14T01:36:40.906369Z",
     "shell.execute_reply.started": "2025-01-14T01:36:40.870789Z"
    }
   },
   "outputs": [],
   "source": [
    "# with open(\"/home/tony/Data/Hoot/multi_all_104khr_filtered_train_manifest.json\", \"w\") as fp:\n",
    "#     for l in train_info:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write('\\n')\n",
    "# with open(\"/home/tony/Data/Hoot/multi_all_104khr_filtered_test_manifest.json\", \"w\") as fp:\n",
    "#     for l in test_info:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write('\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "506b6b20",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:55.891610Z",
     "start_time": "2024-01-09T16:37:55.838219Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:40.907307Z",
     "iopub.status.busy": "2025-01-14T01:36:40.907178Z",
     "iopub.status.idle": "2025-01-14T01:36:40.944089Z",
     "shell.execute_reply": "2025-01-14T01:36:40.943708Z",
     "shell.execute_reply.started": "2025-01-14T01:36:40.907294Z"
    }
   },
   "outputs": [],
   "source": [
    "# with open(DataStoreObject(manifest).get(), 'r') as in_reader:\n",
    "#     for line in in_reader:\n",
    "#         item = json.loads(line)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5907d689",
   "metadata": {},
   "source": [
    "# Train the tokenizer"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3a36ab23",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "- 0.998 has vocab size of 780\n",
    "- 0.9995 has vocab size of 1936\n",
    "- 0.9996 has vocab of 2176\n",
    "- 0.9999 has vocab of 3878\n",
    "- 1.0 has vocab of 12402\n",
    "------------------------\n",
    "python ./scripts/process_asr_text_tokenizer.py \\\n",
    "  --manifest=\"/home/tony/Data/Hoot/all_train_manifest.json\" \\\n",
    "  --data_root=\"./tokenizers/all/\" \\\n",
    "  --vocab_size=1024 \\\n",
    "  --tokenizer=\"spe\" \\\n",
    "  --spe_character_coverage=0.998 \\\n",
    "  --spe_type=\"bpe\" \\\n",
    "  --log\n",
    "\n",
    "------------------------\n",
    "python ./scripts/process_asr_text_tokenizer.py \\\n",
    "  --manifest=\"/home/tony/Data/Hoot/all_train_manifest.json\" \\\n",
    "  --data_root=\"./tokenizers/multi/\" \\\n",
    "  --vocab_size=5120 \\\n",
    "  --tokenizer=\"spe\" \\\n",
    "  --spe_character_coverage=0.9999 \\\n",
    "  --spe_type=\"bpe\" \\\n",
    "  --log\n",
    "  \n",
    " ------------------------\n",
    "python ./scripts/process_asr_text_tokenizer.py \\\n",
    "  --manifest=\"/home/tony/Data/Hoot/multi_filtered_train_manifest.json\" \\\n",
    "  --data_root=\"./tokenizers/multi_filtered/\" \\\n",
    "  --vocab_size=5120 \\\n",
    "  --tokenizer=\"spe\" \\\n",
    "  --spe_character_coverage=0.9999 \\\n",
    "  --spe_type=\"bpe\" \\\n",
    "  --log\n",
    "  \n",
    "   ------------------------\n",
    " python ./scripts/process_asr_text_tokenizer.py \\\n",
    "  --manifest=\"/home/tony/Data/Hoot/metas.json\" \\\n",
    "  --data_root=\"./tokenizers/full/\" \\\n",
    "  --vocab_size=10240 \\\n",
    "  --tokenizer=\"spe\" \\\n",
    "  --spe_character_coverage=1.0 \\\n",
    "  --spe_type=\"bpe\" \\\n",
    "  --log\n",
    "  \n",
    "   ------------------------\n",
    " python ./scripts/process_asr_text_tokenizer.py \\\n",
    "  --manifest=\"/home/tony/Data/Hoot/multi_all_104khr_filtered_train_manifest.json\" \\\n",
    "  --data_root=\"./tokenizers/v3/\" \\\n",
    "  --vocab_size=10241 \\\n",
    "  --tokenizer=\"spe\" \\\n",
    "  --spe_character_coverage=1.0 \\\n",
    "  --spe_type=\"bpe\" \\\n",
    "  --log"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0616448",
   "metadata": {},
   "source": [
    "# Check tokenzier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "253035d4",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:55.947077Z",
     "start_time": "2024-01-09T16:37:55.892947Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:40.944620Z",
     "iopub.status.busy": "2025-01-14T01:36:40.944495Z",
     "iopub.status.idle": "2025-01-14T01:36:40.981045Z",
     "shell.execute_reply": "2025-01-14T01:36:40.980637Z",
     "shell.execute_reply.started": "2025-01-14T01:36:40.944606Z"
    }
   },
   "outputs": [],
   "source": [
    "test_text = \"whoa oh oh whoa oh oh whoa oh oh oh oh oh oh whoa oh oh whoa oh oh whoa oh oh oh oh oh oh 취할 것 같은 불빛이 화려한 밤에 누구보다도 자유로워 지기를 바래 아름다운 이 순간이 끝나기 전에 바람소리에 이 음악이 실리길 원해 whoa oh oh whoa oh oh whoa oh oh oh oh oh oh whoa oh oh whoa oh oh whoa oh oh oh oh oh oh lets get it on tonight and set me free tonight 이 순간 즐겨봐 너와 나 소리 높여 lets groove it party time 두근거리는 느낌이 황홀한 밤에 푸른 바다에 달빛을 물들이길 바래 파도가 이 밤을 데려가기 전에 지금 이대로 시간이 멈추기를 원해 whoa oh oh whoa oh oh whoa oh oh oh oh oh oh whoa oh oh whoa oh oh whoa oh oh oh oh oh oh 이 순간 즐겨봐 너와 나 소리 높여 lets groove it party time whoa oh oh whoa oh oh whoa oh oh oh oh oh oh whoa oh oh whoa oh oh whoa oh oh oh oh oh oh 이 순간 즐겨봐 너와 나 소리 높여 lets groove it party time whoa whoa whoa yeah oh whoa oh whoa oh whoa\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "d0599dc0",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:56.061972Z",
     "start_time": "2024-01-09T16:37:55.948411Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:40.981716Z",
     "iopub.status.busy": "2025-01-14T01:36:40.981584Z",
     "iopub.status.idle": "2025-01-14T01:36:41.081968Z",
     "shell.execute_reply": "2025-01-14T01:36:41.081553Z",
     "shell.execute_reply.started": "2025-01-14T01:36:40.981702Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import sentencepiece\n",
    "\n",
    "tokenizer = sentencepiece.SentencePieceProcessor()\n",
    "tokenizer.load(\"tokenizer_spe_bpe_v20480/tokenizer.model\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "6baf7076",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:56.122437Z",
     "start_time": "2024-01-09T16:37:56.063015Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:41.082560Z",
     "iopub.status.busy": "2025-01-14T01:36:41.082427Z",
     "iopub.status.idle": "2025-01-14T01:36:41.108656Z",
     "shell.execute_reply": "2025-01-14T01:36:41.108197Z",
     "shell.execute_reply.started": "2025-01-14T01:36:41.082546Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(312,)\n",
      "whoa oh oh whoa oh oh whoa oh oh oh oh oh oh whoa oh oh whoa oh oh whoa oh oh oh oh oh oh 취할 것 같은 불빛이 화려한 밤에 누구보다도 자유로워 지기를 바래 아름다운 이 순간이 끝나기 전에 바람소리에 이 음악이 실리길 원해 whoa oh oh whoa oh oh whoa oh oh oh oh oh oh whoa oh oh whoa oh oh whoa oh oh oh oh oh oh lets get it on tonight and set me free tonight 이 순간 즐겨봐 너와 나 소리 높여 lets groove it party time 두근거리는 느낌이 황홀한 밤에 푸른 바다에 달빛을 물들이길 바래 파도가 이 밤을 데려가기 전에 지금 이대로 시간이 멈추기를 원해 whoa oh oh whoa oh oh whoa oh oh oh oh oh oh whoa oh oh whoa oh oh whoa oh oh oh oh oh oh 이 순간 즐겨봐 너와 나 소리 높여 lets groove it party time whoa oh oh whoa oh oh whoa oh oh oh oh oh oh whoa oh oh whoa oh oh whoa oh oh oh oh oh oh 이 순간 즐겨봐 너와 나 소리 높여 lets groove it party time whoa whoa whoa yeah oh whoa oh whoa oh whoa\n"
     ]
    }
   ],
   "source": [
    "print(np.array(tokenizer.encode(test_text)).shape)\n",
    "print(tokenizer.decode(tokenizer.encode(test_text)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d966633",
   "metadata": {},
   "source": [
    "# DEBUG"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "353d4d0f",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:56.239480Z",
     "start_time": "2024-01-09T16:37:56.184175Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:41.109247Z",
     "iopub.status.busy": "2025-01-14T01:36:41.109114Z",
     "iopub.status.idle": "2025-01-14T01:36:41.202044Z",
     "shell.execute_reply": "2025-01-14T01:36:41.201540Z",
     "shell.execute_reply.started": "2025-01-14T01:36:41.109233Z"
    }
   },
   "outputs": [],
   "source": [
    "# x = []\n",
    "# with open(\"/home/tony/Data/Hoot/all_train_manifest.json\", \"r\") as fp:\n",
    "#      for l in fp:\n",
    "#         x.append(json.loads(l))\n",
    "\n",
    "# bad_indices = []\n",
    "# for i, meta in tqdm.tqdm(enumerate(x)):\n",
    "#     encoded_array = np.array(tokenizer.encode(meta[\"text\"]))\n",
    "#     repeat_ratio = max(np.bincount(encoded_array)) / (encoded_array.shape[0] + 1)\n",
    "#     if repeat_ratio > 0.3:\n",
    "#         # print(repeat_ratio, meta)\n",
    "#         bad_indices.append(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "e5f54770",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:56.293353Z",
     "start_time": "2024-01-09T16:37:56.240396Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:41.202685Z",
     "iopub.status.busy": "2025-01-14T01:36:41.202544Z",
     "iopub.status.idle": "2025-01-14T01:36:41.239169Z",
     "shell.execute_reply": "2025-01-14T01:36:41.238783Z",
     "shell.execute_reply.started": "2025-01-14T01:36:41.202670Z"
    }
   },
   "outputs": [],
   "source": [
    "# len(bad_indices)\n",
    "\n",
    "# bad_ids = [\n",
    "#     36004, 91329, 772492\n",
    "# ]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "f65a307d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:56.365226Z",
     "start_time": "2024-01-09T16:37:56.294287Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:41.239745Z",
     "iopub.status.busy": "2025-01-14T01:36:41.239620Z",
     "iopub.status.idle": "2025-01-14T01:36:41.273980Z",
     "shell.execute_reply": "2025-01-14T01:36:41.273608Z",
     "shell.execute_reply.started": "2025-01-14T01:36:41.239732Z"
    }
   },
   "outputs": [],
   "source": [
    "# with open(\"/home/tony/Data/Hoot/all_train_manifest_debug.json\", \"w\") as fp:\n",
    "#     # for l in train_info[:80]:\n",
    "#     for l in selected:\n",
    "#         json.dump(x[l], fp, ensure_ascii=True)\n",
    "#         fp.write('\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "9c374d06",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:56.420690Z",
     "start_time": "2024-01-09T16:37:56.366689Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:41.274539Z",
     "iopub.status.busy": "2025-01-14T01:36:41.274414Z",
     "iopub.status.idle": "2025-01-14T01:36:41.312345Z",
     "shell.execute_reply": "2025-01-14T01:36:41.311969Z",
     "shell.execute_reply.started": "2025-01-14T01:36:41.274526Z"
    }
   },
   "outputs": [],
   "source": [
    "# for bad_id in bad_ids:\n",
    "#     print(x[bad_id])\n",
    "\n",
    "# test_audio = Audio.from_file('/app/suno/data/hoot/2I8_OV4DtCs.wav')\n",
    "# test_audio.play(compress=False)\n",
    "\n",
    "# for meta in base_metas:\n",
    "#     if meta[\"original_id\"] == \"JpkwJW92UcY\":\n",
    "#         print(meta)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7f8985c",
   "metadata": {},
   "source": [
    "# Load the hooted output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "a7be6e73",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:56.505275Z",
     "start_time": "2024-01-09T16:37:56.421982Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:41.312896Z",
     "iopub.status.busy": "2025-01-14T01:36:41.312777Z",
     "iopub.status.idle": "2025-01-14T01:36:41.350393Z",
     "shell.execute_reply": "2025-01-14T01:36:41.350007Z",
     "shell.execute_reply.started": "2025-01-14T01:36:41.312884Z"
    }
   },
   "outputs": [],
   "source": [
    "# total_infos = dict()\n",
    "# for i in tqdm.tqdm(range(0, 1836168, 100)):\n",
    "#     if not os.path.exists(f\"/home/tony/Data/Hoot/alignments/outputs/batch_{i}.json\"):\n",
    "#         # print(\"Missing,\", i)\n",
    "#         continue\n",
    "#     try:\n",
    "#         with open(f\"/home/tony/Data/Hoot/alignments/outputs/batch_{i}.json\", \"r\") as fp:\n",
    "#             infos = json.load(fp)\n",
    "#         for x_info in infos:\n",
    "#             if x_info[\"id\"] in total_infos:\n",
    "#                 break\n",
    "#             total_infos[x_info[\"id\"]] = x_info[\"cer_val\"]\n",
    "#     except:\n",
    "#         # print(\"WTF,\", i)\n",
    "#         pass\n",
    "\n",
    "# plt.hist(total_infos.values(), bins=np.linspace(0, 1, 50))\n",
    "# plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "552c1c73",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:56.570374Z",
     "start_time": "2024-01-09T16:37:56.506567Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:41.351050Z",
     "iopub.status.busy": "2025-01-14T01:36:41.350923Z",
     "iopub.status.idle": "2025-01-14T01:36:41.385902Z",
     "shell.execute_reply": "2025-01-14T01:36:41.385519Z",
     "shell.execute_reply.started": "2025-01-14T01:36:41.351037Z"
    }
   },
   "outputs": [],
   "source": [
    "# high_cer_infos = {k:v for k, v in total_infos.items() if v < 0.4}\n",
    "# print(len(high_cer_infos))\n",
    "\n",
    "# high_cer_train_info = []\n",
    "# for info in train_info:\n",
    "#     if info[\"id\"] in high_cer_infos and info[\"duration\"] < 240:\n",
    "#         high_cer_train_info.append(info)\n",
    "# print(len(high_cer_train_info))\n",
    "\n",
    "# print(\n",
    "#     \"total duration khr\", sum(m[\"duration\"] for m in high_cer_train_info) / 3600000,\n",
    "#     min(m[\"duration\"] for m in high_cer_train_info),\n",
    "#     max(m[\"duration\"] for m in high_cer_train_info),\n",
    "#     min(len(m[\"text\"]) for m in high_cer_train_info),\n",
    "#     max(len(m[\"text\"]) for m in high_cer_train_info),\n",
    "# )\n",
    "\n",
    "# print(Counter(m[\"lang\"] for m in high_cer_train_info))\n",
    "\n",
    "# cutoff = -2000\n",
    "# random.shuffle(high_cer_train_info)\n",
    "# high_cer_train_info, high_cer_test_info = high_cer_train_info[:cutoff], high_cer_train_info[cutoff:]\n",
    "# print(len(high_cer_train_info), len(high_cer_test_info))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "417c0eb3",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-09T16:37:56.651676Z",
     "start_time": "2024-01-09T16:37:56.571763Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:41.386487Z",
     "iopub.status.busy": "2025-01-14T01:36:41.386360Z",
     "iopub.status.idle": "2025-01-14T01:36:41.427365Z",
     "shell.execute_reply": "2025-01-14T01:36:41.426982Z",
     "shell.execute_reply.started": "2025-01-14T01:36:41.386474Z"
    }
   },
   "outputs": [],
   "source": [
    "# with open(\"/home/tony/Data/Hoot/multi_large_vocab_cer_04_train.json\", \"w\") as fp:\n",
    "#     for l in high_cer_train_info:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write('\\n')\n",
    "# with open(\"/home/tony/Data/Hoot/multi_large_vocab_cer_04_test.json\", \"w\") as fp:\n",
    "#     for l in high_cer_test_info:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write('\\n')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1642e3b5",
   "metadata": {},
   "source": [
    "# 2nd round of hoot data prep setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "52f2a9a1",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-18T02:43:46.229977Z",
     "start_time": "2024-01-18T02:43:05.476371Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:41.427915Z",
     "iopub.status.busy": "2025-01-14T01:36:41.427793Z",
     "iopub.status.idle": "2025-01-14T01:36:42.450600Z",
     "shell.execute_reply": "2025-01-14T01:36:42.450006Z",
     "shell.execute_reply.started": "2025-01-14T01:36:41.427903Z"
    }
   },
   "outputs": [],
   "source": [
    "with open(\"/home/tony/Data/Hoot/deezer_metas.json\", \"r\") as fp:\n",
    "    metas = json.load(fp)\n",
    "metas_map = {m[\"id\"]: m for m in metas}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "274e39d7",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-18T02:57:19.260628Z",
     "start_time": "2024-01-18T02:43:49.821152Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:36:42.451326Z",
     "iopub.status.busy": "2025-01-14T01:36:42.451172Z",
     "iopub.status.idle": "2025-01-14T01:47:52.315467Z",
     "shell.execute_reply": "2025-01-14T01:47:52.314897Z",
     "shell.execute_reply.started": "2025-01-14T01:36:42.451310Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 7618/7618 [07:24<00:00, 17.15it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WTF, 761700\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "from collections import defaultdict\n",
    "\n",
    "total_infos_2 = dict()\n",
    "lang_cers = defaultdict(list)\n",
    "for i in tqdm.tqdm(range(0, 761800, 100)):\n",
    "    try:\n",
    "        with open(\n",
    "            f\"/app/suno/data/hoot/alignments/deezer_v5/batch_{i}.json\", \"r\"\n",
    "        ) as fp:\n",
    "            infos = json.load(fp)\n",
    "        for x_info in infos:\n",
    "            if x_info[\"id\"] in total_infos_2:\n",
    "                break\n",
    "            if x_info[\"id\"] not in metas_map:\n",
    "                continue\n",
    "            # if x_info[\"id\"] not in metas_map:\n",
    "            # this is somehow already filtered out...?\n",
    "            total_infos_2[x_info[\"id\"]] = x_info[\"cer_val\"]\n",
    "            lang_cers[metas_map[x_info[\"id\"]][\"lang\"]].append(x_info[\"cer_val\"])\n",
    "    except:\n",
    "        print(\"WTF,\", i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "033dc016",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-18T02:57:19.317468Z",
     "start_time": "2024-01-18T02:57:19.266816Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:47:52.316177Z",
     "iopub.status.busy": "2025-01-14T01:47:52.316027Z",
     "iopub.status.idle": "2025-01-14T01:47:52.319363Z",
     "shell.execute_reply": "2025-01-14T01:47:52.318967Z",
     "shell.execute_reply.started": "2025-01-14T01:47:52.316161Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(698626, 137, 698626)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(total_infos_2), len(lang_cers), sum(len(v) for v in lang_cers.values())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ca6fcca0",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-18T02:57:19.825960Z",
     "start_time": "2024-01-18T02:57:19.318687Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:47:52.320042Z",
     "iopub.status.busy": "2025-01-14T01:47:52.319914Z",
     "iopub.status.idle": "2025-01-14T01:47:52.753995Z",
     "shell.execute_reply": "2025-01-14T01:47:52.753453Z",
     "shell.execute_reply.started": "2025-01-14T01:47:52.320028Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "lang n_songs median cer\n",
      "en 465756 0.167\n",
      "es 63904 0.145\n",
      "fr 26005 0.217\n",
      "de 23036 0.172\n",
      "it 22808 0.128\n",
      "pt 21799 0.152\n",
      "ko 16577 0.303\n",
      "ja 10350 0.335\n",
      "hi 8874 0.349\n",
      "tr 5209 0.171\n",
      "ar 4925 0.301\n",
      "ru 4811 0.204\n",
      "id 3638 0.217\n",
      "pa 3622 0.33\n",
      "nl 1872 0.274\n",
      "tl 1862 0.288\n",
      "pl 1130 0.178\n",
      "sv 1035 0.296\n",
      "ro 977 0.272\n",
      "fi 804 0.32\n",
      "cs 802 0.25\n",
      "af 587 0.303\n",
      "sr 587 0.209\n",
      "vi 452 0.266\n",
      "he 444 0.304\n",
      "no 409 0.343\n",
      "sk 400 0.302\n",
      "da 398 0.305\n",
      "hu 393 0.339\n",
      "sl 345 0.361\n",
      "zh 341 0.414\n",
      "mr 336 0.419\n",
      "uk 291 0.352\n",
      "el 268 0.427\n",
      "th 256 0.418\n",
      "hr 246 0.284\n",
      "fa 239 0.283\n",
      "ca 197 0.348\n",
      "et 170 0.476\n",
      "lv 152 0.381\n",
      "sq 142 0.432\n",
      "lt 129 0.452\n",
      "sw 117 0.522\n",
      "ms 108 0.401\n",
      "eu 107 0.589\n",
      "ku 104 0.682\n",
      "bg 92 0.32\n",
      "eo 88 0.692\n",
      "als 82 0.578\n",
      "cy 79 0.708\n",
      "la 66 0.627\n",
      "is 65 0.622\n",
      "arz 65 0.342\n",
      "km 55 0.992\n",
      "az 48 0.376\n",
      "bn 45 0.372\n",
      "ceb 44 0.572\n",
      "war 42 0.703\n",
      "nn 40 0.378\n",
      "bh 39 0.571\n",
      "su 37 0.628\n",
      "si 36 0.97\n",
      "ta 33 0.412\n",
      "yi 32 0.838\n",
      "gu 31 1.0\n",
      "gl 31 0.365\n",
      "ht 30 0.452\n",
      "mn 28 0.677\n",
      "sh 27 0.326\n",
      "am 26 0.516\n",
      "ur 25 0.842\n",
      "bs 24 0.49\n",
      "kk 19 0.591\n",
      "mg 19 0.7\n",
      "br 19 0.685\n",
      "ga 18 0.816\n",
      "ne 17 0.366\n",
      "nap 16 0.573\n",
      "lb 16 0.502\n",
      "hy 15 0.547\n",
      "mk 14 0.725\n",
      "io 12 0.66\n",
      "ast 12 0.44\n",
      "ml 11 1.0\n",
      "jv 11 0.448\n",
      "kw 11 0.519\n",
      "jbo 11 0.621\n",
      "lmo 10 0.595\n",
      "sa 10 0.588\n",
      "bo 9 1.0\n",
      "ia 9 0.724\n",
      "ky 9 0.526\n",
      "kn 8 0.778\n",
      "uz 8 0.962\n",
      "ka 7 0.618\n",
      "nds 7 0.448\n",
      "vec 7 0.585\n",
      "my 6 0.876\n",
      "mt 5 0.78\n",
      "qu 5 0.509\n",
      "eml 5 0.682\n",
      "pms 4 0.645\n",
      "fy 4 0.488\n",
      "be 4 0.461\n",
      "yo 4 0.686\n",
      "so 4 0.722\n",
      "ckb 4 0.68\n",
      "gn 4 0.638\n",
      "scn 4 0.71\n",
      "ilo 3 0.531\n",
      "sc 3 0.603\n",
      "new 3 0.448\n",
      "ie 3 0.563\n",
      "as 2 0.489\n",
      "gv 2 0.76\n",
      "an 2 0.76\n",
      "min 2 0.503\n",
      "lo 2 0.93\n",
      "tk 2 0.663\n",
      "oc 2 0.693\n",
      "rm 2 0.704\n"
     ]
    }
   ],
   "source": [
    "langs = [(k, len(v)) for k, v in lang_cers.items()]\n",
    "langs.sort(key=lambda x: (-x[1]))\n",
    "print(\"lang n_songs median cer\")\n",
    "cer_percentage_threshold = 0.5\n",
    "langs_cer_cut = {}\n",
    "for k, l_v in langs:\n",
    "    v = lang_cers[k]\n",
    "    if l_v > 1:\n",
    "        print(k, l_v, round(np.quantile(v, cer_percentage_threshold), 3))\n",
    "        langs_cer_cut[k] = round(np.quantile(v, cer_percentage_threshold), 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "bf85525f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "lang n_songs median cer\n",
      "en 465756 0.167\n",
      "es 63904 0.145\n",
      "fr 26005 0.217\n",
      "de 23036 0.172\n",
      "it 22808 0.128\n",
      "pt 21799 0.152\n",
      "ko 16577 0.303\n",
      "ja 10350 0.335\n",
      "hi 8874 0.349\n",
      "tr 5209 0.171\n",
      "ar 4925 0.301\n",
      "ru 4811 0.204\n",
      "id 3638 0.217\n",
      "pa 3622 0.33\n",
      "nl 1872 0.274\n",
      "tl 1862 0.288\n",
      "pl 1130 0.178\n",
      "sv 1035 0.296\n",
      "ro 977 0.272\n",
      "fi 804 0.32\n",
      "cs 802 0.25\n",
      "af 587 0.303\n",
      "sr 587 0.209\n",
      "vi 452 0.266\n",
      "he 444 0.304\n",
      "no 409 0.343\n",
      "sk 400 0.302\n",
      "da 398 0.305\n",
      "hu 393 0.339\n",
      "sl 345 0.361\n",
      "zh 341 0.414\n",
      "mr 336 0.419\n",
      "uk 291 0.352\n",
      "el 268 0.427\n",
      "th 256 0.418\n",
      "hr 246 0.284\n",
      "fa 239 0.283\n",
      "ca 197 0.348\n",
      "et 170 0.476\n",
      "lv 152 0.381\n",
      "sq 142 0.432\n",
      "lt 129 0.452\n",
      "sw 117 0.522\n",
      "ms 108 0.401\n",
      "eu 107 0.589\n",
      "ku 104 0.682\n",
      "bg 92 0.32\n",
      "eo 88 0.692\n",
      "als 82 0.578\n",
      "cy 79 0.708\n",
      "la 66 0.627\n",
      "is 65 0.622\n",
      "arz 65 0.342\n",
      "km 55 0.992\n",
      "az 48 0.376\n",
      "bn 45 0.372\n",
      "ceb 44 0.572\n",
      "war 42 0.703\n",
      "nn 40 0.378\n",
      "bh 39 0.571\n",
      "su 37 0.628\n",
      "si 36 0.97\n",
      "ta 33 0.412\n",
      "yi 32 0.838\n",
      "gu 31 1.0\n",
      "gl 31 0.365\n",
      "ht 30 0.452\n",
      "mn 28 0.677\n",
      "sh 27 0.326\n",
      "am 26 0.516\n",
      "ur 25 0.842\n",
      "bs 24 0.49\n",
      "kk 19 0.591\n",
      "mg 19 0.7\n",
      "br 19 0.685\n",
      "ga 18 0.816\n",
      "ne 17 0.366\n",
      "nap 16 0.573\n",
      "lb 16 0.502\n",
      "hy 15 0.547\n",
      "mk 14 0.725\n",
      "io 12 0.66\n",
      "ast 12 0.44\n",
      "ml 11 1.0\n",
      "jv 11 0.448\n",
      "kw 11 0.519\n",
      "jbo 11 0.621\n",
      "lmo 10 0.595\n",
      "sa 10 0.588\n",
      "bo 9 1.0\n",
      "ia 9 0.724\n",
      "ky 9 0.526\n",
      "kn 8 0.778\n",
      "uz 8 0.962\n",
      "ka 7 0.618\n",
      "nds 7 0.448\n",
      "vec 7 0.585\n",
      "my 6 0.876\n",
      "mt 5 0.78\n",
      "qu 5 0.509\n",
      "eml 5 0.682\n",
      "pms 4 0.645\n",
      "fy 4 0.488\n",
      "be 4 0.461\n",
      "yo 4 0.686\n",
      "so 4 0.722\n",
      "ckb 4 0.68\n",
      "gn 4 0.638\n",
      "scn 4 0.71\n",
      "ilo 3 0.531\n",
      "sc 3 0.603\n",
      "new 3 0.448\n",
      "ie 3 0.563\n",
      "as 2 0.489\n",
      "gv 2 0.76\n",
      "an 2 0.76\n",
      "min 2 0.503\n",
      "lo 2 0.93\n",
      "tk 2 0.663\n",
      "oc 2 0.693\n",
      "rm 2 0.704\n"
     ]
    }
   ],
   "source": [
    "langs = [(k, len(v)) for k, v in lang_cers.items()]\n",
    "langs.sort(key=lambda x: (-x[1]))\n",
    "print(\"lang n_songs median cer\")\n",
    "cer_percentage_threshold = 0.5\n",
    "langs_cer_cut = {}\n",
    "for k, l_v in langs:\n",
    "    v = lang_cers[k]\n",
    "    if l_v > 1:\n",
    "        print(k, l_v, round(np.quantile(v, cer_percentage_threshold), 3))\n",
    "        langs_cer_cut[k] = round(np.quantile(v, cer_percentage_threshold), 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "768780a2",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-18T03:01:31.958520Z",
     "start_time": "2024-01-18T03:01:04.057834Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:47:52.754672Z",
     "iopub.status.busy": "2025-01-14T01:47:52.754529Z",
     "iopub.status.idle": "2025-01-14T01:48:24.789903Z",
     "shell.execute_reply": "2025-01-14T01:48:24.789336Z",
     "shell.execute_reply.started": "2025-01-14T01:47:52.754657Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 698626/698626 [00:09<00:00, 73616.55it/s]\n"
     ]
    }
   ],
   "source": [
    "rates = []\n",
    "cers = []\n",
    "# youtube_views_log = []\n",
    "for k in tqdm.tqdm(total_infos_2):\n",
    "    duration_s = metas_map[k][\"duration_s\"]\n",
    "    n_lyrics = len(metas_map[k][\"lyrics\"].split())\n",
    "    # print(n_lyrics / duration_s)\n",
    "    cers.append(total_infos_2[k])\n",
    "    rates.append(n_lyrics / duration_s)\n",
    "    # youtube_views_log.append(np.log10(metas_map[k][\"youtube_views\"]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ddca3db4",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-12T22:41:25.073971Z",
     "start_time": "2024-01-12T22:41:25.072066Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:48:24.790628Z",
     "iopub.status.busy": "2025-01-14T01:48:24.790474Z",
     "iopub.status.idle": "2025-01-14T01:48:24.792987Z",
     "shell.execute_reply": "2025-01-14T01:48:24.792598Z",
     "shell.execute_reply.started": "2025-01-14T01:48:24.790612Z"
    }
   },
   "outputs": [],
   "source": [
    "# plt.clf()\n",
    "# h = plt.hist2d(rates, youtube_views_log, bins=200)\n",
    "# plt.colorbar(h[3])\n",
    "# # plt.ylim(0, 4)\n",
    "# plt.xlim(0, 5)\n",
    "# plt.xlabel(\"n_words / sec\")\n",
    "# plt.ylabel(\"youtube_views, log10\")\n",
    "# plt.title(\"youtube views vs. num words per sec\")\n",
    "# plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "2e5eb800",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-12T22:41:25.152543Z",
     "start_time": "2024-01-12T22:41:25.074881Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:48:24.793569Z",
     "iopub.status.busy": "2025-01-14T01:48:24.793443Z",
     "iopub.status.idle": "2025-01-14T01:48:24.832093Z",
     "shell.execute_reply": "2025-01-14T01:48:24.831718Z",
     "shell.execute_reply.started": "2025-01-14T01:48:24.793556Z"
    }
   },
   "outputs": [],
   "source": [
    "# plt.hist([r for r, v in zip(rates, youtube_views_log) if v < 6], bins=100, density=True, label=\"views < 1m\", alpha=0.5)\n",
    "# plt.hist([r for r, v in zip(rates, youtube_views_log) if v >= 6], bins=100, density=True, label=\"views >= 1m\", alpha=0.5)\n",
    "# plt.legend()\n",
    "# plt.xlabel(\"word rate / sec\")\n",
    "# plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "b19130f2",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-12T22:41:25.212542Z",
     "start_time": "2024-01-12T22:41:25.153867Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:48:24.832726Z",
     "iopub.status.busy": "2025-01-14T01:48:24.832599Z",
     "iopub.status.idle": "2025-01-14T01:48:24.868630Z",
     "shell.execute_reply": "2025-01-14T01:48:24.868258Z",
     "shell.execute_reply.started": "2025-01-14T01:48:24.832713Z"
    }
   },
   "outputs": [],
   "source": [
    "# plt.clf()\n",
    "# h = plt.hist2d(cers, youtube_views_log, bins=100)\n",
    "# plt.colorbar(h[3])\n",
    "# # plt.ylim(0, 4)\n",
    "# # plt.xlim(0, 0.99)\n",
    "# plt.xlabel(\"cer\")\n",
    "# plt.ylabel(\"youtube_views\")\n",
    "# plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "416b615d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-18T03:01:32.652951Z",
     "start_time": "2024-01-18T03:01:31.959970Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:48:24.869209Z",
     "iopub.status.busy": "2025-01-14T01:48:24.869078Z",
     "iopub.status.idle": "2025-01-14T01:48:25.558515Z",
     "shell.execute_reply": "2025-01-14T01:48:25.558027Z",
     "shell.execute_reply.started": "2025-01-14T01:48:24.869196Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAG2CAYAAACtaYbcAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAACLTUlEQVR4nO2de3gU1f3/37O7ySbksiFIEtCAKFQuIigoBGy9oRGpheq3VaSAilopWCHWCxbFghrFWrwheEerlKoV7Q8pClikSrxxsQiINySg2aBisrlusrvz+4Oy5Hwm7Mlkk+yGvF/Ps8+Ts3POmc+cmd09mfOe98cwTdMEIYQQQkiMcMQ6AEIIIYR0bDgZIYQQQkhM4WSEEEIIITGFkxFCCCGExBRORgghhBASUzgZIYQQQkhM4WSEEEIIITGFkxFCCCGExBRORgghhBASUzgZIYQQQkhMiavJyD333APDMDBjxoyI9V566SX07dsXSUlJGDhwIFauXNk2ARJCCCGkxYmbyciHH36Ixx57DCeddFLEehs2bMD48eMxZcoUbN68GePGjcO4cePwySeftFGkhBBCCGlJjHhIlFdZWYlTTjkFjz76KO68804MHjwYDzzwQKN1L7nkElRVVWHFihXh94YPH47Bgwdj8eLFbRQxIYQQQloKV6wDAIBp06ZhzJgxGDVqFO68886IdYuKilBQUKC8l5+fj1dffbXR+n6/H36/P1wOhULYv38/unTpAsMwoo6dEELIkYtpmqioqED37t3hcLTeYkJtbS3q6uqi7icxMRFJSUktEFHbEvPJyLJly7Bp0yZ8+OGHTarv9XqRnZ2tvJednQ2v19to/cLCQvzpT3+KOk5CCCEdlz179uCYY45plb5ra2vRq2cqvPuCUfeVk5ODXbt2tbsJSUwnI3v27MH111+P1atXt9rAzZo1S7mTUl5ejh49euB0XAAXElpln4QQQo4MAqjHO1iJtLS0VttHXV0dvPuC2L3xWKSnNf/ui68ihJ5DvkZdXR0nI3bYuHEj9u3bh1NOOSX8XjAYxPr16/HII4/A7/fD6XQqbXJyclBaWqq8V1paipycnEb34Xa74Xa7Le+7kACXwckIIYSQCPxPVdkWy/qpaQZS05q/nxDar/Qgpk/TnHPOOdi6dSu2bNkSfg0dOhQTJkzAli1bLBMRAMjLy8PatWuV91avXo28vLy2CpsQQghpcYJmKOpXeyWmd0bS0tJw4oknKu+lpKSgS5cu4fcnTZqEo48+GoWFhQCA66+/HmeccQbuv/9+jBkzBsuWLcNHH32Exx9/vM3jJ4QQQlqKEEyE0PwHXKNpG2vixmfkcBQXF6OkpCRcHjFiBJYuXYrHH38cgwYNwssvv4xXX33VMqkhhBBCSPsgLnxG2hKfzwePx4MzMZaaEUIIIREJmPVYh9dQXl6O9PT0VtnHwd+lb3ceE7WAtfsJe1s11tYi5o/2EkIIIQQImiaCUdwfiKZtrIn7ZRpCCCGEHNnwzgghhBASB3RkASsnI4QQQkgcEIKJYAedjHCZhhBCCCExhXdGCCGEkDiAyzSEEEIIiSl8moYQQgghJEbwzgghhBASB4T+94qmfXuFkxFCCCEkDghG+TRNNG1jDScjhBBCSBwQNA+8omnfXqFmhBBCCCExhXdGCCGEkDiAmhFCCCGExJQQDARhRNW+vcJlGkIIIYTEFN4ZIYQQQuKAkHngFU379gonI4QQQkgcEIxymSaatrGGyzSEEEIIiSm8M0IIIYTEAR35zggnI4QQQkgcEDINhMwonqaJom2s4TINIYQQQmIK74wQQgghcQCXaQghhBASU4JwIBjFgkWwBWNpazgZIYQQQuIAM0rNiEnNCCGEEELaE8FgELfddht69eqF5ORkHH/88Zg3bx5M85B7mmmauP3229GtWzckJydj1KhR+Pzzz5V+9u/fjwkTJiA9PR0ZGRmYMmUKKisrbcXCyQghhBASBxzUjETzssO9996LRYsW4ZFHHsGOHTtw7733Yv78+Xj44YfDdebPn4+HHnoIixcvxvvvv4+UlBTk5+ejtrY2XGfChAnYtm0bVq9ejRUrVmD9+vW45pprbMXCZRpCCCEkDgiaDgTNKDQjNu3gN2zYgLFjx2LMmDEAgGOPPRZ/+9vf8MEHHwA4cFfkgQcewOzZszF27FgAwHPPPYfs7Gy8+uqruPTSS7Fjxw6sWrUKH374IYYOHQoAePjhh3HBBRfgz3/+M7p3796kWHhnhBBCCOmAjBgxAmvXrsVnn30GAPj444/xzjvvYPTo0QCAXbt2wev1YtSoUeE2Ho8Hw4YNQ1FREQCgqKgIGRkZ4YkIAIwaNQoOhwPvv/9+k2PhnRFCCCEkDgjBQCiKewQhHLg14vP5lPfdbjfcbrel/i233AKfz4e+ffvC6XQiGAzirrvuwoQJEwAAXq8XAJCdna20y87ODm/zer3IyspStrtcLmRmZobrNAXeGSGEEELigJbSjOTm5sLj8YRfhYWFje7vxRdfxAsvvIClS5di06ZNePbZZ/HnP/8Zzz77bFseNgDeGSGEEEKOKPbs2YP09PRwubG7IgBw44034pZbbsGll14KABg4cCB2796NwsJCTJ48GTk5OQCA0tJSdOvWLdyutLQUgwcPBgDk5ORg3759Sr+BQAD79+8Pt28KvDNCCCGExAEHBazRvAAgPT1deR1uMlJdXQ2HQ50GOJ1OhEIhAECvXr2Qk5ODtWvXhrf7fD68//77yMvLAwDk5eWhrKwMGzduDNd56623EAqFMGzYsCYfO++MEEIIIXHAAc1IFInybLa98MILcdddd6FHjx4YMGAANm/ejL/85S+48sorAQCGYWDGjBm488470adPH/Tq1Qu33XYbunfvjnHjxgEA+vXrh/PPPx9XX301Fi9ejPr6ekyfPh2XXnppk5+kATgZIYQQQjokDz/8MG677Tb87ne/w759+9C9e3f89re/xe233x6uc9NNN6GqqgrXXHMNysrKcPrpp2PVqlVISkoK13nhhRcwffp0nHPOOXA4HLj44ovx0EMP2YrFMBtarXUAfD4fPB4PzsRYuIyEWIdDCCEkjgmY9ViH11BeXq7oMFqSg79LL33cF53SnM3up7oiiF8N+rRVY20tYqoZWbRoEU466aTwulZeXh7+9a9/Hbb+kiVLYBiG8mo4OyOEEELaKy2lGWmPxHSZ5phjjsE999yDPn36wDRNPPvssxg7diw2b96MAQMGNNomPT0dO3fuDJcNo/0mBiKEEEIOEoKjRXxG2iMxnYxceOGFSvmuu+7CokWL8N577x12MmIYhq3HhQghhBAS38TNPZ1gMIhly5ahqqoq/MhQY1RWVqJnz57Izc3F2LFjsW3btoj9+v1++Hw+5UUIIYTEG0HTiPrVXon5ZGTr1q1ITU2F2+3Gtddei+XLl6N///6N1j3hhBPw9NNP47XXXsPzzz+PUCiEESNGYO/evYftv7CwUHGiy83Nba1DIYQQQppNEI6oX+2VmD9NU1dXh+LiYpSXl+Pll1/Gk08+ibfffvuwE5KG1NfXo1+/fhg/fjzmzZvXaB2/3w+/3x8u+3w+5Obm8mkaQgghWtryaZolmwdF/TTN5Sd/3C6fpom5z0hiYiJ69+4NABgyZAg+/PBDPPjgg3jssce0bRMSEnDyySfjiy++OGydwyUIIoQQQuKJkOlAKIonYkLt2Kkj7u7phEIh5U5GJILBILZu3ap45hNCCCHtkY68TBPTOyOzZs3C6NGj0aNHD1RUVGDp0qVYt24d3njjDQDApEmTcPTRR4czDs6dOxfDhw9H7969UVZWhvvuuw+7d+/GVVddFcvDIIQQQkgUxHQysm/fPkyaNAklJSXweDw46aST8MYbb+Dcc88FABQXFytJfH788UdcffXV8Hq96Ny5M4YMGYINGzY0SV9CCCGExDMhIKonYkItF0qbE3MBa1tDO3hCCCFNpS0FrIs2nYrk1ObfI6ipDGDqKR+2SwFr+11gIoQQQsgRQcyfpiGEEEIIos4vw9w0hBBCCImKEAyEEI1mpP06sHIyQgghhMQBHfnOSPuNnBBCCCFHBLwzQgghhMQB0RqX0fSMEEIIIVERMg2EovEZYdZeQgghhJDmwTsjhBBCSBwQinKZJtSO7y9wMkIIIYTEAdFn7W2/k5H2GzkhhBBCjgh4Z4QQQgiJA4IwEIzCuCyatrGGkxFCCCEkDuAyDSGEEEJIjOCdEUIIISQOCCK6pZZgy4XS5nAyQgghhMQBHXmZhpMRQgghJA5gojxCCCGEkBjBOyOEEEJIHGDCQCgKzYjJR3sJIYSQNsIQN/XNUGziaGG4TEMIIYSQDsWxxx4LwzAsr2nTpgEAamtrMW3aNHTp0gWpqam4+OKLUVpaqvRRXFyMMWPGoFOnTsjKysKNN96IQCBgOxbeGSGEEELigJBpIGQ2f6nFbtsPP/wQweChB4I/+eQTnHvuufjVr34FAJg5cyZef/11vPTSS/B4PJg+fTouuugivPvuuwCAYDCIMWPGICcnBxs2bEBJSQkmTZqEhIQE3H333bZi4WSEEEIIiQOCUWbttdu2a9euSvmee+7B8ccfjzPOOAPl5eV46qmnsHTpUpx99tkAgGeeeQb9+vXDe++9h+HDh+PNN9/E9u3bsWbNGmRnZ2Pw4MGYN28ebr75Ztxxxx1ITExscixcpmmPGA71FW19u9t1ryiPx3A6lVdr7sv2sRJC2h75OTRD6oso+Hw+5eX3+7Vt6urq8Pzzz+PKK6+EYRjYuHEj6uvrMWrUqHCdvn37okePHigqKgIAFBUVYeDAgcjOzg7Xyc/Ph8/nw7Zt22zFzG9XQgghJA44uEwTzQsAcnNz4fF4wq/CwkLtvl999VWUlZXh8ssvBwB4vV4kJiYiIyNDqZednQ2v1xuu03AicnD7wW124DINIYQQEgeE4EAoinsEB9vu2bMH6enp4ffdbre27VNPPYXRo0eje/fuzd5/NHAyQgghhBxBpKenK5MRHbt378aaNWvwyiuvhN/LyclBXV0dysrKlLsjpaWlyMnJCdf54IMPlL4OPm1zsE5T4TINIYQQEgcETSPqV3N45plnkJWVhTFjxoTfGzJkCBISErB27drwezt37kRxcTHy8vIAAHl5edi6dSv27dsXrrN69Wqkp6ejf//+tmLgnZE4wHAlqG8IQZbhdKqbgzI3oxMRsQgvRX3L/iIroM2QKbo3bG2XhOrFM+kiXkMenhKv5tg1mCG5L91YC3TmSy1tznSEmj2ROCCer614iqUVaetHewEgFArhmWeeweTJk+FyHZoSeDweTJkyBQUFBcjMzER6ejquu+465OXlYfjw4QCA8847D/3798fEiRMxf/58eL1ezJ49G9OmTWvS0lBDOBkhhBBC4gAzyqy9ZjParlmzBsXFxbjyyist2xYsWACHw4GLL74Yfr8f+fn5ePTRR8PbnU4nVqxYgalTpyIvLw8pKSmYPHky5s6dazsOW5OR+vp6JCcnY8uWLTjxxBNt74wQQggh8cN5550H0zQb3ZaUlISFCxdi4cKFh23fs2dPrFy5Muo4bE1GEhIS0KNHD8WxjRBCCCHRE4SBYBTJ7qJpG2tsL9P88Y9/xK233oq//vWvyMzMbI2Y2h9irdWRoA6r1FA4ksRamjOy7sGQ9UNi/dSlOY26+iKPgFlfL9prNCB1an2HWCsMVVer7cX+nZ06qf2JWbqMx3Ac/lakReMhYreuPQcjbpfnMlRXJ2KRH36hOZH7l+iM1GS8HWTtvD0Q9/oiu7T0/mJ9PNGgxO4ANB/jliJkNk/30bB9e8X2ZOSRRx7BF198ge7du6Nnz55ISUlRtm/atKnFgiOEEELIkY/tyci4ceNaIQxCCCGkYxOKUsAaTdtYY3syMmfOnBbb+aJFi7Bo0SJ8/fXXAIABAwbg9ttvx+jRow/b5qWXXsJtt92Gr7/+Gn369MG9996LCy64oMViIoQQQmJBCAZCUeg+omkba5o1jSorK8OTTz6JWbNmYf/+/QAOLM988803tvo55phjcM8992Djxo346KOPcPbZZ2Ps2LGHTbCzYcMGjB8/HlOmTMHmzZsxbtw4jBs3Dp988klzDoMQQgghcYBhHu6ZnsPw3//+F6NGjYLH48HXX3+NnTt34rjjjsPs2bNRXFyM5557LqqAMjMzcd9992HKlCmWbZdccgmqqqqwYsWK8HvDhw/H4MGDsXjx4ib17/P54PF4cCbGwmUk6Bs0ghSuGSJNshRoGqmqrgbJSUrRTFbbm6J9oLNa31kpBKN1qgA1lKwel+lU55zOSjWDYyhJ3Z+jWhVpSkEppO6uokp9Q+wPASHsM6QAVuxPEhQ7bNC/KcSzECJCi6gwQl+NYelfY0inQytotTaIrr2mvxanpUWaDevHWgAZ46zNFnNBeW1HG5+dc9GU+tESw3PvaPCdHjDr8VbdSygvL7dlsW6Hg79Ll711GRJTI5tORqKusg5Lz17aqrG2Frav3oKCAlx++eX4/PPPkZR06EfyggsuwPr165sdSDAYxLJly1BVVRW2mpUUFRUp6YyBA+mKD6YzJoQQQtorBzUj0bzaK7Y1Ix9++CEee+wxy/tHH3207ZTBALB161bk5eWhtrYWqampWL58+WE97Q+XrjjSfv1+P/z+Q3cCfD6f7RgJIYQQ0nrYnka53e5Gf9A/++wzdO3a1XYAJ5xwArZs2YL3338fU6dOxeTJk7F9+3bb/RyOwsJCeDye8Cs3N7fF+iaEEEJaihCMcH6aZr3asYDV9p2RX/ziF5g7dy5efPFFAIBhGCguLsbNN9+Miy++2HYAiYmJ6N27N4ADWQI//PBDPPjgg43efcnJyQmnJz5Iw3TGjTFr1iwUFBSEyz6fz/aExGJuJE3MpIZEmJSZR2Uo5WCaqgGp8ySIstqfQ8gWan6itk+sFCZhYoqZUCV0Dkepa5KuGrEem67G76pWNSmG0F04XHItWZik+UUiPLn2naZqaozqGrW+1Jw06N+Qehap4fD7I2+XZbkO75BJ/ITOSJqeadfxg2JzZB2A9doT58KujsCursDuWr2ufqx1H5HQjI0u4WO0eh7tudQlhdTpc2Jd3y4xvFYajr1ptp3juBnl0zRmO56M2L4zcv/996OyshJZWVmoqanBGWecgd69eyMtLQ133XVX1AGFQiFlWaUheXl5Sjpj4EC64sNpTIADd3LS09OVFyGEEBJvRHVXJMqMv7HG9p0Rj8eD1atX491338XHH3+MyspKnHLKKRZhaVOYNWsWRo8ejR49eqCiogJLly7FunXr8MYbbwAAJk2ahKOPPhqFhYUAgOuvvx5nnHEG7r//fowZMwbLli3DRx99hMcff9z2vgkhhBASH9iejDz33HO45JJLMHLkSIwcOTL8fl1dHZYtW4ZJkyY1ua99+/Zh0qRJKCkpgcfjwUknnYQ33ngD5557LgCguLgYjgZ5SEaMGIGlS5di9uzZuPXWW9GnTx+8+uqrzCBMCCGk3dORHVht+4w4nU6UlJQgKytLef+HH35AVlZW3Gf0bY7PiE4z4kxRE70Z0kck5yilHLVmpIt6wdnWjATV+hbNiLgitJoRjS+JVjMiEt/Z0YxAk9TPlEt+0uNEoxmxtheDa1MzYtGE2NSMhOqj1IzYJdYaj7b0mohzzUjUifkk8a4ZiSENxzpg1uPfwVfaxGdk7JtXIiGl+T4j9VV1eO28p9ulz4jtOyOmacKQX+gA9u7dC4/H0yJBxRvyQ+9wq5MJo1Oy2kCYnJmJIvNrovohrk9Vv2Tqk9XxDXaWP97q7mrFdkN8R/nT1f7l5CWUICYD4ks15FL7d8jJjPwSdaplZ5U6WXHUiAmEFMDKLzlh4oaqBlmAheGcnJwYaamIiMhobMkQLOvLjMLSsE3GLkzVLP2JsTPk5CUgDO5kRmj5g+XSTLA1PxBRZ57V1NeLNGVANn7Qov1x1BnaaY4FRuTJiDyX2ng1E9moxch2Dep0/emIxhCvjSc+DY0sDRNAzeHrkpahyZORk08+GYZhwDAMnHPOOXA1cAkNBoPYtWsXzj///FYJkhBCCDnS6ci5aZo8GTmYrXfLli3Iz89Hauqh/zgTExNx7LHHNuvRXkIIIYQg6idiOsTTNAez9R577LG49NJL4Xa7NS0IIYQQQvTYVredffbZ+O6778LlDz74ADNmzODjtYQQQkgU0GfEBpdddhmuueYaTJw4EV6vF6NGjcKJJ56IF154AV6vF7fffntrxBlTLEI2KcITmV2lwDeUKASqqeqwB91CsJqklutF0l/L9SZ1X6Lskg+niP6lyaizVhXiSYFtQqUqpLMIYGWS3ySZRVg41kphXqoQCNeL7Q1FnJanYzQZg+W+dA+TOTRPWEgBrcAMaYR18ukdIR7WPcmlxa7AVFzqlv3ZzexqCUf0Z0fU2NJusAKdYNWaQTm6p090T+dYaG33XJuCWtv7b0l33iivQ337huem7X7gO/Iyje07I5988glOO+00AMCLL76IgQMHYsOGDXjhhRewZMmSlo6PEEIIIUc4tu+M1NfXh/Uia9aswS9+8QsAQN++fVFSUtKy0RFCCCEdBN4ZscGAAQOwePFi/Oc//8Hq1avDj/N+++236NKlS4sHSAghhHQETBx6vLc5r+hs92KL7Tsj9957L375y1/ivvvuw+TJkzFo0CAAwD//+c/w8s2RhmUdX7eun6zqCAIpqmYi6BamZynqbNafoe4/IDQj0pFVToalRiQoHnySpmg1iWoHyfvV+Bz16vH6M9XLxlmvrr+GxFp4gk/oIoTJmUUTIkzVLPUbOtxKzYh0b3UJHYAwDYN0NBUaELOsHLYQ8ViuDalRkT5WUrcgu3dE1i1YTMVCkY2zZH8W0zRh1CUTmOo0LbZdQyUR1vajdiSNVlMikPvX6Xss2b/ltSnFVxbNikbPY/d4bZqeWa81zU+hXQM8OxqVKM34LDT8nNozKY+KjnxnxPZk5Mwzz8T3338Pn8+Hzp07h9+/5ppr0KlTpwgtCSGEEEKs2J6MAAfy0zSciAAH/EcIIYQQ0jx4Z8QmL7/8Ml588UUUFxejTuTm2LRpU4sERgghhHQkOvJkxLaA9aGHHsIVV1yB7OxsbN68Gaeddhq6dOmCr776CqNHj26NGAkhhBByBGP7zsijjz6Kxx9/HOPHj8eSJUtw00034bjjjsPtt9+O/fv3t0aMMcdiTiSNtaRIUgqeRPO6NPGG1EfJZKDClKw+VW3grBUma0KD6BCJZS2CVtG/3yMErd8JoZ0UtGaoO3T6hSiyk7o9obxWjVdsNxLU8XTUysy4h+IzpWDUpbmkpeC11q+WLedOnnvNuZYmZ6ZNQacuTX2dEKBKwa0U5Fr6s7iaRSzrRJs6rIJZzfFJI7EImVtbUgzbpPqGMO8T4l7rWGkEmaL/kDh3+nikYZ3uXNk00Is2i69WVGrPZK5l9x2ZWGXt5Z0RGxQXF2PEiBEAgOTkZFRUVAAAJk6ciL/97W8tGx0hhBDSQTBNI+pXe8X2ZCQnJyd8B6RHjx547733AAC7du2yPrZICCGEkLjlm2++wW9+8xt06dIFycnJGDhwID766KPwdtM0cfvtt6Nbt25ITk7GqFGj8Pnnnyt97N+/HxMmTEB6ejoyMjIwZcoUVFZW2oqjWYny/vnPfwIArrjiCsycORPnnnsuLrnkEvzyl7+02x0hhBBCEJ3h2cGXHX788UeMHDkSCQkJ+Ne//oXt27fj/vvvV56WnT9/Ph566CEsXrwY77//PlJSUpCfn4/a2kPL7RMmTMC2bduwevVqrFixAuvXr8c111xjKxbDtHk7IxQKIRQKwfW/tflly5Zhw4YN6NOnD377298iUZM4LNb4fD54PB6cibFwiTXgMJq1WEeSKrowPOlKOdhNdaKt7ZaslKuyVF1Dndoc/kwRjljurPeIdf169QJ0+oWOQsoShGlaok8tJ1RKkzfRXixtu2rU+q6qyGv5rhq5lq4WnTXqDqQuxFF3aLtRJ4IRhmmGNEGT6/IyEZ7UA8n2cp1d1JdJE3WJ+SyJ9ILi3CYKnYJfaFzk2rjUZOgS8WmMp3T1JTodgtboytqgYeeH39Z4MGp1jV5HbtcmztPsT4fUiOhMxKIde+142G0vDfJkdaGp0ZqeRdi/9tijMUw7sHOl6ExLC/8dMOuwtuIFlJeXIz09XbZsEQ7+Lg179fdwpbj1DQ5DoMqP98c91ORYb7nlFrz77rv4z3/+0+h20zTRvXt33HDDDfjDH/4AACgvL0d2djaWLFmCSy+9FDt27ED//v3x4YcfYujQoQCAVatW4YILLsDevXvRvXv3JsXepDN20UUXwec78Iv1/PPPI9jgxF966aV46KGHcN1118X9RIQQQgg50vH5fMrLL/+J+R///Oc/MXToUPzqV79CVlYWTj75ZDzxxBPh7bt27YLX68WoUaPC73k8HgwbNgxFRUUAgKKiImRkZIQnIgAwatQoOBwOvP/++02OuUmTkRUrVqCqqgrAgaWZ8nKbFtmEEEIIiUhLCVhzc3Ph8XjCr8LCwkb399VXX2HRokXo06cP3njjDUydOhW///3v8eyzzwIAvF4vACA7O1tpl52dHd7m9XqRlZWlbHe5XMjMzAzXaQpNerS3b9++mDVrFs466yyYpokXX3zxsLeAJk2a1OSdE0IIIeQALfVo7549e5TfaLe78aWfUCiEoUOH4u677wYAnHzyyfjkk0+wePFiTJ48udlxNIcmTUYWL16MgoICvP766zAMA7Nnz4Yh/RcAGIbByQghhBDSDKJ9PPdg2/T09CZpRrp164b+/fsr7/Xr1w//+Mc/ABx4ehYASktL0a1bt3Cd0tJSDB48OFxn3759Sh+BQAD79+8Pt28KTZqMjBgxIvwIr8PhwGeffWa5LXMkYzU9E8I2IWI0LMZXoj8hYgwmRTYtCyVGFpYFU0U2T5Hl1lkjBa5q+0CSWg4mCNOzH9T9h8RVI+OtTxWC30BkE7jEclXoFkgVJmiivaOmQf1g5LEx09TkjUaNMFALCEGrFKBqBKtScCoFo0qGYQCm2J8h2pumGp+lvjQ5k8K9kBTIRhZB6kSUdkWV0WZytW5uYHCnyVAs0WUsttTXiHctWXU17XVo+wtFNkHTipHl2EdrWmbXdE4jWNWhnvsWto3QGcg1ND2z6ZXXnhg5ciR27typvPfZZ5+hZ8+eAIBevXohJycHa9euDU8+fD4f3n//fUydOhUAkJeXh7KyMmzcuBFDhgwBALz11lsIhUIYNmxYk2Ox7cC6a9cudO3a1W4zQgghhETAjHKZxu5dlZkzZ2LEiBG4++678etf/xoffPABHn/8cTz++OMADqx2zJgxA3feeSf69OmDXr164bbbbkP37t0xbtw4AAfupJx//vm4+uqrsXjxYtTX12P69Om49NJLm/wkDdCMycjBGRMhhBBCWg4T1gwTdtvb4dRTT8Xy5csxa9YszJ07F7169cIDDzyACRMmhOvcdNNNqKqqwjXXXIOysjKcfvrpWLVqFZKSDt31feGFFzB9+nScc845cDgcuPjii/HQQw/ZiqVZWXsJIYQQ0v75+c9/jp///OeH3W4YBubOnYu5c+cetk5mZiaWLl0aVRycjBBCCCFxQAgGDJsuqrJ9e8XWZMQ0TezZswdZWVnKLZojDiFusgjZNJlhA6mqyDAkBKGmFBFKwapbCNOETiwojQ+lhtEt4pciQyHsc1Wp7aXDatAtBLC1anwBsd0tsvZa2gsBbX2qS2xX2zvqhYLM2UDY1kkY7QVE2x+EJ44QlCJBDGZAk0VX3kN1SddOtf9QpTq4hnDvtQhexSN4Zp0QtEpxtHyqTWoO5Rqyxl3YEKJKSxZgXWJY6dKpES3achW1fC4jZ2a1Oozac+XUCUwlth1NBXYzHFv2p8kirBe0Rhak6txz7R6/ne1RZXtuDI2Yt6Fw3DQ12ZRbkJZ6mqY9YuvTaZomevfujT179rRWPIQQQgjpYNiajDgcDvTp0wc//PBDa8VDCCGEdEgOmp5F82qv2M7ae8899+DGG2/EJ5980hrxEEIIIR0S04z+1V6xLWCdNGkSqqurMWjQICQmJiI5Wc1Iu3///hYLLl6xrJXKBIFifbM+RZ3z1aWK/sQ6fChRrHemyIyU4oqTF2CFyPTqilxfmpgFhaxBmv5IDYjM8isn5456dbu/s7rDhErNWrU0BpOZdhvWFYZvpidF3V4n9iU0GRYNidRoSJM0DY40cbJFfyaEyZqmf0McuzXrrzg+adAnERobi8mbDpuZai1r9Zr2qlYgctZdOwZqB3YtPxeRtWIyg7Llm9+SoTmyhqWRACNvF9jViFh0F1HGp9UPCexmIY7UVmLVszQ9rsY7bNhf+73b0J6wPRl54IEHWiEMQgghpGPTkQWsticjbZ08hxBCCOkIdOTJiG3NCAB8+eWXmD17NsaPHx9OkPOvf/0L27Zta9HgCCGEkI4CBaw2ePvttzFw4EC8//77eOWVV1BZWQkA+PjjjzFnzhxbfRUWFuLUU09FWloasrKyMG7cOEvSHsmSJUtgGIbyOqI9TwghhJAjHNvLNLfccgvuvPNOFBQUIC0tLfz+2WefjUceecRWX2+//TamTZuGU089FYFAALfeeivOO+88bN++HSkpKYdtl56erkxaDGn8FCU6IyiLMVSSFLYhYlkKVoNJokKqEDFWif0laER/UuAqhieQJozBaoUJWo2ITxye3B5IlqZmQugmwnHvV4/PdAkTOLeYI4usww2zEssMyUa1EPWJrL7yXMkMyqiXWXvFWEuBqxTTatrbzeyqFazK+jKrrxToymtbiq81RlYWkaddoaBGsBpJ5GjZ5pKfu8gCVIlV0BrZEM6SoVmHzljLbtZd2b08fssOxLUoBcC2M+FqTM5sXtu6/Tc0nTOD4jqWGYTtZii2BqOWGx5L1GpYG2FE+URMh3qaZuvWrY160GdlZeH777+31deqVauU8pIlS5CVlYWNGzfiZz/72WHbGYaBnJwcW/sihBBC4pkDk5FoNCMtGEwbY3uZJiMjAyUlJZb3N2/ejKOPPjqqYMrLD1h3Z2ZmRqxXWVmJnj17Ijc3F2PHjo2oVfH7/fD5fMqLEEIIIfGD7cnIpZdeiptvvhlerxeGYSAUCuHdd9/FH/7wB0yaNKnZgYRCIcyYMQMjR47EiSeeeNh6J5xwAp5++mm89tpreP755xEKhTBixAjs3bu30fqFhYXweDzhV25ubrNjJIQQQlqLg0/TRPNqrximae/GTl1dHaZNm4YlS5YgGAzC5XIhGAzisssuw5IlS+DUGecchqlTp+Jf//oX3nnnHRxzzDFNbldfX49+/fph/PjxmDdvnmW73++H338oM5vP50Nubi7OxFi4jMOsuYr1RodIbmbRlGQdpZRreqvl6mx1P1U56gXj76LuPpCqrlGaSZq1arlcGrBkS1PL9er2xDK1nFCpVneIxHbyck/+PvIl5KrW6BxE84QKsTYtdB+uCrF+HAFHncz6J/qWpl9+sc6u1ZBIxzixvVYMntQFyER0Uo9kaS/OrcbkzKIZ0RmFaeKTWHQV0shK7E9nNGbdQYP4ZF2pG7CZaE6LxqDNotnQnVub8WhN3aI1nLPsUGP6ZlfTEqWmJKp92x1r0Z+zsyf8dyBUh7U/Povy8nKkp6fb6rep+Hw+eDweHP/XWXB2av4DGcHqWnw5sbBVY20tbGtGEhMT8cQTT+C2227DJ598gsrKSpx88sno06dPs4OYPn06VqxYgfXr19uaiABAQkICTj75ZHzxxReNbne73XCLTKiEEEIIiR9sT0YO0qNHD/To0SOqnZumieuuuw7Lly/HunXr0KtXL9t9BINBbN26FRdccEFUsRBCCCGxpCObntmejASDQSxZsgRr167Fvn37EBK3rd96660m9zVt2jQsXboUr732GtLS0uD1egEAHo8nnPNm0qRJOProo1FYWAgAmDt3LoYPH47evXujrKwM9913H3bv3o2rrrrK7qEQQggh8YMJqzWE3fbtFNuTkeuvvx5LlizBmDFjcOKJJ0bl8bFo0SIAwJlnnqm8/8wzz+Dyyy8HABQXF8PRYJ38xx9/xNVXXw2v14vOnTtjyJAh2LBhA/r379/sOAghhJCYE60ItSPdGVm2bBlefPHFFlkWaYp2dt26dUp5wYIFWLBgQdT7toUUcqV3UrcLUaHMcitNzkyhe3MKjWKwkxBriXAMpxBbuVVhWFAIVE2/ENwKU7VQtRpQMFHdv6ta7F/o0GTWX0mgkxqPs1YYkYn6wSRZXx3QUPLhd+j6UQ3WTBSGdfWRRXSmOLfGdz+qFSwmZ5osvjLTa13kLL0hITi1CETF5N8i2hS712VyhVNcKzI+KdrUmKRBJq7ViTB1xmAN2mtFiRZBZ2QxvRwLhxQjS6G6S4iL5Vi1sOmXpb5GoBtNVtzmoNu/3Xgj9W97rHT1NRmLjQY6QyPUfn/g2xPNErD27t27NWIhhBBCOiwd2YHVts/IDTfcgAcffLBJdzUIIYQQ0jQ6ss9Ik+6MXHTRRUr5rbfewr/+9S8MGDAACSJXxyuvvNJy0RFCCCHkiKdJkxGPx6OUf/nLX7ZKMHGLzlxIPFEUShCJ32QiOLGUXZchzIZSpVlS5MR3nnRVJ/HjfjXJoCES4RlVYn00qHYYkDkKxf7cQkZRLzQuUgMjVSFO0Z+jXqx1B3TrvQ22Cw1FKEUY1NVLAzlxydeKsa6JnFgObqGZkKZkUoNRWaX2LzxvLP/HSN2BXPeXRlrJwiBJmK6Z0rRN9ifucBpS4yI0LVI/pdMpSGMwM6DGY2kv1+4b6gakBsEVObGdVkOhMflyJIr+5FhIZOxSQBMllviF3sZwaJIQ6jQclvHVJeITugtNfNr6NtAmcNQatmkWBRqORajtEuXBNKIToR7pd0aeeeaZ1o6DEEII6dBQM0IIIYQQEiNsP01z8sknN+otYhgGkpKS0Lt3b1x++eU466yzWiRAQgghpEPQgU3PbN8ZOf/88/HVV18hJSUFZ511Fs466yykpqbiyy+/xKmnnoqSkhKMGjUKr732WmvESwghhByR8GkaG3z//fe44YYbcNtttynv33nnndi9ezfefPNNzJkzB/PmzcPYsWNbLNCYIsVSohzySBM09YKwCDTFBWMERP39QjjWvVatL4Rq+79PU8qJnVQRZp0UEaYIUac4HmeVyFosdHsO6YsltWTiqkrwqccfdEvBq3o80vTMVabuMBjB9MxZJQSoYhHVUSMElNJELFkVqBpVwvFNLsrKLL6iLAWrcrtpMRWTgk85+EIgWyOuDWHMZRGoSuMuKZiV+7MrQtTVF6ZphszqG8E4TCdatGy3KyCVIkiZ8ViToViX4dgu2qy3mizGcrvF1E1g17TMKqAVYnJdxmcbAlYZu4zNEqvO7E9g2d5QCC4/46RVsH1n5MUXX8T48eMt71966aV48cUXAQDjx4/Hzp07o4+OEEII6UiYUbzaMbYnI0lJSdiwYYPl/Q0bNiAp6cBjhqFQKPw3IYQQQvR05GUa25OR6667Dtdeey2uv/56PP/883j++edx/fXXY+rUqfj9738PAHjjjTcwePDglo6VEEIIOXKJ5q5IM+6O3HHHHTAMQ3n17ds3vL22thbTpk1Dly5dkJqaiosvvhilpaVKH8XFxRgzZgw6deqErKws3HjjjQjoPHkawbZmZPbs2ejVqxceeeQR/PWvfwUAnHDCCXjiiSdw2WWXAQCuvfZaTJ061XYwhBBCCGk7BgwYgDVr1oTLrga6spkzZ+L111/HSy+9BI/Hg+nTp+Oiiy7Cu+++CwAIBoMYM2YMcnJysGHDBpSUlGDSpElISEjA3XffbSsO25MRAJgwYQImTJhw2O3JycnN6TZusLhIykyljTza3BB5pywgHEqDQtNouoRwLFMVzqWn1ihlp3BkrRTler84rZ2E8K1C3e6sFllyhW7PIbMKS9NPobfttE+NJ5AsnS/VYn2qKjZz/xgQ29V4EyoPbQ8JF05TlEOJkbPeGnViBi8FqkniZMkZv3RA1WVylVl/pXBOXlu6zKby2pTbNYJWS1mTJdiiCdWIOC2iUt3x6ESbEbArmNQ6jMr2YqzNmprD1DxYQSewFdWlKFO6hGoyHOuconUZlKPJqttYfZ3gWIfSnyE/J0JkL91yo81w3FBIbjNjcHQYaMSX2WZ7e7hcLuTk5FjeLy8vx1NPPYWlS5fi7LPPBnDAALVfv3547733MHz4cLz55pvYvn071qxZg+zsbAwePBjz5s3DzTffjDvuuAOJmu+nhtD0jBBCCIkHWmiZxufzKS+/35KjI8znn3+O7t2747jjjsOECRNQXFwMANi4cSPq6+sxatSocN2+ffuiR48eKCoqAgAUFRVh4MCByM7ODtfJz8+Hz+fDtm3bbB16kyYjmZmZ+P777wEAnTt3RmZm5mFfhBBCCIkdubm58Hg84VdhYWGj9YYNG4YlS5Zg1apVWLRoEXbt2oWf/vSnqKiogNfrRWJiIjIyMpQ22dnZ8Hq9AACv16tMRA5uP7jNDk1aplmwYAHS0g54WTzwwAO2dkAIIYSQJtBCDqx79uxBenp6+G239Dv6H6NHjw7/fdJJJ2HYsGHo2bMnXnzxxTaXWzRpMjJ58uRG/z5SsZj/CPMjI6Ce2FCSuvYcSBa6BTHKMqttXYIw5pLro4LKGnX/Se76w9T8X//VanyGWLoNeNT11cQ96vprfbpShEtNRIuESrUssxZL3GWR145l+4QKadJ2aLujXhg71UbWDZhCsyFTG1g0JFLj4YhsgAdTCG6k5kJqUKqF7iCgydob1KzjS1MzeXvWkllWxbrWLjQ5cofSVE1nDCY/S7pMuw2264ytLIIWoSuwtpfVxWjIsZQZkMV2hxirkMzoLNBpLOxrNiJrQCz7tzme2vh0Jmw2UeLX6WHEsdsdOwsNjzXK47BFC2XtTU9PVyYjTSUjIwM/+clP8MUXX+Dcc89FXV0dysrKlLsjpaWlYY1JTk4OPvjgA6WPg0/bNKZDiUSzRjkUCuGzzz7DO++8g/Xr1ysvQgghhLQ/Kisr8eWXX6Jbt24YMmQIEhISsHbt2vD2nTt3ori4GHl5eQCAvLw8bN26Ffv27QvXWb16NdLT09G/f39b+7b9NM17772Hyy67DLt374Yp/ysyDARtqN8JIYQQcgDTtD7gZre9Hf7whz/gwgsvRM+ePfHtt99izpw5cDqdGD9+PDweD6ZMmYKCggJkZmYiPT0d1113HfLy8jB8+HAAwHnnnYf+/ftj4sSJmD9/PrxeL2bPno1p06YddmnocNiejFx77bUYOnQoXn/9dXTr1q3RDL6EEEIIsUkbZ+3du3cvxo8fjx9++AFdu3bF6aefjvfeew9du3YFcEAv6nA4cPHFF8Pv9yM/Px+PPvpouL3T6cSKFSswdepU5OXlISUlBZMnT8bcuXNth257MvL555/j5ZdfRu/evW3vjBBCCCHxwbJlyyJuT0pKwsKFC7Fw4cLD1unZsydWrlwZdSy2JyPDhg3DF198cURNRnRmRJbt0khK3B2SWXqliVidRxprqUtbwVq1/3K/mpW3S065UpaCVkOYoMEvhGdpQqRZq24PCBG1S2gsZRZfC5rZuUOIMKVey1mrMUeKsLm+sxq80yJo1ZiMSSymYNK0TASTIIy0pEmayAJsMSWT/QeEcZZGoCqH3pTx6USLMouxLmOpLtMrhGBWGodJk7RI5lRSkKoTgOqWjGWWXikAledeXiumRuiuiUcnorSMhSVTraVBxP6iRZrK6b43daJTrQlcw/Nr09BNK97ViW8bfq5C4gu8NWkhAWt7pEmTkf/+97/hv6+77jrccMMN8Hq9GDhwIBLEl+9JJ53UshESQgghHQDDtJrN2m3fXmnSZGTw4MEwDEMRrF555ZXhvw9uo4CVEEIIaSZtrBmJJ5o0Gdm1a1drx0EIIYSQDkqTJiM9e/Zs7Thiitb8R5bd6rq3EVTXG4NJ6rpdfYraXJqOyXW+xDR1jdLhVBuUlasduhJFYjmRKM8UGhKjWj0eR71IlCcT48kntET8UkMil2MTqtQ3Qk6xFi6GN5gkkmDJtfIIOg9HvebOnFxWl5oI2bdLBCeNrKRGRCJ1B9JELUl8BIXGxNAYd0n9kpEQ2ajLklhPXvvyeOT46I5HIjQwpkgkqNVNRDA9k9g1urLqZRwRt2s1KFL/o9m/JYmi3J/UaGgS++kS4VnikcnlxP7sanIc4tqzaEw0Ghg7WA3YNGaHusR4kN/xDb707OX3iw5qRgghhBASUzrwMg2z9hJCCCEkpvDOCCGEEBIPdOA7I5yMEEIIIfEAJyPN43e/+x3mzp2Lo446qqXiiQsswjYp4hMiw6BbmIYJAas0EZMiI2ey2p9TCFYdDrXcPesHpfzNjxlKOSVFFVn6qlThmyNDFciaP6gK1XrVYw2uKiE8E1eNQyQzlQJdmbU46BaC3Uq1QShBXT0MJkoTuUP1pWDVFILJoCi7ymrV7WlJStlRJ0R5lWp9s5N6Mg2ZdVcixM4QAk7ITLDyWpOiSym0S1TPrVmjxqs1lpIiQlnWiEKtHUrBq4hfxqsRtEYUOVpMy0T2a2mwFoic3drSn0bYLgWf8pdAK4yXAlONyFJn7GURZWqOx7J/UV8KUq3YM3WTAlydgLVhe4vhm83r0jL2ugzDDa9TnfEfaRGi0ow8//zz8Pl8LRULIYQQ0nE5+DRNNK92SlR3RmTWXkIIIYQ0j47swMqnaQghhBASU6KajFRUVOC4445rdvvCwkKceuqpSEtLQ1ZWFsaNG4edO3dq27300kvo27cvkpKSMHDgwBbJGEgIIYTEFLMFXu2UqJZpxowZgyeffBLdunVrVvu3334b06ZNw6mnnopAIIBbb70V5513HrZv346UlJRG22zYsAHjx49HYWEhfv7zn2Pp0qUYN24cNm3ahBNPPLF5B2IzGyiSVdGjIeoHE4RwS1wgoQThSFor3QTV+kdlVirlUp+qMDVD6v5q/apQLNGjClrry1TBqpms7jChQr0snBqNpt+jlt1lajnkUuNz1arHX99J3e72CeGdaI8G+tv6NPVYXVWqqDAkXCYNIUZzVgiBqi4TqSRJ2NMKAakFKWiViMyvFsdT6Qirc7HUOKQabnEtyP07pShS922nGT/pMKtxYI2I+Nw6EjSCT10WXY07rcX5VwpMLYJWlagzy2q2WxxRxfEYuiS7UrusOR45nlZXVBGfFBBLx9tIGZsl4ktSnyE5sthZboe/weegLbP2dmCimoysX78eNTWaX6oIrFq1SikvWbIEWVlZ2LhxI372s5812ubBBx/E+eefjxtvvBEAMG/ePKxevRqPPPIIFi9e3OxYCCGEkFhiIErNSItF0vbElWakvLwcAJCZmXnYOkVFRRg1apTyXn5+PoqKihqt7/f74fP5lBchhBBC4oeoJiM9e/ZEgi5RWBMJhUKYMWMGRo4cGXG5xev1Ijs7W3kvOzsbXq+30fqFhYXweDzhV25ubovESwghhLQofLS3eXzyySctFQemTZuGTz75BO+8806L9QkAs2bNQkFBQbjs8/m0ExLtWqhYh6/OUTUkkkAn8YZTvQ+XllmtlINSA1Kvnqa6OrXcKVld0zTEfb4yb3rE/Rs14nhlFl4hi3CIJVR3uei+LnKWXqk7cNWo5YDI2uuqUtd/A8nOw26TpmcJFWqw0uRMxuLwi4MPyKy2MvOqWGsWGgyLxkJnoCQzv+qyBgsMoWeymKzJdXlpkiY1JlJDYzGf0mT1lVgMBUV9qQWIpKvQmHZZTdFEfZ3pmNSQGBpNijB0k/oYXRZdnQ7CcnwCwylM3qSeSPYvNSWWDu2dG20WXo1GxEKk49VlJNboT7T7bvg5CrbhDzwdWGPL9OnTsWLFCqxfvx7HHHNMxLo5OTkoLS1V3istLUVOTk6j9d1uN9zyB4IQQgghcUNMNSOmaWL69OlYvnw53nrrLfTq1UvbJi8vD2vXrlXeW716NfLy8lorTEIIIaT14aO9sWHatGlYunQpXnvtNaSlpYV1Hx6PB8nJB3KATJo0CUcffTQKCwsBANdffz3OOOMM3H///RgzZgyWLVuGjz76CI8//njMjoMQQgiJFjqwxohFixahvLwcZ555Jrp16xZ+/f3vfw/XKS4uRklJSbg8YsQILF26FI8//jgGDRqEl19+Ga+++mrzPUYIIYQQElNiemekKblt1q1bZ3nvV7/6FX71q1+1YCBCKCVEkFJEaCYJU7B6YeIl/dqkhjFNFXpVVamaFqdLjcflFFl2hWLaLwSucntq1yqlXPO1ELTKRLFSdyfKQaGRDApBqxSsuoQVTV2qEJkKo7K6NCF0E8JDZ+3hhW3SgE5mAHZWR87cGnKrY2mkCIO7GnEuRGZTaaqGoOYal1l7pYBUCjwtxluR/5+QJmY6UaZFgCq36zJaa4zEdKJKizCxodBQ11YKz3UCV4lOkCnHQoqXdcci0dXXZCW2iDSFqZjMkmsxpLNcW1JgKrP+yvAim0Nqz7Um62/DeOwKUkP1kWPTjn1DYXcosmi8RaGAlRBCCCExpQNPRuLK9IwQQgghHQ/eGSGEEELigI4sYOVkBGhkrVSuW6vlULJYdxfr7IkV6ubq7uIK8av9JXVW1/VdTnU9s7pG3d9Puu1Typ+VZKnx1av915li7ThBJIurFccnqssEWy41b58FU9R3CN2EIWQS9alqg4RqkWBLLtW7D39DL6FSJMpzCx2B1HDIZXOhAzDq1P7MJHVwjFpxMH6xvixNyKQmQybaC8h1dk19mZhP1LdoRCRC8yJ1EKY8Hp3GxJIsLbLRVqhKNfyzmso1GA+NAZs2aaAO2V4Y0Fl0B+J7wXKscrsm8ZxOI6IzcbNrkmZJEKpJZKfTwFh0HPLa0yT2s8Qfqa4mqaHtBIxyrNIaCP+CbfgzGa2Lajt2YLW9TPP73/8eDz30kOX9Rx55BDNmzGiJmAghhJCORwf2GbE9GfnHP/6BkSNHWt4fMWIEXn755RYJihBCCCEdB9v3n3744Qd4PB7L++np6fj+++9bJChCCCGko9GRNSO274z07t0bq1atsrz/r3/9C8cdd1yLBEUIIYR0OGK8THPPPffAMAxFclFbW4tp06ahS5cuSE1NxcUXX2zJD1dcXIwxY8agU6dOyMrKwo033oiATBSpwfadkYKCAkyfPh3fffcdzj77bADA2rVrcf/99+OBBx6w211cYDXUiZw906iLLJSr6arZodBKJSao/VVUqqLHnEyfUt69v7NSTktVRYx19Wq81eXJStkQWSiNgDAMEgLWkEsI00R9pyVrr1oOJKn13T6Z1Ve0l5l0paazQXehBHks6uDK2bYpDNmcNeoHJthJPXiHy+Z8PUEMnl+IAmUWXktWXc3+pAhSZvkVJmqmzS8EQ/YnTc1kfDpBq2hviqzDDiHI1Yo8GyLFsqKtbRGj/JxrhOymGGuLYFVmOJYiSykeFkjhuDVjcpS/PDqBq00s36PyXNo1hYtQ1/a5tinmVT6XochGiUcKH374IR577DGcdNJJyvszZ87E66+/jpdeegkejwfTp0/HRRddhHfffRcAEAwGMWbMGOTk5GDDhg0oKSnBpEmTkJCQgLvvvrvJ+7c9Gbnyyivh9/tx1113Yd68eQCAY489FosWLcKkSZPsdkcIIYQQAIhymaa5d0YqKysxYcIEPPHEE7jzzjvD75eXl+Opp57C0qVLwzcfnnnmGfTr1w/vvfcehg8fjjfffBPbt2/HmjVrkJ2djcGDB2PevHm4+eabcccddyBR90Tf/2iW6dnUqVOxd+9elJaWwufz4auvvuJEhBBCCImGFlqm8fl8yssvH9EXTJs2DWPGjMGoUaOU9zdu3Ij6+nrl/b59+6JHjx4oKioCABQVFWHgwIHIzs4O18nPz4fP58O2bduafOjNmowEAgGsWbMGr7zySji/zLfffovKSo0BBSGEEEJaldzcXHg8nvDrYNb7xli2bBk2bdrUaB2v14vExERkZGQo72dnZ8Pr9YbrNJyIHNx+cFtTsb1Ms3v3bpx//vkoLi6G3+/Hueeei7S0NNx7773w+/1YvHix3S7jDkdKJ/WNRFUHYCaqi7n+DLUckn48aZHXK50iIZXUiFTUquvqdXWRE+OFTLl2K+acbhFPrVo/KHy1HHXqdof0RhK3Bi3tRf2A8AFz1agdBN1i/devbm+YmNDhV48lKJMY+iPre4x6dbvDL8YuQSYXE+3lOrm4Viz6Irm2LepbTM+k5kNul/0JkzXLSrrQhJjVahZDS7IyqZuQSSSl5kVg0V9JjUiNyKJoMb46VNbpBCwaDJ0JWgSTrcbrC5OxoL3/5Rzi3FjGWp5rqd+RmhbY05BYTMXkudQYh+n612pYbJqmNdR5WJLwaQzULEaWsr00eIuYdNHmdRINLZSbZs+ePUhPP5QQ1e12N1p9z549uP7667F69WokJSU1WqetsH1n5Prrr8fQoUPx448/Ijn5kDDyl7/8JdauXduiwRFCCCEdhYOP9kbzAg5YbTR8HW4ysnHjRuzbtw+nnHIKXC4XXC4X3n77bTz00ENwuVzIzs5GXV0dysrKlHalpaXIyckBAOTk5FierjlYPlinKdiejPznP//B7NmzLaKUY489Ft98843d7gghhBASA8455xxs3boVW7ZsCb+GDh2KCRMmhP9OSEhQbjTs3LkTxcXFyMvLAwDk5eVh69at2LfvUJqS1atXIz09Hf37929yLLaXaUKhEIKN3P7cu3cv0tLS7HZHCCGEkBiQlpaGE088UXkvJSUFXbp0Cb8/ZcoUFBQUIDMzE+np6bjuuuuQl5eH4cOHAwDOO+889O/fHxMnTsT8+fPh9Xoxe/ZsTJs27bB3ZBrD9p2R8847T/ETMQwDlZWVmDNnDi644AK73RFCCCEEiLnpWWMsWLAAP//5z3HxxRfjZz/7GXJycvDKK6+EtzudTqxYsQJOpxN5eXn4zW9+g0mTJmHu3Lm29mP7zsj999+P/Px89O/fH7W1tbjsssvw+eef46ijjsLf/vY3u93FJdKYyUhJUcqhBJHlVmocxai6ytUKgc6qUK2uXm2QnKCKqxwO9Qrr3kV1GasPqv3v25+OiCQJI6pKtb1TiDhdamJVywVvFaSqZWedMDGTPl9CtyfHzxDasmBDozNTPRcOIUi1mJxVikfcpEmXwJLlVxpPJYrMrvUagakU6YksuRZTNCkylIMlTcf8quOcxWhL1DeEWNusFVmA5fHL+KUgtk443onxlUZhlsy4ETLhagWqMjYpmLRrgiawfC9osvLKeK0ZkIXIUix9a/sT8UlBq+X4pUiztTO8mpHNI3VZgyNl8ZXIuiGdeZ5G4KpcK22YCTce7ODXrVunlJOSkrBw4UIsXLjwsG169uyJlStXRrVf25ORY445Bh9//DH+/ve/4+OPP0ZlZSWmTJmCCRMmKIJWQgghhJCmYHsyAgAulwsTJkzAhAkTWjoeQgghpOPSjpPdRYNtzcizzz6L119/PVy+6aabkJGRgREjRmD37t0tGhwhhBDSYYhDzUhbYXsycvfdd4eXY4qKivDII49g/vz5OOqoozBz5swWD5AQQgghRza2l2n27NmD3r17AwBeffVV/N///R+uueYajBw5EmeeeWZLx9cmSDc/KSRDkloOJKtiJ+kYKrPe1ndRhVnZR5cp5ZREVdhWF1RPS5JLFWNV1anx1PjFDgWWLL3lav+uSnW7v4sqPEuoECJRqZOTmk1Lll3h4CpEkaZGoxlyqe0Tqg7twFWlVjaFuFhqz0LJ4twKgWV9mjqWSXuE6FBm8Q1Edtc1XdK1U/zrIkWVUtAqkSJOIaqUWYMt0juZRbdKVSdbsva6pMhQnhyNSFEKWGV9i8OraN9QiCjFvDqBoxS4SkcCi6BSOI5K8a9FYKpxn9W4gspzLwWrlvY6tP2L7zmN2tFy/Jrx1tW3jodGcBxpmymyU8uubbrrSvGs6T70OTJ1n8kWJB4ErLHC9p2R1NRU/PDDDwCAN998E+eeey6AA4rbGmntTAghhJCm0YGXaWzfGTn33HNx1VVX4eSTT8Znn30W9hbZtm0bjj322JaOjxBCCCFHOLbvjCxcuBB5eXn47rvv8I9//ANdunQBcMDjfvz48S0eICGEENIRaKncNO0R23dGMjIy8Mgjj1je/9Of/tQiAcUCmZ1Srk2HOqlrxcEksV3IEOQFkZiuGkHVCZOynknqun1Zneoi5vWpJmapSUInIBx3/VJDkiyNutTjDUiTsyqpc1C7qxeu/06LyZlaNsX4hMRSe326ur+UUhGv1H00MD0LJUZeG5YmXyFx7IbQfDjrpAmZGlswRR1sZ6UwCRNZgg2dYZJD6hbE/qV5k9Sc6NbGpambNBmL3NqiY7Bs1+kKZBZj2Z80DpMamAafTYvJmEZTYdGCaUzPtPoVWV/oc6RYyqo5Edm/pf7G0r8wOdOZoFmyGktDOXH8OlMyu5ocgV3NiaV9g/NnOCLHqs1YrMlAbImtobYp1HaakZbK2tsesX1nhBBCCCGkJWmW6RkhhBBCWpgOfGeEkxFCCCEkDuCjvU2gulpmSyOEEEJIi8FHe/UcddRROPvss/GLX/wCv/jFL5CTk9OacbU+hiNspGO4IpuGmVLYJgWVYhTrjlKFZJ1cqpCrrl4VS31fq2ZOrRdpgLPSKpSyr1YVuKYkqorRamHOVPOjKrp01Akxlzj8xB/UckBNWowENRyLSZnEkoVX6N7c5apArD5FHe9E3+GFcoFOom6Zqo6VAldHfWQxmjQlk1l4HXXqwYaEIZ6zRmTNFdeWmaQOhkMKNqXpmDR7kv8UJAn1suxPZvWVWYc1IkOt0ZU0/pKmbDojr0BkUaa6L82FJkSKETOxNoYcKylclN8DmrG0ZBHWZIjWxWcRoMpzp8sQbVOQahlvmfVXXpu6LME2iSQ41hnK6cTK1tjsiWtJy9PkOyOffvop8vPz8eKLL+LYY4/FsGHDcNddd2Hr1q2tGR8hhBDSMejAd0aaPBnp0aMHrrvuOqxZswalpaWYMWMGtm7dip/+9Kc47rjjMGPGDLz11lsI2rUwJoQQQkiH9hlp1qO9Ho8H48ePx7Jly/Ddd9/hscceQzAYxBVXXIGuXbvihRdeaOk4CSGEEHKEEvXTNAkJCTj33HNx7rnn4uGHH8bmzZsR0Jj5HGT9+vW47777sHHjRpSUlGD58uUYN27cYeuvW7cOZ511luX9kpIS2xoWw2FYDLHCiHV7mXytLk0t+zPU5o5k9fjTktV1/BM671PK3hrVRezYtP3q/oTooqRcNUHz1agaEqcwCEInuRYszJDkUre4KpxShiBOr/TpcvqF7iKgjnN9qjBZEzKIhGqRXM0p6x9+LTogEt0J+Q3c+4VGQXRlyjxviWIwhKbEIa51UxhbQcQuNSgWZFIuufYtjbZkfXlNS52A1BnIa11qOCIlL0Mjxl8aUzOLcVm9THgmtQANTM+kPkYm/atT+7KYgtUJNz6pz5FIjcfhvi8Ot90pjbbEuZKaDk3iPGmaJvU2Fv2PTOqoMQbTJaOzJBDVJQI0bRqN2dCY6EzPLCZoGr2LHDuzgRYs1IaJ8vhobwty8sknN7luVVUVBg0ahCuvvBIXXXRRk9vt3LkT6emHfpCzsrJsxUgIIYTEGx350d6Y+oyMHj0ao0ePtt0uKysLGRkZLR8QIYQQQtqcdmkHP3jwYHTr1g3nnnsu3n333Yh1/X4/fD6f8iKEEELiDj5N0z7o1q0bFi9ejH/84x/4xz/+gdzcXJx55pnYtGnTYdsUFhbC4/GEX7m5uW0YMSGEENJEOvBkxPYyTU1NDUzTRKdOB4y6du/ejeXLl6N///4477zzWjzAhpxwwgk44YQTwuURI0bgyy+/xIIFC/DXv/610TazZs1CQUFBuOzz+ZCbmwszZML83wKbxSBHCLVCQsBanyLqy2SYASGOEhfIvtpUpdy9k3q3JiNBTYPbWSg8yzKTlbK3ShXAVlSrglZ5hZoJOiGbEJwK0zOnEJxKAazfIwSnIrGtQ+gIpWA2KHRyCVVqvLVdDjWQglSHX2T3lJo6KRIUIsNQotrAVSaNo0R7sQNpigZpshYQgyXFcdJ7yZBqYnFAfjGYKaqBHmrE4EvRprg4DZuiTcMhTN3k/mS8UsQoRZERxO8WgzW7wkJp6CZNzCRyrCzZvUV/cqw0Yl2LIFWKfaVIUwpGbRrUaQWsOlMzzf6lQNi2gV6E+OSxO8R1I7P6WturZaspmhpbqIH412xf/7O3W2yP8tixY/Hcc88BAMrKyjBs2DDcf//9GDt2LBYtWtTiAeo47bTT8MUXXxx2u9vtRnp6uvIihBBC4g2jBV7tFduTkU2bNuGnP/0pAODll19GdnY2du/ejeeeew4PPfRQiweoY8uWLejWrVub75cQQghpUbhM03Sqq6uRlnZgWeDNN9/ERRddBIfDgeHDh2P37t22+qqsrFTuauzatQtbtmxBZmYmevTogVmzZuGbb74J34l54IEH0KtXLwwYMAC1tbV48skn8dZbb+HNN9+0exiEEEJIXNGRH+21fWekd+/eePXVV7Fnzx688cYbYZ3Ivn37bC+BfPTRRzj55JPD3iQFBQU4+eSTcfvttwM4YGZWXFwcrl9XV4cbbrgBAwcOxBlnnIGPP/4Ya9aswTnnnGP3MAghhBASJ9i+M3L77bfjsssuw8yZM3HOOecgLy8PwIG7JHYMzwDgzDPPhBkhk+WSJUuU8k033YSbbrrJbshadE6AgU7qMIWE7qyuqyq6y8ouV8rScbVPilr+srqrUnaK6e0PQkEaMIUjrHBU7ZJWpZRLvjtKDdgpXESr1f4CKer2Tt8K0abUQEpdm3BslbcOrSJJtRhMlAJYteysbXB+LBmU1TccASnQFLFWqsEGOwlBpnRglS6awpHVlK6XQtRoETlKEabIAowK9VwiWYiTZfuKyoj7t5TFubC4fupEh9L1s5MqrjarVTG23L+lvRR9NthuEXRqxLbarLPy2CzfA6J/qe90C6G7GHvpbqsTzFoEunbRXVtyf3LshWOtgchuwbprResIK4iUaddwRP6psjio6txepQNrQIy9cZi/Wxs6sDad//u//8Ppp5+OkpISDBo0KPz+Oeecg1/+8pctGhwhhBDSoWjHE4poaJYDa05OjiUXzGmnndYiARFCCCGkY9GkyYidvDGvvPJKs4MhhBBCOiptLWBdtGgRFi1ahK+//hoAMGDAANx+++3hNC21tbW44YYbsGzZMvj9fuTn5+PRRx9FdnZ2uI/i4mJMnToV//73v5GamorJkyejsLAQLl0iSkGTans8nvDfpmli+fLl8Hg8GDp0KABg48aNKCsrszVpiSdkNk251htyC9Mz4SuV0FnVHXTtpK4dd0tSNSRHJVQoZZ9bXWd3G+r6ZVkwsjA4PVk1mvq+QtWYGGliPVQmtKySa+VqsU7s3il8tixZe2VyUqGxMUQ2T1eNzIQrwhFryQkVhyoEk9Rzo+hJGkH2FUhTM8E6a0UmVJl115QLyJF1C4Y0QZPr+jKTrMSSFVecS2kqJk3EZH2pyahWHewMqUmp0+gYpImcNGGTxl4CqR+y6AwaHk+EjL5AI5oMeawyy6/83IvYpIbDkSz0MHJsdFl9Zf/yeKQBncyorNPX6K4laUImHfZkPJr2CInPikanYY1f6pkOr+OwaD5EW6u2SWhINPu2xNrwXNo8r1HRxpqRY445Bvfccw/69OkD0zTx7LPPYuzYsdi8eTMGDBiAmTNn4vXXX8dLL70Ej8eD6dOn46KLLgqnYQkGgxgzZgxycnKwYcMGlJSUYNKkSUhISMDdd99tK5YmTUaeeeaZ8N8333wzfv3rX2Px4sVw/u8EBoNB/O53v6OhGCGEENJOuPDCC5XyXXfdhUWLFuG9997DMcccg6eeegpLly7F2WefDeDAXKBfv3547733MHz4cLz55pvYvn071qxZg+zsbAwePBjz5s3DzTffjDvuuAOJ8p+jCNh+tPfpp5/GH/7wh/BEBACcTicKCgrw9NNP2+2OEEIIITi0TBPNC4AlOazfLx9xtBIMBrFs2TJUVVUhLy8PGzduRH19PUaNGhWu07dvX/To0QNFRUUAgKKiIgwcOFBZtsnPz4fP58O2bdtsHbvtyUggEMCnn35qef/TTz9FSD72SAghhJCm0UIOrLm5uUqC2MLCwsPucuvWrUhNTYXb7ca1114bzjXn9XqRmJiIjIwMpX52dja8Xi8AwOv1KhORg9sPbrOD7adprrjiCkyZMgVffvll+Ama999/H/fccw+uuOIKu90RQgghpAXZs2ePIptwu92HrXvCCSdgy5YtKC8vx8svv4zJkyfj7bffboswFWxPRv785z8jJycH999/P0pKSgAA3bp1w4033ogbbrihxQNsLQyHETagkplDzRRVxFeXKk3B1L5CIVXglOlWRYFHu39Uyhki7e3Rier2HVVqrp2aoCoCPCpJNcLyVqhZe0NBNd7UNFXg6vtePQCh0YSrSma2VbcbNr2ZpODVUS8VtJG3C483+DMPXbZJP8isvapQLeQWwjQpmtNk9ZX9WUSTocgixFCK+iUgBa1GmriYJH5NplpLJllxQPJcSSFfkhCsCtGmKY3CJNJYTGaelZlfBaZFVCloGK8mS65O4GkRiErRo8gYbBGsiu2WrLsWkzTpkqYRTWoErRaDukhi38b6k1lxNVl6pRGYPJfSJM0qMBb1tZl1I7e3tS9L9uvIyk7LWDbIrm3ITNutSEs9TWMnKWxiYiJ69+4NABgyZAg+/PBDPPjgg7jkkktQV1eHsrIy5e5IaWlp2NojJycHH3zwgdJfaWlpeJsdbC3TBAIBPP/885g8eTK++eYblJWVoaysDN988w1uuukmRUdCCCGEEBvEQaK8UCgEv9+PIUOGICEhAWvXrg1v27lzJ4qLi8PO63l5edi6dSv27TvkKr569Wqkp6ejf//+tvZr686Iy+XCtddeix07dgAAn54hhBBCWoo2frR31qxZGD16NHr06IGKigosXboU69atwxtvvAGPx4MpU6agoKAAmZmZSE9Px3XXXYe8vDwMHz4cAHDeeeehf//+mDhxIubPnw+v14vZs2dj2rRpEZeGGsP2Ms1pp52GzZs3o2fPnnabEkIIISRO2LdvHyZNmoSSkhJ4PB6cdNJJeOONN3DuuecCABYsWACHw4GLL75YMT07iNPpxIoVKzB16lTk5eUhJSUFkydPxty5c23HYnsy8rvf/Q433HAD9u7diyFDhiAlRV3zPumkk2wHEQvMkAnzfwtscu02mCTMhqQ3ULI6/czqrJqYZSSoycGqQ+pabq10ARMMSftaKX8fUDUhH/x4rLr/VNVkrSZJfYyr9Ef1DpaRIMyfHHI6LRLTiafCAqlqOVH1dLOYoAXFBNkhdAwhcRUaIvlcKEHGc2h7farQEXRSywmVUtOg25dawVGn7juUqPbvkMZZAVGukSZlmmRm0qRM6gbcGlMzqQuQaBLlWXQN8r8baRwm+xcaEmnEZU2kJ0zX5P4a6DSkCZkhDeFksjSpA9AtI2vMrWRiPMu5s/s0odSwyOOxJL6zp12walKEeEszHtrx0o637FBqeMRnRZOwVMFiwCb0NNrPgVQoqLEHUg6d60Cg7Z4SbWsH1qeeeiri9qSkJCxcuBALFy48bJ2ePXti5cqV9nbcCLYnI5deeikA4Pe//334PcMwYJomDMNA0OYHhhBCCCFg1l477Nq1qzXiIIQQQkgHxfZkhFoRQgghpOUxTNOSr8lu+/aK7ckIAHz55Zd44IEHwk/V9O/fH9dffz2OP/74Fg2OEEII6TBwmabpvPHGG/jFL36BwYMHY+TIkQCAd999FwMGDMD/+3//L6zCjXcamp5ZjKKEcCyYKMrJqi7GH1CHsXenUqXc1/2tUt4XUAWlxyT+oJSrQ6qIz+v3KOWMxJqI5U3eY5RycpIqXAvWC4Mgvzi+pMiixgSfujkgshhLwashNKSWrMEyk24nISINqA0aZuYNJQqjJnEqQy71jaBb3VfSPjXYQKoQEVaqY+f6URVcBtNV0zBp4uWsrRbbhTjarZYt/9lIEaMlC690pJMplO2JELXbZTxSKCiNsARmlToeWkGtndh0beVYaNpLwzdrxmaBNFnTjZ0UmEqBrjSQ02TxlcisxLavBZsiUWm6ZulPGvRBHr8wlWt4LekM3ASWjMACaehmMXxrIDQ3deedtAi2JyO33HILZs6ciXvuucfy/s0339xuJiOEEEJIPNHWT9PEE7YT5e3YsQNTpkyxvH/llVdi+/btLRIUIYQQ0uGIAwfWWGF7MtK1a1ds2bLF8v6WLVuQlZXVEjERQgghpANhe5nm6quvxjXXXIOvvvoKI0aMAHBAM3LvvfeioKCgxQNsLQynE8ZBVx6xVhwUydXqhcmXs7OqI+jpURPd5SaoGpAEQ13v/EmiqinJcKi6hY3+XLX/5O+V8tvf/0QpJznVtda6gBp/oE6sNYvEfqZbrP0GpS5ALdarHmwWDUlQLB0nqp5wCAkNjkyMJ9s7hOakoU5E6nlkX446se4vji2Yoo6No16YeknNiUc17XIIUzNTmJqZLrHuLnUAVWoSQ1MkXzNkIjpp1iRMxSD3p9MBSJ2F0CVYdBAyWVxCZB2DJVFeBFMzABGTy0kNhdREWEy+pEGbNGDT2FVbYpemZDJ2eapk/0LHYNFIyHMjj8evfk/oNCRmXeSMlhZdhTxeqcsQ9Q1n5PGwaEqgS24XQaOi0a9Yx9ae6Zkci1hpRjryMo3tychtt92GtLQ03H///Zg1axYAoHv37rjjjjsUIzRCCCGE2IBP0zQdwzAwc+ZMzJw5ExUVB/7lTUtL07QihBBCSCQ68p0R25qRp59+OuzCmpaWxokIIYQQQqLC9mSksLAQvXv3Ro8ePTBx4kQ8+eST+OKLL1ojNkIIIaTj0IGfprG9TPP555/jm2++wbp167B+/Xr8+c9/xm9/+1t069YNZ555Jp5//vnWiLN1kWY90vQscpJdZCepCs6KkCpyHJdSpZQ/r1eFaD+EVOOsFCFo3V1zlFJ2OVRhXpJTFap1z1DT6H5bppqm1ZvqaQ+lC+WdT90eVMODs06KRtXtDpnMVIyfs1YI26QWTYQjTdFCzkMNXDVCpCgEpPVpIotvhTRiErEKEzWHX2bxVYMLJQoBbI167kIpqojRqBf7l4JVXeZXKVAV59IiQNVllpX1JVIEKo25pBDQkg1VRRqJaWkgXLQIUIWgVMZmyYorRZBSgJoY+YNu1qpiY8uxiu8Ni2laSAhwdccjt1uy8AqxsBQbS4GqPH5pwqYToAohpzQ5MzWZcC2CXCm+ltdSJAM9jamZRCfWlWPZMFN4CG1retael1qiwfadEQA4+uijMWHCBCxYsAAPPvggJk6ciNLSUixbtqyl4yOEEELIEY7tOyNvvvkm1q1bh3Xr1mHz5s3o168fzjjjDLz88sv42c9+1hoxEkIIIUc+pmkvJUJj7dspticj559/Prp27YobbrgBK1euREZGRiuERQghhHQs+DSNDf7yl79g5MiRmD9/PgYMGIDLLrsMjz/+OD777LPWiI8QQgghRzi274zMmDEDM2bMAABs3boVb7/9NlatWoXp06cjKysLe/fubekYWx8h5AokCwfTFLV6WpqaJfc44ZD685RipfxlILJoL0FkWv0uoD4ufUKnEqW8tyZDKUuBVSeXKuSzOLBKh9U6IRwTs2tnbWTBqpR3ScPCepHVV7aw9CeEc64atdzQwVXGGhICVmed5l8FcWocAZmpVWQqFY6sUpAa9KgH66gSIj2BIbPYSjG1vO0qy1KUWKOKLJEs1MdS5FkrUixLl1HpcioFrxYRpBAtCsGtYUoRp/pZiiSqtAgm/TI9tHQI1WSp1WUgFk7MRiiykNGs0QhSpX5UjrUUpGoEq5b9a9x2dQ61FgFponQpjSz6tDi0IrJrqvb4GpZ1wmyB5dxL4bTI1B43eXlpemYP0zSxefNmrFu3Dv/+97/xzjvvIBQKoWvXri0dHyGEENIhMEIHXtG0b6/YnoxceOGFePfdd+Hz+TBo0CCceeaZuPrqq/Gzn/2M+hFCCCGE2Mb2ZKRv37747W9/i5/+9KfweDz6BoQQQgjRw2WapnPfffc1qd7AgQOxcuVK5ObmHrbO+vXrcd9992Hjxo0oKSnB8uXLMW7cuIj9rlu3DgUFBdi2bRtyc3Mxe/ZsXH755TaO4H8YhjVL5f+QWWV1C4onJu9RyvvFWmymWGtNNdS173W16rq+zPpbVNVHKR+TXKaUv67KVMrldWp/qanqunxVtWrEFahWLwNXpchUmxTZ/Cgok5+KW4VumdVXLJUnVIpPkBhvqUFpaJpmSt8psS4tTc6CSWKtWN7WFJoMR11ksySpO3BWCh2DNA1zCx1BuipIMmqFpkMaP9XWRd4uNSdSIyJ1Ekni5Mm1eGkMJo21JNJcSqd5kfHItf6G/Wk0B5a2Go2F1KBIHYElVllfY1pm2b8ug7I0TZMZkmWWXnluBFqTNLldc64sJmWWHWoM7ywmbRqNT8P+dI+syuvOZrZqGVt96qF9B+qbZcfVLPg0TSvw9ddfo15+EQqqqqowaNAgLFy4sEl97tq1C2PGjMFZZ52FLVu2YMaMGbjqqqvwxhtvtETIhBBCSOw46DMSzaud0iwBa0sxevRojB49usn1Fy9ejF69euH+++8HAPTr1w/vvPMOFixYgPz8/NYKkxBCCCGtSNvdf2oBioqKMGrUKOW9/Px8FBUVHbaN3++Hz+dTXoQQQki8cXCZJppXe6VdTUa8Xi+ys7OV97Kzs+Hz+VBTU9Nom8LCQng8nvArkoaFEEIIiRnM2nvkMmvWLBQUFITLPp/vwITE6TgkkBIivkAndY4ms84Gg+p2b32GUu7qrFTKCVBFjZ2FEK1/4o9K+T81PZSyQ1xhbqcqXMt0q8ZZ2/Z2U8rSpC2wXxhhOdT+6zyqiDGhQj1ep9BoutSkxJbxCqhJjGFIXZ9bFZ8lVoYibq9PPVR2l8nMqNIgLXIm0/pksW+fzN4Z2RBOzuctWXxFll9Dlv0iU6pbbW9oDPOkiNIiSPVJUzONaZnsT4o2pVGWFFGK8TcDIsuvzIyrERYi2KAsY5UZjzWZWC2mWlIgKr8OpShSipF1AlV5rNJUTZN51iKwlds1GZctAlcpkJXxyvGV6LL+BiOPj+Xcy/giCZClFlkXi0SKnyNlBAYQSDrUX9BmhmDSPNrVZCQnJwelpaXKe6WlpUhPT0dycnKjbdxuN9xu+bgHIYQQEl905KdpWm0y8thjj1mWVKIlLy8PK1euVN5bvXo18vLyWnQ/hBBCSJvDrL32WLt2LdauXYt9+/YhJG5dPv300wCAyy67TNtPZWUlvvjii3B5165d2LJlCzIzM9GjRw/MmjUL33zzDZ577jkAwLXXXotHHnkEN910E6688kq89dZbePHFF/H666835zAIIYQQEgfYnoz86U9/wty5czF06FB069YNhm6tLgIfffQRzjrrrHD5oLZj8uTJWLJkCUpKSlBcfCjpXK9evfD6669j5syZePDBB3HMMcfgySefbN5jveYhtY+ZpK5lSh1BIEWdcHVJUUUSe+tU07E+iV6l3EOs/X4TrIgYWq5LNT2rFu19NeqSVHFlhlJOSVF1AtLkDJ3kWrJadPpEgi251C5WxKTxmEx8JzUmsr40TasTFRKq1fF3BA4FLPU9rhq1bqCTNOESsdWLteSgWnbWCk2HTLAlNRIikZ4psqPJ7c66yKZiFlM3YZqGSpFoT5qWyXV6+Z+TTGynMzWTn3dZPyR0Am6he5DJ7ER8Zp24eDTGXkpbmRhOLs9KPYzlWISmol5oSqSGQ461JpmbXdMyiz5Hg0UDYtFJRE4cqDVFq5fXauR4pKmZNsljJJM6XdJDG9cJ0ISxCjX+d2vT1ss0hYWFeOWVV/Dpp58iOTkZI0aMwL333osTTjghXKe2thY33HADli1bBr/fj/z8fDz66KPKykdxcTGmTp2Kf//730hNTcXkyZNRWFgIl0bX1BDbk5HFixdjyZIlmDhxot2mFs4880yr618DlixZ0mibzZs3R71vQgghJK5oYzv4t99+G9OmTcOpp56KQCCAW2+9Feeddx62b9+OlJQD7tAzZ87E66+/jpdeegkejwfTp0/HRRddhHfffRcAEAwGMWbMGOTk5GDDhg0oKSnBpEmTkJCQgLvvvrvJsdiejNTV1WHEiBF2mxFCCCEkjli1apVSXrJkCbKysrBx40b87Gc/Q3l5OZ566iksXboUZ599NgDgmWeeQb9+/fDee+9h+PDhePPNN7F9+3asWbMG2dnZGDx4MObNm4ebb74Zd9xxBxI1T4UdxLbPyFVXXYWlS5fabUYIIYSQCLSU6Zk0+vT7/ZF3/D/Ky8sBAJmZB6QHGzduRH19vWI22rdvX/To0SNsNlpUVISBAwcqyzb5+fnw+XzYtm1bk4/d9p2R2tpaPP7441izZg1OOukkJIjkUH/5y1/sdkkIIYSQkGn1o7HbHrCYe86ZMwd33HFH5KahEGbMmIGRI0fixBNPBHDAaDQxMREZGRlK3ezsbHi93nCdxsxID25rKrYnI//9738xePBgAMAnn3yibItGzNrmGEZYwGbUq2KmRJFF1lmj3kCqD6liqiSh2Py6/iilHMJ+pRxEutq/WOirMtXbWh9XqiZovoBqWlYbUCeEnVNUUWNVVWelbAaECLNOKlDVYkhcJVKQ6hTmt9L0zCW3y/5qERHTKUSPDUSmrlrxwZVJYaVmrkYYYYm+g24hni0X6jUpwBSmZGaiem2ERFkKXi0iSClaFIJX1IntycLATiIFqi6Z6VaebFG2KQy09G85HiHirFVPfqRMslqxqzQ5c0Y2QbNkiRViXIsxlkj8KcW5lngEUrAqs+BaBLIWcbAYS81jnDJ+y/HrTNOk4FcnIrWYg2mMyeS1FUkALD838rrViWF1GZktYtvD/N3atJBmZM+ePUhPP/Q70xSvrWnTpuGTTz7BO++8E0UAzcf2ZOTf//53a8RBCCGEkBYgPT1dmYzomD59OlasWIH169fjmGOOCb+fk5ODuro6lJWVKXdHSktLkZOTE67zwQcfKP0dNCc9WKcptKvcNIQQQsiRioEoNSM292eaJqZPn47ly5fjrbfeQq9evZTtQ4YMQUJCAtauXRt+b+fOnSguLg6bjebl5WHr1q3Yt29fuM7q1auRnp6O/v37NzmWdmUHTwghhByxtLED67Rp07B06VK89tprSEtLC2s8PB4PkpOT4fF4MGXKFBQUFCAzMxPp6em47rrrkJeXh+HDhwMAzjvvPPTv3x8TJ07E/Pnz4fV6MXv2bEybNs1WKhZORgghhJAOyKJFiwAc8O9qyDPPPIPLL78cALBgwQI4HA5cfPHFiunZQZxOJ1asWIGpU6ciLy8PKSkpmDx5MubOnWsrlo47GQkEAeN/AiopjpJFp/rG/spOajmQopR7ufcp5bKQWr9/orr97erjlfLWqmOUcr2w4fzS10Upd0pQhWZ7flAFqxZBlNRuCYGus1Y40CarDVw16nYpWE30id1pFgNNqamsE1mEU9X9JZUd2l4vHFidfiE+FoJPKViVBJPV/gLp6szeIfvTZV6tF/WFIDWUpgpQDeH4atSqamEzRdSvFmpiKRKUDqhSlFkl1MWdhL1ujVAXW4R/Ukgo7XUjiy4tmXbNwwuGLQ6gcl+WDMRCcCqe/LOKFsWxyfpSnCvHRvRnuITg1i8Eq/K/RkuWYOHuqxHgGlG750r1t2a7RB6/FCMLAa4U7FrOr9pYLUuzVjl2MnbdHQMxtrHK2tvWDqyRTEcPkpSUhIULF2LhwoWHrdOzZ09L3ji7dNzJCCGEEBJPtLEDazxBASshhBBCYgrvjBBCCCFxgGGaMKIQsEbTNtZ03MmIywkYjR++NKZKqFBvINVWC1OysqOV8jGJqsnZ/kCqWr9amJgF1XX6b2sylLJDLARW+tW15nLRPlAvjLcCYm25Vpo9qUWZpTexXJqOqdvF7hGUzsNyKV4kmnWIzLkhl7o/qQNpqNNIqFLXkmVbaWLmEBoGUy41i6y9UiNiSA2EqC9Nz8yEyFl+peGePBdmsnqtGVU2NRzS/Elul+vhQtegXWuXRlw6kzRpeiZ1ENJIrKHRmMyCa4ixdmiy6EpNg9QVSOTYyWOT51LqX3RjIcdWXEtSE+NIVj9ooRpV72PRxMix1V4bGs2HxjTNYvomPovy/Em9gsVkrqFeKFJG30aRYyvaa859Qx1cNIaotgn97xVN+3YKl2kIIYQQElM67p0RQgghJI7gMg0hhBBCYksHfpqGkxFCCCEkHmhjB9Z4osNORoyEBBjGAZWS6VaHIbFCCLVEll6zXpXalFSoCYlerB+ilHulqYLWBIfaf0aCKkQrq1ONrQIik2pygioUK/khQymjRpzWgCokc9SLcl1kgapDaBolMmuvNDlzivZSsGpITahIRJtcJusfKgfdauxS0CqTNThrxbkVosFgYmSjp2CSEO0JkZ6rUhhtCRMzM0GTyVRiSoGsKlI0ZFZeS7ZSjVGXJYuvHDCZxVcj6tRlT9WJFuX2BiJJM1QvqsoLR5pqCUGnwBSGctIQzpLV1pJVVl7Y4nMkPrdmSIyVLitvSCP41AlSJZprzSJIFedWt10ev0V0qjEPs2QJbigytVyHmutOotluOIVQ3Gz8b9J6dNjJCCGEEBJPtLUDazzByQghhBASD3TgZRo+2ksIIYSQmNJx74yEQmGxglGrrkUHOqnri0k/qE1ru6rDVmaopmZ1HrV9XUCtX12nrmVXlKtmRp0zq5RyZbVqclZXLXQD5aIclBoRqAinr4RKdbNTyAqCIp+Xu0wtW/q3GImJ+qIsJDlIrBA6CemF1GBp2aHxlXLWClM0oYkwhUZEakisOgBhilYdWRPhqFXXwYNJatJErWmZ1BHo5PKyfb04OUniZFYLwY/UWUiNiNQdSB2FJV5NfBI5Hg33p0kkZ9FYaEy6tDoDiRxLTVJAi6ZFJrYTY21aEu8JzYnQVFiOR1PfYtImNDIykZ1EakRkYjuHuLZ0/VmupUjnQ5oNymOX2ipx7h0JIjYxNqYYm0CD6nbt1qLBOPSz1Oz27ZWOOxkhhBBC4gku0xBCCCGExAbeGSGEEELiAZqeEUIIISSW0A6+A2IGgzD/p6w0hNAqsVwVqjkz1dUsV5VarhdGVtWmKkiVWX7NkBBRBtT+yn2qyDH4o9reVaHuL5AhVJx+ke1TxGsxMZOaQaHYkgJXKZIKCE2mW5iUyf5d1XKHor9kYSRWre6wYSZeaaDm9Avjq4AQpqWpY+eqEaJDIZJ0SHFzqjBHgkBjLOWoFoMvs/4miP37g2K7EPmF5OBFNgJDQBh9uYWgVYo0RRZdyMyssn6iqC9FjLK+TrDb8MtVHotEGqgJgaUUKVrEyTLrrURmsbUITjWmYrK9LquvbK/Jkhsp6y0AGEni3GgM6bTxyOOJdO6a1GGk8dNlj5aGcBoDNo14uaEPpc70kbQMHXYyQgghhMQVHVjAyskIIYQQEg+YAKJ5PLf9zkU4GSGEEELiAWpGOiCOpGQ4HImNbxPr9J2+U8t16SKx3o/q+mPILUzPPMIISy7jpwpNRK0wXfOKtVlx1hJ3i7VksQwvTcksJmUCqRFxSF2DWI91+tXtCZVqOZQoNCD+yEZkyZWRE2w5Gmx3CE2I1Ig4hIbC/aPQiIhlalMYWZlC0+AqVzUXhmbd33QLYyu5ji/+DZKJ9aTpmCHX1XU6CvnlJBPjSaSRl1+YQ9WoJmlGsqqPsugQpI5AmlVJDUok3YU8dpk4zhDnTmdqptGUWDQYEhmrPBfyWpLXihwbO/qZRvYvNRsykZ7FBE2iS6Qn+5OJ/yIZ1qEJGhdJg/NhMbCTdaXBnKFxrZD9Ce1UQyNGacpIWocOOxkhhBBC4goTUWpGWiySNoeTEUIIISQe6MACVjqwEkIIISSm8M4IIYQQEg+E0Iggxmb7dkpcTEYWLlyI++67D16vF4MGDcLDDz+M0047rdG6S5YswRVXXKG853a7UVtb22j9w2EGAzBDB24MGRWqYtPhES5ehipuSv5evRXm96hXT0ho8qTgU+KqEgJVIZiSglK53SUSr0pTMiloTdqvVpAmY1JQmlAlBKniqkmojmwcllAV2YgsQWTWddaq4rKQzKzboL3cl6WuECU6pUDUYjoms/hKsyQhynNEzpxq+NWLwVGvMTGTSJGfLouu3G4RQYqLQV6atcIUTQhOrZlvNVmCJTIe2V6KThuKHuXnSI6lFIiKvi0mXdL0TO5bXDtmvciaK7PuBjUCUXEtWQSnmlvsFhGnPB4pyI0cjdVETfYvTOAsAlh5PnQCY3EtW+KXn7UG/RtoWRWpIcz55L6DSQ3+jmZyYJOO/DRNzJdp/v73v6OgoABz5szBpk2bMGjQIOTn52Pfvn2HbZOeno6SkpLwa/fu3W0YMSGEEEJakphPRv7yl7/g6quvxhVXXIH+/ftj8eLF6NSpE55++unDtjEMAzk5OeFXdnZ2G0ZMCCGEtAIHBazRvNopMZ2M1NXVYePGjRg1alT4PYfDgVGjRqGoqOiw7SorK9GzZ0/k5uZi7Nix2LZtW1uESwghhLQenIzEhu+//x7BYNByZyM7Oxter7fRNieccAKefvppvPbaa3j++ecRCoUwYsQI7N27t9H6fr8fPp9PeRFCCCEkfogLAasd8vLykJeXFy6PGDEC/fr1w2OPPYZ58+ZZ6hcWFuJPf/qTtSOH45DYUIiZpAtm8rfVStlZk6SUE6pF1t6jZGZYddfS9dOQk1lpzCgzzwrBqdunbpdZbmX/UqCaJASkhhB1hlxifz8KoZwQsrmqhZBQuo5Kp0qxPeRS58hO0Z/DbyPbqeY/BaNO7SvkVM+txRHVKV03hUhPCjSloFQ4oBq1NgWfUqQpx1I6rOpcLnWCU+kKKjArq5SydLK0OKyKc2sRdYpMuA1Fj0ZItNWIEHWCVIkpxLtSEOtITVG3+2UGZo14WCPw1KETfBrJ6rVrVqvfWxZXUrl/UbYIVi1iafk5l2LkyPuzCFYFDQW5uozElmzVGnGt5diEmLdhpl5T8xFpUWLgM7J+/Xrcd9992LhxI0pKSrB8+XKMGzeuQZcm5syZgyeeeAJlZWUYOXIkFi1ahD59+oTr7N+/H9dddx3+3//7f3A4HLj44ovx4IMPIjU1tclxxPTOyFFHHQWn04nS0lLl/dLSUuTk5DSpj4SEBJx88sn44osvGt0+a9YslJeXh1979uyJOm5CCCGkxQm1wMsmVVVVGDRoEBYuXNjo9vnz5+Ohhx7C4sWL8f777yMlJQX5+fnKE6wTJkzAtm3bsHr1aqxYsQLr16/HNddcYyuOmE5GEhMTMWTIEKxduzb8XigUwtq1a5W7H5EIBoPYunUrunXr1uh2t9uN9PR05UUIIYTEGwcf7Y3mZZfRo0fjzjvvxC9/+UvLNtM08cADD2D27NkYO3YsTjrpJDz33HP49ttv8eqrrwIAduzYgVWrVuHJJ5/EsGHDcPrpp+Phhx/GsmXL8O233zY5jpg/TVNQUIAnnngCzz77LHbs2IGpU6eiqqoq7CUyadIkzJo1K1x/7ty5ePPNN/HVV19h06ZN+M1vfoPdu3fjqquuitUhEEIIIXGD1En6/X59o0bYtWsXvF6v8pCJx+PBsGHDwg+ZFBUVISMjA0OHDg3XGTVqFBwOB95///0m7yvmmpFLLrkE3333HW6//XZ4vV4MHjwYq1atCotai4uL4Wiwbv3jjz/i6quvhtfrRefOnTFkyBBs2LAB/fv3t7fjQCC8xmkGxbq3xYhJmHhVqNsddeparrNGmPuItepAitANCN1B0C36F5oRlKlF2V5qRkIJavyJtZHv5ZlOqfEQ/VdI8yO1GEhT1/JdlSJbp1zfFbP5BJ8qsglmirX6BteD/E/AUa6uk5vSaEnzn4OjSmTlLa9QK6Sra6BmovgIiYzElqy3ieqxGEIjAYfUOUgjKGfksqwvTczkWrsus63UPQiNikUjIjUmcu1e9KfL5KroCqQ+RpP11qJJkJoRjWZCHpuMVacJsdSXyKy+UgMiTcksGg2xP/mDI8+t1Odox0eTcVn0rzNh02bWjWRSp8tWLfuSxyL/7ZZjI8bWn9lgV837HW8eLaQZyc3NVd6eM2cO7rjjDtvdHXyQJNJDJl6vF1lZWcp2l8uFzMzMwz6I0hgxn4wAwPTp0zF9+vRGt61bt04pL1iwAAsWLGiDqAghhJA2JGQ28kSDzfYA9uzZo0gS3PKfhjgk5ss0hBBCCGk5pE6yuZORgw+SRHrIJCcnx+KYHggEsH///iY/iAJwMkIIIYTEB3FmetarVy/k5OQoD5n4fD68//774YdM8vLyUFZWho0bN4brvPXWWwiFQhg2bFiT9xUXyzSEEEIIiXZCYb9tZWWlYo2xa9cubNmyBZmZmejRowdmzJiBO++8E3369EGvXr1w2223oXv37mEvkn79+uH888/H1VdfjcWLF6O+vh7Tp0/HpZdeiu7duzc5jo47GTFNHDxx0gDHEKI/Q4innD5V8OrwqKJGp1+YMcksthWqsC0kMsWGElVxVUKFjE8Iw6SRlBCImklCCCficdSpQjYp4gxkqFmMDZEtVWa2TRTxhcT+ZSZbixBPiBgdFeJ8NBQOSmGbNBWrEeozt5qJ1CLIlF8Esn8puKwVYl5ppiSEcYYQN0OK/Bw6kabGSEAjctRm9ZUCVGns5U6MvF1cWxZRJgRSVCk2N/xsyiyyOkM2i8hRCtNlxmZdrPI61ZisaY26dD86crsUZVoM+KTBnk3BqUz3rRGaW7Iay/YW8bLmfEUaD0tG5shiWcvY6xD9JTQw6na0pYA1Bnz00Uc466yzwuWCggIAwOTJk7FkyRLcdNNNqKqqwjXXXIOysjKcfvrpWLVqFZKSDpnsvfDCC5g+fTrOOeecsOnZQw89ZCuOjjsZIYQQQuKJGDiwnnnmmTAjtDMMA3PnzsXcuXMPWyczMxNLly61ve+GcDJCCCGExAOhQ3fsm9++fUIBKyGEEEJiSoe9M2IGgzCN/62xWsyDxDq4KBti3dwQ65XOTsmRd64zhpKaCrn+qbsVJ5OlVYtFT2GOZKYLUzExHq7vNJmO5fGI+JyVIlNgolj7l7oLGb/QOZjJhx5TM8pEbCmqvsVitCT/c5AaD4lc55cmZTpke4kuWZhf6pc0/z9oxk6r6ZA6ADF+hjRxs2m0FQqJ47HoQIzDbrdou3QmW9JEK2jvfy9T6Gksifc0id8s8Undg0UDoktkp9F0yGtD6pU0iQUtyP409Q2nei4tpm8yfpuJDCPFYsjvUIFFUyK/g4S+yHQ2/nerY4as42S3fTulw05GCCGEkLgiBpqReIGTEUIIISQeoGaEEEIIISQ28M4IIYQQEg9wmaYDEgwBRuOCLFMaYSWJ7J1SiCaNsHTZOkV/OkMfi8hSihQtmVul0E2apAkTMmHiBikqlOZRcv8yPil8k+Iy2Z8ms6tFiFfXoH8pRJMCUxlrpThWuS957JaxFx8ZOba6sapWswpb6kukoDQoBKRCyOdIFWJkGb8UQ8v+IT4TUqQJnQgx8vFIEaWlf2k42DBDs8xiqxNgyr4tBnORTcO0gk9Nll4T4ntBjpXcv+57QKK5Fk2dWFsnhraIQjVZgKWYWde/7vxF6svynaE51xLNj3bDrL0hm5r1qDAR5WSkxSJpc7hMQwghhJCY0nHvjBBCCCHxBJdpCCGEEBJTQiFALoXabt8+4TINIYQQQmJKx70zYhhhUZQZEEKzROnsKIRpVWrZIQWuUpilc1IU4isjOQkRka6eUjimy1gpHVPl/qTwTeMiagrHWelIa0GOj4xHjLdFpNrQBVT+JyD7lqJAsS95bjV+qRY3Xsu5lg6iIY3QTp67ROliqXGIlSJNi+ul2K5xkNWKRO3eBtaJKDUiTWX/si+d26TMEmupL/ZtyGtDI3iVn1uNC6j1cy/2J/uTYmKJFD+L+A2Z4VmKQIXjq+XakXpd+b0iz53FyVqIkV3i2g5ohP4N4jXkZaIVL4uHEMS+LYixCLkPnYtQWy59cJmGEEIIITGlA09GuExDCCGEkJjCOyOEEEJIPNCB7eA77GTEDAQs2WnD22SGR6kDkJlPdWZCMhunNHaSRltS5yCNouRasdRUSDRGU5Br43I9VrM2bFQIIzFp6lYtsvbKtWepY5DHL89Tg+O3ZJWV6/4y06sYC0t9cW4sY6HTz/iF8ZTYrss0K3u31Ndl+dVpTDTnVpdp1aJr0GUB1q3V29CBaLPiWrbLrsW+QpG1TRYNiNR4SM2DzuTLguZc6n5YTKFl02lYDNGfLn5dxmsZTlBnNKbRsESobwYia0BC8nOuuy5NOTZCb1NvNPp3a2OaIct3mt327ZUOOxkhhBBC4grTjO7uBjUjhBBCCCHNg3dGCCGEkHjAjFIz0o7vjHAyQgghhMQDoRBgRKH7oGak/WG4XDCMAyKokF8aQYlslFLcJAWdlgtAiqU0xk4y26ZFEKtmepWCV51RlTQrsooMxWWgySRrMerSIUWfcvw0glU7xluWLZast5q+dIJKjehOK7IUXzTWeDRfJhqRoV70GNkkznJta7BmshXmUVJYaBGd6rYf6l8nStTGJpD7ClnM+uTn3J7gUyv2tWuapsEqWBWCW9251l1LMkuvzBgtvmdC9fJatJGlV4NOsKo/N3K7em7d+w/9HbT5dUeaR4edjBBCCCFxBZdpCCGEEBJLzFDIcvfUVvt2vEzDp2kIIYQQElM67p0Rh6E1sAoj1xvl0qdGV2BKcyWdDkGzzh6qro643VJfl1RKg06HEO1ad7T7t4Mu1pbcF9DIOr1m/3Kd3aozsHct2T/eYOTt0mROZ8om45NmUzKeCO0t6/wadBoNy1jKWHSJ3HQaCMv3QOSxlMdnV2Ni1choNDWB5puQNYZVcyOa2/0eapgoT17HOg2IPHbL5yTy59zR4FBMjZdbi8JlGkIIIYTElJCpnShFpB1PRrhMQwghhJCYwjsjhBBCSDxgmgCi8Rlpv3dGOBkhhBBC4gAzZMKMYpnG5GSk/WE4nTBkWs+mont8yu7jVZr6ds2dbAvF7KIxU4pnLOLjON+/7Xh1Ymu7+7Np8qbvP4oToBN+R3nsLU6U3wNWYy6daDNKtN9DLbs7LQ3Fy7p9t/B3rqIhbcvfdzOE6O6M8NHeqFi4cCGOPfZYJCUlYdiwYfjggw8i1n/ppZfQt29fJCUlYeDAgVi5cmUbRUoIIYQcWdj9DW4NYj4Z+fvf/46CggLMmTMHmzZtwqBBg5Cfn499+/Y1Wn/Dhg0YP348pkyZgs2bN2PcuHEYN24cPvnkkzaOnBBCCGk5zJAZ9csudn+DW4uYT0b+8pe/4Oqrr8YVV1yB/v37Y/HixejUqROefvrpRus/+OCDOP/883HjjTeiX79+mDdvHk455RQ88sgjbRw5IYQQ0oKYoehfNrH7G9xaxFQzUldXh40bN2LWrFnh9xwOB0aNGoWioqJG2xQVFaGgoEB5Lz8/H6+++mqj9f1+P/wNEruVl5cDAJbsuBfp6elRHgEhhJAjGZ/Ph9xHb20TcWgA9VFpVAI4YNTn8/mU991uN9xut6V+c36DW4uYTka+//57BINBZGdnK+9nZ2fj008/bbSN1+tttL7X6220fmFhIf70pz9Z3s/NzW1m1IQQQjoaP/zwAzweT6v0nZiYiJycHLzjjV7/mJqaavl9mzNnDu644w5L3eb8BrcWR/zTNLNmzVLupJSVlaFnz54oLi5utQvrSMbn8yE3Nxd79uzhnSWbcOyaD8cuOjh+zae8vBw9evRAZmZmq+0jKSkJu3btQp1IBdIcTNOEIVKdNHZXJN6I6WTkqKOOgtPpRGlpqfJ+aWkpcnJyGm2Tk5Njq/7hbk95PB5+KKMgPT2d49dMOHbNh2MXHRy/5uNwtK7EMikpCUlJSa26D0lzfoNbi5gKWBMTEzFkyBCsXbs2/F4oFMLatWuRl5fXaJu8vDylPgCsXr36sPUJIYQQYqU5v8GtRcyXaQoKCjB58mQMHToUp512Gh544AFUVVXhiiuuAABMmjQJRx99NAoLCwEA119/Pc444wzcf//9GDNmDJYtW4aPPvoIjz/+eCwPgxBCCGl36H6D24qYT0YuueQSfPfdd7j99tvh9XoxePBgrFq1KiyoKS4uVm6PjRgxAkuXLsXs2bNx6623ok+fPnj11Vdx4oknNml/brcbc+bMaRdraPEIx6/5cOyaD8cuOjh+zedIHzvdb3BbYZjt2cyeEEIIIe2emJueEUIIIaRjw8kIIYQQQmIKJyOEEEIIiSmcjBBCCCEkphyRkxG76ZBfeukl9O3bF0lJSRg4cCBWrozekrc9Y2f8nnjiCfz0pz9F586d0blzZ4waNSom6afjheam4l62bBkMw8C4ceNaN8A4xu7YlZWVYdq0aejWrRvcbjd+8pOfdOjPrt3xe+CBB3DCCScgOTkZubm5mDlzJmpra9so2vhh/fr1uPDCC9G9e3cYhnHYPGcNWbduHU455RS43W707t0bS5YsafU4j3jMI4xly5aZiYmJ5tNPP21u27bNvPrqq82MjAyztLS00frvvvuu6XQ6zfnz55vbt283Z8+ebSYkJJhbt25t48jjA7vjd9lll5kLFy40N2/ebO7YscO8/PLLTY/HY+7du7eNI489dsfuILt27TKPPvpo86c//ak5duzYtgk2zrA7dn6/3xw6dKh5wQUXmO+88465a9cuc926deaWLVvaOPL4wO74vfDCC6bb7TZfeOEFc9euXeYbb7xhduvWzZw5c2YbRx57Vq5caf7xj380X3nlFROAuXz58oj1v/rqK7NTp05mQUGBuX37dvPhhx82nU6nuWrVqrYJ+AjliJuMnHbaaea0adPC5WAwaHbv3t0sLCxstP6vf/1rc8yYMcp7w4YNM3/729+2apzxit3xkwQCATMtLc189tlnWyvEuKU5YxcIBMwRI0aYTz75pDl58uQOOxmxO3aLFi0yjzvuOLOurq6tQoxr7I7ftGnTzLPPPlt5r6CgwBw5cmSrxhnvNGUyctNNN5kDBgxQ3rvkkkvM/Pz8VozsyOeIWqY5mA551KhR4fd06ZCLioqU+gCQn5/f5umT44HmjJ+kuroa9fX1rZpUKh5p7tjNnTsXWVlZmDJlSluEGZc0Z+z++c9/Ii8vD9OmTUN2djZOPPFE3H333QgGg20VdtzQnPEbMWIENm7cGF7K+eqrr7By5UpccMEFbRJze4a/Ga1DzB1YW5LmpEP2er2N1vd6va0WZ7zSEumkb775ZnTv3t3yYT3Sac7YvfPOO3jqqaewZcuWNogwfmnO2H311Vd46623MGHCBKxcuRJffPEFfve736G+vh5z5sxpi7DjhuaM32WXXYbvv/8ep59+OkzTRCAQwLXXXotbb721LUJu1xzuN8Pn86GmpgbJyckxiqx9c0TdGSGx5Z577sGyZcuwfPnyNs8+2d6oqKjAxIkT8cQTT+Coo46KdTjtjlAohKysLDz++OMYMmQILrnkEvzxj3/E4sWLYx1au2DdunW4++678eijj2LTpk145ZVX8Prrr2PevHmxDo10UI6oOyPNSYeck5MTF+mT44Fo0kn/+c9/xj333IM1a9bgpJNOas0w4xK7Y/fll1/i66+/xoUXXhh+LxQKAQBcLhd27tyJ448/vnWDjhOac91169YNCQkJcDqd4ff69esHr9eLuro6JCYmtmrM8URzxu+2227DxIkTcdVVVwEABg4ciKqqKlxzzTX44x//qOQDIyqH+81IT0/nXZEoOKKuuOakQ87Ly1PqA8Dq1avbPH1yPNDcdNLz58/HvHnzsGrVKgwdOrQtQo077I5d3759sXXrVmzZsiX8+sUvfoGzzjoLW7ZsQW5ubluGH1Oac92NHDkSX3zxRXgCBwCfffYZunXr1qEmIkDzxq+6utoy4Tg4sTOZriwi/M1oJWKtoG1pli1bZrrdbnPJkiXm9u3bzWuuucbMyMgwvV6vaZqmOXHiRPOWW24J13/33XdNl8tl/vnPfzZ37Nhhzpkzp8M/2mtn/O655x4zMTHRfPnll82SkpLwq6KiIlaHEDPsjp2kIz9NY3fsiouLzbS0NHP69Onmzp07zRUrVphZWVnmnXfeGatDiCl2x2/OnDlmWlqa+be//c386quvzDfffNM8/vjjzV//+texOoSYUVFRYW7evNncvHmzCcD8y1/+Ym7evNncvXu3aZqmecstt5gTJ04M1z/4aO+NN95o7tixw1y4cCEf7W0BjrjJiGma5sMPP2z26NHDTExMNE877TTzvffeC28744wzzMmTJyv1X3zxRfMnP/mJmZiYaA4YMMB8/fXX2zji+MLO+PXs2dMEYHnNmTOn7QOPA+xeew3pyJMR07Q/dhs2bDCHDRtmut1u87jjjjPvuusuMxAItHHU8YOd8auvrzfvuOMO8/jjjzeTkpLM3Nxc83e/+535448/tn3gMebf//53o99hB8dr8uTJ5hlnnGFpM3jwYDMxMdE87rjjzGeeeabN4z7SMEyT9+QIIYQQEjuOKM0IIYQQQtofnIwQQgghJKZwMkIIIYSQmMLJCCGEEEJiCicjhBBCCIkpnIwQQgghJKZwMkIIIYSQmMLJCCGEEEJiCicjhBBCCIkpnIwQQmxTV1cX6xAIIUcQnIwQ0kEIhUKYP38+evfuDbfbjR49euCuu+4CAOzZswe//vWvkZGRgczMTIwdOxZff/11uO3ll1+OcePG4a677kL37t1xwgknxOgoCCFHIq5YB0AIaRtmzZqFJ554AgsWLMDpp5+OkpISfPrpp6ivr0d+fj7y8vLwn//8By6XC3feeSfOP/98/Pe//0ViYiIAYO3atUhPT8fq1atjfCSEkCMNJsojpANQUVGBrl274pFHHsFVV12lbHv++edx5513YseOHTAMA8CBZZiMjAy8+uqrOO+883D55Zdj1apVKC4uDk9OCCGkpeCdEUI6ADt27IDf78c555xj2fbxxx/jiy++QFpamvJ+bW0tvvzyy3B54MCBnIgQQloFTkYI6QAkJycfdltlZSWGDBmCF154wbKta9eu4b9TUlJaJTZCCKGAlZAOQJ8+fZCcnIy1a9datp1yyin4/PPPkZWVhd69eysvj8cTg2gJIR0NTkYI6QAkJSXh5ptvxk033YTnnnsOX375Jd577z089dRTmDBhAo466iiMHTsW//nPf7Br1y6sW7cOv//977F3795Yh04I6QBwmYaQDsJtt90Gl8uF22+/Hd9++y26deuGa6+9Fp06dcL69etx880346KLLkJFRQWOPvponHPOOUhPT4912ISQDgCfpiGEEEJITOEyDSGEEEJiCicjhBBCCIkpnIwQQgghJKZwMkIIIYSQmMLJCCGEEEJiCicjhBBCCIkpnIwQQgghJKZwMkIIIYSQmMLJCCGEEEJiCicjhBBCCIkpnIwQQgghJKZwMkIIIYSQmPL/AVWD5/d0ek1uAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.clf()\n",
    "h = plt.hist2d(cers, rates, bins=100)\n",
    "plt.colorbar(h[3])\n",
    "plt.ylim(0, 4)\n",
    "# plt.xlim(0, 0.99)\n",
    "plt.xlabel(\"cer\")\n",
    "plt.ylabel(\"n_words / sec  -- higher faster\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "2172be9d",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-18T03:01:36.428046Z",
     "start_time": "2024-01-18T03:01:32.654154Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:48:25.559235Z",
     "iopub.status.busy": "2025-01-14T01:48:25.559090Z",
     "iopub.status.idle": "2025-01-14T01:48:30.078970Z",
     "shell.execute_reply": "2025-01-14T01:48:30.078473Z",
     "shell.execute_reply.started": "2025-01-14T01:48:25.559220Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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z90TAMxoMzm1wppDs2JcMBMAwNWKPU0AAAAmEJoAAABMIDQBAACYQGgCAAAwgdAEAABgAqEJAADABEITAACACYQmAAAAEwhNAAAAJrg1NCUmJsrDw8Php3379vb158+fV1xcnJo0aaKGDRtq0KBBys3NdRjj8OHDiomJkZ+fn5o3b66nn35aRUVFDjVr1qzRzTffLIvForCwMC1evLjMXJKTk9WmTRv5+voqIiJC33zzTbW8ZgAAUDu5fU/TjTfeqF9++cX+s379evu6CRMm6LPPPtOyZcu0du1aHTlyRPfff799fXFxsWJiYlRQUKANGzbovffe0+LFizV16lR7zcGDBxUTE6Pbb79d27dv1/jx4zV69GitWrXKXvPhhx8qISFB06ZN09atW9W1a1fZbDYdPXrUNU0AAAA1nttDU7169RQcHGz/adq0qSTp5MmTevfddzVnzhzdcccdCg8P16JFi7RhwwZt3LhRkpSenq7du3fr/fffV7du3TRgwADNmDFDycnJKigokCSlpKQoNDRUr7zyijp06KD4+Hg98MADmjt3rn0Oc+bM0ZgxYzRy5Eh17NhRKSkp8vPz08KFC13fEAAAUCO5/Qt7v/vuO7Vs2VK+vr6KjIzUzJkz1apVK2VnZ6uwsFBRUVH22vbt26tVq1bKyspSz549lZWVpc6dOysoKMheY7PZNG7cOO3atUs33XSTsrKyHMYorRk/frwkqaCgQNnZ2ZoyZYp9vaenp6KiopSVlXXJeefn5ys/P9/+OC8vT5JUWFiowsLCK+rJxUrHc/a4V8riZbh7Cg6utD81tc91DX12DfrsGvTZdaqr15UZz62hKSIiQosXL1a7du30yy+/aPr06erTp4927typnJwc+fj4KCAgwOE5QUFBysnJkSTl5OQ4BKbS9aXrLleTl5enc+fO6fjx4youLi63Zu/evZec+8yZMzV9+vQyy9PT0+Xn52euAZWUkZFRLeNW1ewe7p6Bo5UrVzplnJrW57qKPrsGfXYN+uw6zu712bNnTde6NTQNGDDA/u9dunRRRESEWrdurY8++kj169d348wqNmXKFCUkJNgf5+XlKSQkRNHR0bJarU7dVmFhoTIyMtS/f395e3s7dewr0SlxVcVFLrQz0XZFz6+pfa5r6LNr0GfXoM+uU129Lj1SZIbbD89dKCAgQDfccIO+//57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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(total_infos_2.values(), bins=np.linspace(0, 1, 50))\n",
    "plt.grid(True)\n",
    "plt.title(\"Deezer cer distribution\")\n",
    "plt.xlabel(\"cer\")\n",
    "plt.ylabel(\"n_songs\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "097e26a4",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-12T22:41:30.694878Z",
     "start_time": "2024-01-12T22:41:30.692934Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:48:30.079677Z",
     "iopub.status.busy": "2025-01-14T01:48:30.079522Z",
     "iopub.status.idle": "2025-01-14T01:48:30.082164Z",
     "shell.execute_reply": "2025-01-14T01:48:30.081768Z",
     "shell.execute_reply.started": "2025-01-14T01:48:30.079662Z"
    }
   },
   "outputs": [],
   "source": [
    "# sub_total_infos = {k: v for k, v in total_infos.items() if k in total_infos_2}\n",
    "\n",
    "# len(sub_total_infos)\n",
    "\n",
    "# plt.hist(sub_total_infos.values(), bins=np.linspace(0, 1, 50))\n",
    "# plt.show()\n",
    "\n",
    "# np.median(list(sub_total_infos.values())), np.median(list(total_infos_2.values()))\n",
    "\n",
    "# interesting_diffs = []\n",
    "# for k in total_infos_2:\n",
    "#     if k in sub_total_infos and total_infos_2[k] - sub_total_infos[k] < 0.3 and sub_total_infos[k] > 0.6:\n",
    "#         interesting_diffs.append(k)\n",
    "# print(len(interesting_diffs))\n",
    "\n",
    "# for idx in interesting_diffs:\n",
    "#     if idx in metas_map and metas_map[idx][\"lang\"] == \"zh\":\n",
    "#         print(metas_map[idx])\n",
    "#         break"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42dcbcc8",
   "metadata": {},
   "source": [
    "# prepare the 2nd hoot dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "326e1b84",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-15T18:49:58.544826Z",
     "start_time": "2024-01-15T18:49:56.487590Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T15:34:40.602741Z",
     "iopub.status.busy": "2025-01-14T15:34:40.602572Z",
     "iopub.status.idle": "2025-01-14T15:34:43.196382Z",
     "shell.execute_reply": "2025-01-14T15:34:43.195791Z",
     "shell.execute_reply.started": "2025-01-14T15:34:40.602725Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "911520\n"
     ]
    }
   ],
   "source": [
    "high_cer_infos_2 = {}\n",
    "for k, v in total_infos_2.items():\n",
    "    k_lang = metas_map[k][\"lang\"]\n",
    "    # should probably also play it safe\n",
    "    cut_threshold = min(langs_cer_cut.get(k_lang, 0.5), 0.8)\n",
    "    if v <= cut_threshold:\n",
    "        high_cer_infos_2[k] = v\n",
    "print(len(high_cer_infos_2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "636c3311",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-15T18:51:44.029594Z",
     "start_time": "2024-01-15T18:51:42.398978Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T15:37:30.232542Z",
     "iopub.status.busy": "2025-01-14T15:37:30.232210Z",
     "iopub.status.idle": "2025-01-14T15:37:31.992066Z",
     "shell.execute_reply": "2025-01-14T15:37:31.991479Z",
     "shell.execute_reply.started": "2025-01-14T15:37:30.232525Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "895906 6999.265625\n"
     ]
    }
   ],
   "source": [
    "high_cer_train_info_2 = []\n",
    "for info in train_info:\n",
    "    if (\n",
    "        info[\"id\"] in high_cer_infos_2 and info[\"duration\"] < 360\n",
    "    ):  # --> this is how v3 t9 data is prepared\n",
    "        # if info[\"id\"] in high_cer_infos_2 and 210 < info[\"duration\"] < 300:\n",
    "        high_cer_train_info_2.append(info)\n",
    "print(len(high_cer_train_info_2), len(high_cer_train_info_2) / 2 / 8 / 8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "bf451a42",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-15T18:52:00.685027Z",
     "start_time": "2024-01-15T18:51:59.480509Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T15:37:43.551574Z",
     "iopub.status.busy": "2025-01-14T15:37:43.551251Z",
     "iopub.status.idle": "2025-01-14T15:37:46.406410Z",
     "shell.execute_reply": "2025-01-14T15:37:46.405823Z",
     "shell.execute_reply.started": "2025-01-14T15:37:43.551558Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total duration khr 50.62553444444445 60 359 21 7299\n",
      "Counter({'en': 556183, 'es': 53985, 'pt': 38682, 'fr': 37381, 'de': 31486, 'ru': 28456, 'pl': 27434, 'it': 22929, 'tr': 12561, 'ko': 10908, 'ja': 8834, 'iw': 5892, 'nl': 5445, 'ro': 4010, 'da': 3669, 'sv': 3493, 'ar': 3166, 'hr': 2961, 'sr': 2824, 'no': 2534, 'vi': 2438, 'fi': 2214, 'cs': 2211, 'tl': 1876, 'zh-Hant': 1795, 'az': 1762, 'id': 1727, 'hu': 1714, 'romanization': 1531, 'bs': 1473, 'fa': 1383, 'sk': 1331, 'bg': 853, 'sq': 838, 'et': 708, 'uk': 705, 'zh': 667, 'ms': 646, 'ca': 539, 'lv': 492, 'lt': 450, 'sw': 380, 'is': 331, 'eu': 301, 'th': 301, 'af': 277, 'sl': 277, 'zu': 271, 'mk': 266, 'co': 240, 'ht': 233, 'gl': 230, 'sco': 209, 'la': 175, 'xh': 141, 'eo': 135, 'el': 103, 'yo': 82, 'sn': 80, 'rw': 77, 'ln': 73, 'cy': 70, 'ceb': 69, 'hi': 67, 'wo': 55, 'jw': 48, 'ga': 47, 'sa': 46, 'ak': 46, 'st': 45, 'ne': 44, 'lb': 44, 'uz': 43, 'war': 42, 'mi': 39, 'be': 39, 'rm': 35, 'fo': 34, 'lg': 34, 'gd': 34, 'aa': 29, 'mg': 29, 'so': 28, 'tn': 26, 'sm': 26, 'ig': 26, 'oc': 23, 'ka': 22, 'ny': 21, 'haw': 20, 'ha': 19, 'ia': 19, 'tk': 19, 'ts': 18, 'su': 17, 've': 16, 'mn': 15, 'qu': 15, 'ie': 15, 'mt': 13, 'ku': 13, 'tlh': 12, 'to': 11, 'kha': 11, 'pa': 11, 'crs': 11, 'hy': 11, 'gn': 11, 'bi': 11, 'rn': 10, 'om': 10, 'tt': 9, 'kl': 9, 'br': 9, 'fj': 8, 'fy': 8, 'ss': 8, 'mfe': 7, 'my': 7, 'vo': 6, 'tg': 5, 'bn': 5, 'ta': 5, 'km': 4, 'gv': 4, 'ky': 4, 'hmn': 3, 'kk': 3, 'si': 2, 'nso': 2, 'ay': 2, 'ur': 2, 'na': 2, 'kn': 1, 'nr': 1, 'ik': 1, 'iu': 1, 'yi': 1})\n"
     ]
    }
   ],
   "source": [
    "print(\n",
    "    \"total duration khr\",\n",
    "    sum(m[\"duration\"] for m in high_cer_train_info_2) / 3600000,\n",
    "    min(m[\"duration\"] for m in high_cer_train_info_2),\n",
    "    max(m[\"duration\"] for m in high_cer_train_info_2),\n",
    "    min(len(m[\"text\"]) for m in high_cer_train_info_2),\n",
    "    max(len(m[\"text\"]) for m in high_cer_train_info_2),\n",
    ")\n",
    "print(Counter(m[\"lang\"] for m in high_cer_train_info_2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "063513d5-ddf4-47c5-aa3c-6382d63f35e2",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-14T16:00:32.470361Z",
     "iopub.status.busy": "2025-01-14T16:00:32.469783Z",
     "iopub.status.idle": "2025-01-14T16:00:32.699485Z",
     "shell.execute_reply": "2025-01-14T16:00:32.698913Z",
     "shell.execute_reply.started": "2025-01-14T16:00:32.470342Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3870\n",
      "3000\n"
     ]
    }
   ],
   "source": [
    "selected_multi_validation_set = read_jsonl(\n",
    "    \"/home/tony/Data/Hoot/v4_multi_validation_set.json\"\n",
    ")\n",
    "print(len(selected_multi_validation_set))\n",
    "selected_en_validation_set = read_jsonl(\n",
    "    \"/home/tony/Data/Hoot/v4_en_validation_set.json\"\n",
    ")\n",
    "print(len(selected_en_validation_set))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "26c6eac1-736a-4f93-9a19-40e1c0152dc5",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-14T16:00:33.396095Z",
     "iopub.status.busy": "2025-01-14T16:00:33.395767Z",
     "iopub.status.idle": "2025-01-14T16:00:33.400562Z",
     "shell.execute_reply": "2025-01-14T16:00:33.400011Z",
     "shell.execute_reply.started": "2025-01-14T16:00:33.396079Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6870\n"
     ]
    }
   ],
   "source": [
    "selected_validation_set_ids = set(x[\"id\"] for x in selected_multi_validation_set).union(\n",
    "    set(x[\"id\"] for x in selected_en_validation_set)\n",
    ")\n",
    "print(len(selected_validation_set_ids))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "5492f723-0ac1-45bd-8539-bfd093a5335b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-14T15:59:56.367179Z",
     "iopub.status.busy": "2025-01-14T15:59:56.366634Z",
     "iopub.status.idle": "2025-01-14T15:59:57.063118Z",
     "shell.execute_reply": "2025-01-14T15:59:57.062469Z",
     "shell.execute_reply.started": "2025-01-14T15:59:56.367125Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "895906\n",
      "889036\n"
     ]
    }
   ],
   "source": [
    "print(len(high_cer_train_info_2))\n",
    "high_cer_train_info_2 = [\n",
    "    x for x in high_cer_train_info_2 if x[\"id\"] not in selected_validation_set_ids\n",
    "]\n",
    "print(len(high_cer_train_info_2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "90466614",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-15T18:52:12.098221Z",
     "start_time": "2024-01-15T18:52:11.939584Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T15:44:14.123946Z",
     "iopub.status.busy": "2025-01-14T15:44:14.123554Z",
     "iopub.status.idle": "2025-01-14T15:44:14.517921Z",
     "shell.execute_reply": "2025-01-14T15:44:14.517273Z",
     "shell.execute_reply.started": "2025-01-14T15:44:14.123925Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "885036 4000\n"
     ]
    }
   ],
   "source": [
    "cutoff = -4000\n",
    "random.shuffle(high_cer_train_info_2)\n",
    "high_cer_train_info_2, high_cer_test_info_2 = (\n",
    "    high_cer_train_info_2[:cutoff],\n",
    "    high_cer_train_info_2[cutoff:],\n",
    ")\n",
    "print(len(high_cer_train_info_2), len(high_cer_test_info_2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "74ef0ed9",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-15T18:52:34.087188Z",
     "start_time": "2024-01-15T18:52:23.399643Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T15:44:18.027449Z",
     "iopub.status.busy": "2025-01-14T15:44:18.027087Z",
     "iopub.status.idle": "2025-01-14T15:44:53.231893Z",
     "shell.execute_reply": "2025-01-14T15:44:53.231193Z",
     "shell.execute_reply.started": "2025-01-14T15:44:18.027431Z"
    }
   },
   "outputs": [],
   "source": [
    "# with open(\"/home/tony/Data/Hoot/v4_t1_cer_50_long_train.json\", \"w\") as fp:\n",
    "#     for l in high_cer_train_info_2:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write('\\n')\n",
    "# with open(\"/home/tony/Data/Hoot/v4_t1_cer_50_long_test.json\", \"w\") as fp:\n",
    "#     for l in high_cer_test_info_2:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write('\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "61409fbd",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-15T18:52:34.091372Z",
     "start_time": "2024-01-15T18:52:34.089444Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T01:48:35.505118Z",
     "iopub.status.busy": "2025-01-14T01:48:35.504994Z",
     "iopub.status.idle": "2025-01-14T01:48:35.539824Z",
     "shell.execute_reply": "2025-01-14T01:48:35.539404Z",
     "shell.execute_reply.started": "2025-01-14T01:48:35.505106Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Done\n"
     ]
    }
   ],
   "source": [
    "print(\"Done\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "535130a0",
   "metadata": {},
   "source": [
    "# Curate a seperate list of long audios, for just evaluation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "13fa3abf",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-11T19:10:11.366040Z",
     "start_time": "2024-01-11T19:10:10.100230Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T16:00:15.047699Z",
     "iopub.status.busy": "2025-01-14T16:00:15.047401Z",
     "iopub.status.idle": "2025-01-14T16:00:17.115621Z",
     "shell.execute_reply": "2025-01-14T16:00:17.114871Z",
     "shell.execute_reply.started": "2025-01-14T16:00:15.047681Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "855934\n"
     ]
    }
   ],
   "source": [
    "high_cer_train_info_2_long = []\n",
    "for info in train_info:\n",
    "    if info[\"id\"] in high_cer_infos_2 and info[\"duration\"] < 300:\n",
    "        high_cer_train_info_2_long.append(info)\n",
    "print(len(high_cer_train_info_2_long))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "5c7f0742",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-11T19:10:11.424285Z",
     "start_time": "2024-01-11T19:10:11.367473Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T16:00:17.116825Z",
     "iopub.status.busy": "2025-01-14T16:00:17.116651Z",
     "iopub.status.idle": "2025-01-14T16:00:17.480047Z",
     "shell.execute_reply": "2025-01-14T16:00:17.479393Z",
     "shell.execute_reply.started": "2025-01-14T16:00:17.116808Z"
    }
   },
   "outputs": [],
   "source": [
    "random.shuffle(high_cer_train_info_2_long)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "cfbf0a99",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-11T19:10:12.582481Z",
     "start_time": "2024-01-11T19:10:12.457526Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T16:00:17.480831Z",
     "iopub.status.busy": "2025-01-14T16:00:17.480681Z",
     "iopub.status.idle": "2025-01-14T16:00:18.515817Z",
     "shell.execute_reply": "2025-01-14T16:00:18.515175Z",
     "shell.execute_reply.started": "2025-01-14T16:00:17.480815Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3870\n"
     ]
    }
   ],
   "source": [
    "selected_validation_set = []\n",
    "c = Counter()\n",
    "for m in high_cer_train_info_2_long:\n",
    "    if c[m[\"lang\"]] < min(len(lang_cers.get(m[\"lang\"], [])) // 4, 50):\n",
    "        selected_validation_set.append(m)\n",
    "        c[m[\"lang\"]] += 1\n",
    "print(len(selected_validation_set))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "d3c6afd4-c44a-495d-b311-bb8042a9bfe1",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-15T01:23:44.489159Z",
     "iopub.status.busy": "2025-01-15T01:23:44.488728Z",
     "iopub.status.idle": "2025-01-15T01:23:44.789090Z",
     "shell.execute_reply": "2025-01-15T01:23:44.788560Z",
     "shell.execute_reply.started": "2025-01-15T01:23:44.489140Z"
    }
   },
   "outputs": [],
   "source": [
    "# with open(\"/home/tony/Data/Hoot/v4_multi_validation_set.json\", \"w\") as fp:\n",
    "#     for l in selected_validation_set:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write(\"\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "f8d88911",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-01-11T19:10:43.816910Z",
     "start_time": "2024-01-11T19:10:43.660712Z"
    },
    "execution": {
     "iopub.execute_input": "2025-01-14T16:00:18.763232Z",
     "iopub.status.busy": "2025-01-14T16:00:18.762767Z",
     "iopub.status.idle": "2025-01-14T16:00:19.678028Z",
     "shell.execute_reply": "2025-01-14T16:00:19.677390Z",
     "shell.execute_reply.started": "2025-01-14T16:00:18.763214Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3000\n"
     ]
    }
   ],
   "source": [
    "selected_validation_set_ids = set(x[\"id\"] for x in selected_validation_set)\n",
    "selected_en_validation_set = []\n",
    "c = Counter()\n",
    "for m in high_cer_train_info_2_long:\n",
    "    if (\n",
    "        m[\"lang\"] == \"en\"\n",
    "        and m[\"id\"] not in selected_validation_set_ids\n",
    "        and c[m[\"lang\"]] < 3000\n",
    "    ):\n",
    "        selected_en_validation_set.append(m)\n",
    "        c[m[\"lang\"]] += 1\n",
    "print(len(selected_en_validation_set))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "c1e7ac97",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-01-15T01:23:52.018137Z",
     "iopub.status.busy": "2025-01-15T01:23:52.017514Z",
     "iopub.status.idle": "2025-01-15T01:23:52.217614Z",
     "shell.execute_reply": "2025-01-15T01:23:52.217124Z",
     "shell.execute_reply.started": "2025-01-15T01:23:52.018119Z"
    }
   },
   "outputs": [],
   "source": [
    "# with open(\"/home/tony/Data/Hoot/v4_en_validation_set.json\", \"w\") as fp:\n",
    "#     for l in selected_en_validation_set:\n",
    "#         json.dump(l, fp, ensure_ascii=True)\n",
    "#         fp.write(\"\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2854610a",
   "metadata": {},
   "source": [
    "# Validations and checks"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "a0e31899-aeca-457d-bafa-c313f22180b7",
   "metadata": {},
   "outputs": [],
   "source": [
    "train_infos = read_jsonl(\"/home/tony/Data/Hoot/v4_t1_cer_50_long_train.json\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "094c8548",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "882484\n"
     ]
    }
   ],
   "source": [
    "print(len(train_infos))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "df1ffb98",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "399\n",
      "{'audio_filepath': '/app/suno/data/hoot/audios/genius/RX2YPLZfGaI.mp3', 'duration': 225, 'text': 'бля я не стремился быть чистеньким я не стремился быть нужным вам все что хотел это высверлить свое имя в их в головах загонялся писал заливался искал себе выход из ёбаной жизни амебы город за городом стопка за стопкой все льется рекой из окна небоскреба окурком сигары размажь себя вся твоя жизнь жидкая кашица пятиэтажная жидкая кашица полная злости и полная зависти нахуй всех нахуй всех нахуй всех нахуй всех нахуй всех нахуй всех нахуй всех нахуй всех', 'lyrics': '[Стих: СД]\\nБля...\\nЯ не стремился быть чистеньким, я не стремился быть нужным вам\\nВсе что хотел это высверлить,\\u2005свое\\u2005имя в их\\u2005в головах\\nЗагонялся, писал\\nЗаливался, искал себе выход\\u2005из ёбаной жизни амебы\\nГород за городом стопка за стопкой\\nВсе льется рекой из окна небоскреба\\nОкурком сигары размажь себя, вся твоя жизнь жидкая кашица Пятиэтажная жидкая кашица, полная злости и полная зависти\\nНахуй всех, нахуй всех\\nНахуй всех, нахуй всех\\nНахуй всех, нахуй всех\\nНахуй всех, нахуй всех', 'lang': 'ru', 'id': 'e16485e4-2241-45c9-b73d-9ec4782c23cf', 'genius_views': 784, 'youtube_views': 560}\n",
      "{'audio_filepath': '/app/suno/data/hoot/audios/genius/jSJmaKevLDY.mp3', 'duration': 219, 'text': 'lá dentro das trevas um homem que foge órfão da graça órfão de deus deus que me ajude não vou descansar ele há de ser meu ele há de ser meu na escuridão ele vai enquanto eu sigo o senhor quem caminha do lado dos justos terá o seu valor e quem cair o inferno verá terá o horror ah as estrelas são são incontáveis enchem as trevas de ordem e luz e sentinelas são mudas e sós céu que a todos conduz deus que a todos conduz e não se soltam do céu e nunca vão se soltar girando e girando e voltando outra vez para o mesmo lugar pois quem cair o inferno verá terá o horror e assim há de ser e assim foi escrito nas estrelas e páginas e quem for fraco e sair da luz irá pagar deus me dê forças hei de buscá lo há de ser meu eu não vou ceder eu juro na lei das estrelas do céu o inspetor se acha muito mas quem manda aqui sou eu meu teatro nunca fecha se a cortina não desceu sou gavroche creia em mim eu tô sempre aqui assim', 'lyrics': '[JAVERT]\\nLá, dentro das trevas\\nUm homem que foge\\nÓrfão da graça, órfão de Deus\\nDeus que me ajude\\nNão vou descansar\\nEle há de ser meu\\nEle há de ser meu\\n\\nNa escuridão, ele vai\\nEnquanto eu sigo o senhor\\nQuem caminha do lado dos justos\\nTerá o seu valor\\nE quem cair o inferno verá\\nTerá o horror\\nAh, as estrelas são\\nSão incontáveis\\nEnchem as trevas de ordem e luz\\nE sentinelas são\\nMudas e sós\\nCéu que a todos conduz\\nDeus que a todos conduz\\n\\nE não se soltam do céu\\nE nunca vão se soltar\\nGirando e girando e voltando outra vez\\nPara o mesmo lugar\\nPois quem cair o inferno verá\\nTerá o horror\\n\\nE assim há de ser\\nE assim foi escrito\\nNas estrelas e páginas\\nE quem for fraco e sair da luz\\nIrá pagar\\n\\nDeus me dê forças\\nHei de buscá-lo\\nHá de ser meu\\nEu não vou ceder\\nEu juro na lei\\nDas estrelas do céu\\n\\n\\n\\n[GAVROCHE]\\nO inspetor se acha muito\\nMas quem manda aqui sou eu\\nMeu teatro nunca fecha\\nSe a cortina não desceu\\nSou Gavroche, creia em mim\\nEu tô sempre aqui assim', 'lang': 'pt', 'id': '002e40aa-6183-40a1-b135-c3989403c77e', 'genius_views': 798, 'youtube_views': 83291}\n",
      "{'audio_filepath': '/app/suno/data/hoot/audios/genius/W9aOK2v5s5s.mp3', 'duration': 193, 'text': \"your sundress and bleach blonde hair adolescent vacant stare my peace of mind cure the thoughts swimming in my head imprompt decisions late nights in love forgone conclusions tell me what you're thinking of just leave me out to dry been lost here for the longest time i can't even win i'll just breathe you in it's the end of an era it's a fall from grace you said you needed time you said you needed space and no simple lie it's wishful thinking you and i felt like dreaming but you left me out to dry i've been living off of borrowed time i can't even win i'll just breathe you in it's the end of an era it's a fall from grace you said you needed time you said you needed space you can leave if you wanna someone will take my place so in the meantime can we fade away i used to know who you were now i know who you're not forgetting all that i learned such a freeing thought do i miss you when i have nothing else can i win when i'm losing myself was what we had even real so i keep looking back and i refuse to believe that it's the end of an era it's a fall from grace you said you needed time you said you needed space you can leave if you wanna someone will take my place so in the meantime can we fade away can we fade away\", 'lyrics': \"[Verse 1]\\nYour sundress and bleach blonde hair\\nAdolescent vacant stare\\nMy peace of mind\\nCure the thoughts swimming in my head\\nImprompt decisions\\nLate nights in love\\nForgone conclusions\\nTell me what you're thinking of\\n\\n[Pre-Chorus]\\nJust leave me out to dry\\nBeen lost here for the longest time\\nI can't even win\\nI'll just breathe you in\\n[Chorus]\\nIt's the end of an era\\nIt's a fall from grace\\nYou said you needed time\\nYou said you needed space\\n\\n[Verse 2]\\nAnd no simple lie\\nIt's wishful thinking\\nYou and I\\nFelt like dreaming\\n\\n[Pre-Chorus]\\nBut you left me out to dry\\nI've been living off of borrowed time\\nI can't even win\\nI'll just breathe you in\\n\\n[Chorus]\\nIt's the end of an era\\nIt's a fall from grace\\nYou said you needed time\\nYou said you needed space\\nYou can leave if you wanna\\nSomeone will take my place\\nSo in the meantime\\nCan we fade away?\\n\\n\\n[Bridge]\\nI used to know who you were\\nNow I know who you're not\\nForgetting all that I learned\\nSuch a freeing thought\\nDo I miss you when I have nothing else?\\nCan I win when I'm losing myself?\\nWas what we had even real?\\nSo I keep looking back\\nAnd I refuse to believe that...\\n\\n[Chorus]\\nIt's the end of an era\\nIt's a fall from grace\\nYou said you needed time\\nYou said you needed space\\nYou can leave if you wanna\\nSomeone will take my place\\nSo in the meantime\\nCan we fade away?\\nCan we fade away?\", 'lang': 'en', 'id': '024b610a-164d-4f00-b63d-5ea6be4434d9', 'genius_views': 1375, 'youtube_views': 46811}\n",
      "{'audio_filepath': '/app/suno/data/hoot/audios/genius/qEN97bJxulM.mp3', 'duration': 213, 'text': 'refrão sei que tu quer me dar muito amor e prazer dividir uma casinha e fazer um bebê se tu quiser me dar vou te satisfazer então promete ser minha que eu me entrego a você eu e ela os altos e baixos nós sustenta ela pequena maleável eu quase com ela é marrenta eu vou na dela ela me atenta e aqui dentro o bagulho esquenta ela senta em câmera lenta não vai faltar língua vai achar que eu sou poliglota essa roupa tá boa em você mas pelada tu é mais gostosa fiquei a mercê dessa moça mas sem pressa vou chegar dessa bossa que ela esboça com esse jogo de olhar te sinto recito repito esse rito não é difícil eu sou perito é instinto quando te excito se eu beber mais uma dose eu não sei qual vai ser o fim foi só falar levantou e pegou a garrafa de gim olhou pra mim e encheu meu copo perguntei quer ser feliz ela me disse topo vou te levar prum estrelas uisque arregado mentira vou fazer tu ver estrelas no meu quarto condição não tem mas gata curte o momento sei que tá faltando a cota mas tá sobrando talento eu e você o bagulho é doido nem a sombra acompanha é o magrinho malandreado e a gostosa piranha refrão sei que tu quer me dar muito amor e prazer dividir uma casinha e fazer um bebê se tu quiser me dar vou te satisfazer então promete ser minha que eu me entrego a você quando eu tô duro ela fortalece no din quando eu tô duro ela vem sentar em mim algo me diz que você foi feita pra mim tamo juntão bebê é nós até depois do fim ligação de alma inexplicável nosso vínculo vida me dá porrada mas você é o meu estímulo e eu que não sei nadar no teu mar eu mergulho nossa história é de outras vidas esse é mais um capítulo então vem vamos escrever sem pensar no amanhã a manha que só você tem pique mocinha e vilã tipo doce como hortelã e bolada que nem o islã só você me deixa louco e mantém minha mente sã se tu é bonnie e eu sou clyde tu é pé no chão e eu sou viagem é sensatez ato pensado e eu sou inconsequente selvagem eu sou movido a sacanagem e tu chega na carruagem salto alto e maquiagem refrão sei que tu quer me dar muito amor e prazer dividir uma casinha e fazer um bebê se tu quiser me dar vou te satisfazer então promete ser minha que eu me entrego a você', 'lyrics': 'Refrão\\n(Ian Matheus)\\nSei que tu quer me dar muito amor e prazer\\nDividir uma casinha e fazer um bebê\\n\\nSe tu quiser me dar, vou te satisfazer\\nEntão promete ser minha que eu me entrego a você\\n\\n\\n(Tchelo)\\nEu e ela, os altos e baixos nós sustenta\\nEla pequena maleável, eu quase com 1,90\\nEla é marrenta, eu vou na dela, ela me atenta\\nE aqui dentro o bagulho esquenta, ela senta em câmera lenta\\nNão vai faltar língua, vai achar que eu sou poliglota\\nEssa roupa tá boa em você, mas pelada tu é mais gostosa\\nFiquei a mercê dessa moça, mas sem pressa vou chegar\\nDessa bossa que ela esboça com esse jogo de olhar\\n\\nTe sinto, recito, repito esse rito\\nNão é difícil, eu sou perito, é instinto quando te excito\\nSe eu beber mais uma dose eu não sei qual vai ser o fim\\nFoi só falar, levantou e pegou a garrafa de gim\\n\\nOlhou pra mim e encheu meu copo\\nPerguntei \"quer ser feliz?\" ela me disse \"topo\"\\nVou te levar prum 5 estrelas, uisque arregado\\nMentira, vou fazer tu ver estrelas no meu quarto\\n\\nCondição não tem, mas gata curte o momento\\nSei que tá faltando a cota, mas tá sobrando talento\\nEu e você o bagulho é doido, nem a sombra acompanha\\nÉ o magrinho malandreado e a gostosa piranha\\n\\n\\nRefrão\\n(Ian Matheus)\\nSei que tu quer me dar muito amor e prazer\\nDividir uma casinha e fazer um bebê\\n\\n\\nSe tu quiser me dar, vou te satisfazer\\nEntão promete ser minha que eu me entrego a você\\n\\n\\n(Tchelo)\\nQuando eu tô duro ela fortalece no din\\nQuando eu tô duro ela vem sentar em mim\\nAlgo me diz que você foi feita pra mim\\nTamo juntão bebê, é nós até depois do fim\\n\\nLigação de alma, inexplicável nosso vínculo\\nVida me dá porrada, mas você é o meu estímulo\\nE eu que não sei nadar, no teu mar eu mergulho\\nNossa história é de outras vidas, esse é mais um capítulo (então vem)\\n\\nVamos escrever sem pensar no amanhã\\nA manha que só você tem, pique mocinha e vilã\\nTipo doce como hortelã e bolada que nem o islã\\nSó você me deixa louco e mantém minha mente sã\\n\\nSe tu é Bonnie e eu sou Clyde, tu é pé no chão e eu sou viagem\\nÉ sensatez, ato pensado e eu sou inconsequente, selvagem\\nEu sou movido a sacanagem e tu chega na carruagem, salto alto e maquiagem\\n\\n\\nRefrão\\n(Ian Matheus)\\nSei que tu quer me dar muito amor e prazer\\nDividir uma casinha e fazer um bebê\\n\\n\\nSe tu quiser me dar, vou te satisfazer\\nEntão promete ser minha que eu me entrego a você', 'lang': 'pt', 'id': '94a15a27-0a3b-4368-b5e2-a46de7275799', 'genius_views': 24, 'youtube_views': 1223}\n",
      "{'audio_filepath': '/app/suno/data/hoot/audios/genius/JSHq1dLEn6I.mp3', 'duration': 202, 'text': 'neste lugar colecionei todas as coisas que eu encontrei quem olha pode pensar que eu conquistei o que eu quis tudo o que achei dentro do mar é um tesouro com algo a contar sim ela é feliz tenho coisas por todos os cantos traquitanas e trecos demais eu parei de contar tenho tantos e daí tanto faz quero mais quero saber como os homens são quero aprender como eles dançam como é pular num só como eles dizem ah pé caudas são feitas só pra nadar mas quem tem pernas caminha dança e sempre corre atrás do que o coração quer onde tem sol onde tem ar onde é normal correr e dançar sinto que lá posso encontrar o meu lugar quero saber como é viver onde o sol brilha topo pagar o que custar pra acontecer lá pode crer vão me entender lá um pai sabe ver que a filha é ousada e cansada de obedecer lá eu vou saber tudo o que eu quiser minhas perguntas terão respostas como o fogo que traz calor traz também dor faço o que for pra me tornar parte do mundo acima do mar quem sabe lá posso encontrar o meu lugar', 'lyrics': '[ARIEL]\\nNeste lugar colecionei\\nTodas as coisas que eu encontrei\\nQuem olha pode pensar\\nQue eu conquistei o que eu quis\\n\\nTudo o que achei dentro do mar\\nÉ um tesouro com algo a contar\\nQuem olha em volta supõe:\\n\"Sim, ela é feliz!\"\\nTenho coisas por todos os cantos\\nTraquitanas e trecos demais\\nEu parei de contar, tenho tantos\\nE daí? Tanto faz, quero mais!\\n\\nQuero saber como os homens são\\nQuero aprender como eles dançam\\nComo é pular num só…\\nComo eles dizem?\\nAh, pé!\\n\\nCaudas são feitas só pra nadar\\nMas quem tem pernas caminha, dança\\nE sempre corre atrás\\nDo que o coração quer\\n\\nOnde tem sol\\nOnde tem ar\\nOnde é normal\\nCorrer e dançar\\nSinto que lá posso encontrar\\nO meu lugar\\n\\nQuero saber como é viver\\nOnde o sol brilha\\nTopo pagar o que custar pra acontecer\\n\\n\\nLá, pode crer, vão me entender\\nLá um pai sabe ver que a filha\\nÉ ousada e cansada de obedecer\\n\\nLá eu vou saber tudo o que eu quiser\\nMinhas perguntas terão respostas\\n\\nComo o fogo\\nQue traz calor\\nTraz também dor\\n\\nFaço o que for pra me tornar\\nParte do mundo acima do mar\\n\\nQuem sabe lá\\nPosso encontrar\\nO meu lugar', 'lang': 'pt', 'id': 'eb71c444-a557-41ab-b4e3-9de533a19746', 'genius_views': 113, 'youtube_views': 258703}\n",
      "{'audio_filepath': '/app/suno/data/hoot/audios/genius/-JouZ2iUSLI.mp3', 'duration': 197, 'text': 'podziurawiłem parę nike czasem tak się gubię mordo że się kurwa nie poznaję całe życie na przypale to przeze mnie bo policja nie próbuje mnie odnaleźć piszę to kiedy mam fazę potem wrzucamy do sieci i czekamy co się stanie ziomek mówi mi że siedzi wiem że wszyscy tu koledzy już czekają co się stanie wszyscy mamy chorą banie ale co trzeba jakoś iść żeby być tu myślę o tym kiedy palę przy stoliku myślę o tym kiedy wracam do warszawy ryju całe noce siedzę w pracy tamta miała być ostatnio z takim hajsem iść w pizdu nie wiesz co to dla mnie znaczy ale nigdy niе zostanę na chodniku czy na winklu wypuszczam dym chmura wygląda jak my kolejna jesień przychodzi razеm z nią zupełnie mordo nie dziś ona mi mówi żebym w końcu żył i chyba rozumie jak nikt ja sam nie rozumiem jak wszyscy ja sam nie rozumiem jak nikt wypuszczam dym chmura wygląda jak my kolejna jesień przychodzi razem z nią zupełnie mordo nie dziś ona mi mówi żebym w końcu żył i chyba rozumie jak nikt ja sam nie rozumiem jak wszyscy ja sam nie rozumiem jak ty gdzie te lepsze dni powiedziałem parę rzeczy które nie znaczyły nic obiecałem parę rzeczy które potem miałem w chuju i do dzisiaj jest mi za to wstyd wszystko dookoła mówi idź wszystko mówi mi bądźmy dorośli stawiam flachę na stolik jak przyjmuje gości ciekawe co będę pamiętał z tej nocy zajebane ale jestem mam stówę w kieszeni nie setkę mam lufę w kieszeni i cichą nadzieję że przede mną tylko najlepsze nie wiem gdzie moje miejsce ale kiedyś tam będę studiuje wzrokiem przestrzeń ciekawe co życie przyniesie wypuszczam dym chmura wygląda jak my kolejna jesień przychodzi razem z nią zupełnie mordo nie dziś ona mi mówi żebym w końcu żył i chyba rozumie jak nikt ja sam nie rozumiem jak wszyscy ja sam nie rozumiem jak nikt wypuszczam dym chmura wygląda jak my kolejna jesień przychodzi razem z nią zupełnie mordo nie dziś ona mi mówi żebym w końcu żył i chyba rozumie jak nikt ja sam nie rozumiem jak wszyscy ja sam nie rozumiem jak ty', 'lyrics': '[Zwrotka 1]\\nPodziurawiłem parę Nike\\nCzasem tak się gubię mordo\\nŻe się kurwa nie poznaję\\nCałe życie na przypale\\nTo przeze mnie\\nBo policja nie próbuje, mnie odnaleźć\\nPiszę to kiedy mam fazę\\nPotem wrzucamy do sieci, i czekamy co się stanie\\nZiomek mówi mi, że siedzi\\nWiem, że wszyscy tu koledzy już czekają co się stanie\\nWszyscy mamy chorą banie, ale co\\nTrzeba jakoś iść, żeby być tu\\nMyślę o tym, kiedy palę przy stoliku\\nMyślę o tym, kiedy wracam do Warszawy, ryju\\nCałe noce siedzę w pracy\\nTamta miała być ostatnio\\nZ takim hajsem iść w pizdu\\nNie wiesz co to dla mnie znaczy\\nAle nigdy niе zostanę na chodniku, czy na winklu\\n\\n[Refren]\\nWypuszczam dym, chmura wygląda jak my\\nKolejna jesień przychodzi, razеm z nią zupełnie\\nMordo nie dziś\\nOna mi mówi, żebym w końcu żył\\nI chyba rozumie jak nikt\\nJa sam nie rozumiem jak wszyscy\\nJa sam nie rozumiem jak (nikt)\\nWypuszczam dym, chmura wygląda jak my\\nKolejna jesień przychodzi, razem z nią zupełnie\\nMordo nie dziś\\nOna mi mówi, żebym w końcu żył\\nI chyba rozumie jak nikt\\nJa sam nie rozumiem jak wszyscy\\nJa sam nie rozumiem jak ty\\n\\n\\n[Zwrotka 2]\\nGdzie te lepsze dni?\\nPowiedziałem parę rzeczy\\nKtóre nie znaczyły nic\\nObiecałem parę rzeczy\\nKtóre potem miałem w chuju\\nI do dzisiaj jest mi za to wstyd\\nWszystko dookoła mówi idź\\nWszystko mówi mi, bądźmy dorośli\\nStawiam flachę na stolik, jak przyjmuje gości\\nCiekawe co będę pamiętał z tej nocy\\nZajebane, ale jestem\\nMam stówę w kieszeni, nie setkę\\nMam lufę w kieszeni, i cichą nadzieję\\nŻe przede mną tylko najlepsze\\nNie wiem gdzie moje miejsce\\nAle kiedyś tam będę\\nStudiuje wzrokiem przestrzeń\\nCiekawe co życie przyniesie\\n\\n\\n\\n[Refren]\\nWypuszczam dym, chmura wygląda jak my\\nKolejna jesień przychodzi, razem z nią zupełnie\\nMordo nie dziś\\nOna mi mówi, żebym w końcu żył\\nI chyba rozumie jak nikt\\nJa sam nie rozumiem jak wszyscy\\nJa sam nie rozumiem jak (nikt)\\nWypuszczam dym, chmura wygląda jak my\\nKolejna jesień przychodzi, razem z nią zupełnie\\nMordo nie dziś\\nOna mi mówi, żebym w końcu żył\\nI chyba rozumie jak nikt\\nJa sam nie rozumiem jak wszyscy\\nJa sam nie rozumiem jak ty', 'lang': 'pl', 'id': '981dfdff-ffbf-4f72-80fa-758e64470ff0', 'genius_views': 33, 'youtube_views': 23853}\n",
      "{'audio_filepath': '/app/suno/data/hoot/audios/genius/JPDaGyAvkOM.mp3', 'duration': 292, 'text': \"no wait before coppa strikes you need to make another cover of megalovania i'm talking like this we need a proper lyrical adaptation of this okay let me just follow that link real quick hmm this might be tricky but i think i can make something out of this\", 'lyrics': \"[Intro]\\nNo, wait\\nBefore coppa strikes, you NEED to make another cover of Megalovania\\nI'm talking like this\\nWe need a proper lyrical adaptation of this\\nOkay, let me just follow that link real quick\\nHmm, this might be tricky but I think I can make something out of this\", 'lang': 'en', 'id': '282aff77-4967-464f-bb20-2519c098df97', 'genius_views': 83, 'youtube_views': 92126}\n",
      "{'audio_filepath': '/app/suno/data/hoot/audios/genius/M90sp9OpSFw.mp3', 'duration': 285, 'text': \"okay dann battlen wir platz aus grinchi wenn das hier mal kein fest wird ich gehör' ins finale und du bist auch nicht zurecht hier konstante leistung in den battles mein freund du hast in vier battles dreimal auf die fresse bekomm'n\", 'lyrics': \"[Part]\\nOkay, dann battlen wir Platz 3 aus Grinchi, wenn das hier mal kein Fest wird\\nIch gehör' ins Finale und du bist auch nicht zurecht hier\\nKonstante Leistung in den Battles, mein Freund\\nDu hast in vier Battles dreimal auf die Fresse bekomm'n\", 'lang': 'de', 'id': '221e7f8d-5773-4f13-9da4-71f1f24a8c4a', 'genius_views': 427, 'youtube_views': 219192}\n",
      "{'audio_filepath': '/app/suno/data/hoot/audios/genius/xGtgaOJ6lo4.mp3', 'duration': 207, 'text': \"tu tá me diminuindo tu não soma assim você sempre me diz não e eu sou mais sim eu querendo falar de amor mas eu não sou marcinho eu disse para de fumar e ela disse só um macinho e ela me transformou no seu cigarro me usou até que eu virasse fumaça e eu que já não tinha nenhum filtro fui nos levando direto pra essa desgraça e a gente pode ser o que a gente quer quando mais novo sonhava em ser astronauta e como cê me levava pra outro mundo esse realizar de sonho ainda vai me fazer falta e eu te transformei na minha bebida te bebi até perder todos reflexos eu que só dizia coisas sem sentido fiquei só pra contar essa história sem nexo e a gente pode ser o que gente quer quando mais nova sonhava em ser bailarina como eu sempre dancei conforme a música ainda posso realizar todos esses teus sonhos mina ainda faço teu café bem forte com muito açúcar dessa vez chego mais cedo eu tô perdendo na sinuca cansei de ver teu choro virar maço de malboro depois da última briga quando eu vi tava no soro linda bailarina eu sei seguir teus passos sabe que eu não 'cinto' usando um cadarço vai ficar redondo feito um compasso conheço os seus limites por isso ultrapasso eu conheço seus limites por isso ultrapasso por isso ultrapasso eu não cinto usando cadarço conheço os limites por isso ultrapasso por isso ultrapasso e ela vem com carinho e eu agi igual um calo não sei porque mas sempre que tem que falar me calo o menos dela sempre mais e o meu mais sempre menos quis transformar minha loucura nos seus dias amenos ela as vezes ta que nem dalit cheia de não me toque repetido eu sou seu card vê se não me troque a minha vida é toda torta e ela tem toque as vezes me enche tanto me sinto bangkok falei que orgulho é opção ela diz que eu sou doente falei se orgulho é solução saí pra esfriar a mente menino prepotente já dizia minha coroa a vida é tão simples e nós que complica atoa de joão de barro à beija flor nós fomos papagaio eu sempre tinha que repetir e tu falava pra caralho já cansei de c'est la vie enquanto isso eu tô aqui não me apegando em crenças só pensando se ela ouvir se não surtir efeito assim eu me calo mas se fizer efeito vai ser igual a falta do roberto carlos e eu vou ser rei igual roberto carlos eu vou ser rei eu vou ser rei refrão então me diz quem é você onde tu tá agora o que tu tá fazendo essa hora a mina que eu conheci dizia que ela não chora me diz cadê você ou melhor quem você é agora o que tu tá fazendo essa hora a mina que eu conheci dizia que ela não chora a mina que eu conheci dizia que ela não chora o que tu tá fazendo essa hora quem você é agora a mina que eu conheci dizia que ela não chora\", 'lyrics': '(Gudi Tupa)\\nTu tá me diminuindo, tu não soma assim\\nVocê sempre me diz não e eu sou mais sim\\nEu querendo falar de amor, mas eu não sou Marcinho\\nEu disse \"para de fumar\" e ela disse \"só um macinho\"\\n\\nE ela me transformou no seu cigarro\\nMe usou até que eu virasse fumaça\\nE eu que já não tinha nenhum filtro\\nFui nos levando direto pra essa desgraça\\nE a gente pode ser o que a gente quer\\nQuando mais novo sonhava em ser astronauta\\nE como cê me levava pra outro mundo\\nEsse realizar de sonho ainda vai me fazer falta\\n\\nE eu te transformei na minha bebida\\nTe bebi até perder todos reflexos\\nEu que só dizia coisas sem sentido\\nFiquei só pra contar essa história sem nexo\\n\\nE a gente pode ser o que gente quer\\nQuando mais nova sonhava em ser bailarina\\nComo eu sempre dancei conforme a música\\nAinda posso realizar todos esses teus sonhos mina\\n\\nAinda faço teu café bem forte\\nCom muito açúcar\\nDessa vez chego mais cedo\\nEu tô perdendo na sinuca\\n\\nCansei de ver teu choro\\nVirar maço de malboro\\nDepois da última briga\\nQuando eu vi tava no soro\\n\\nLinda bailarina, eu sei seguir teus passos\\nSabe que eu não \\'cinto\\' usando um cadarço\\nVai ficar redondo feito um compasso\\nConheço os seus limites por isso ultrapasso\\n\\n\\nEu conheço seus limites por isso ultrapasso\\nPor isso ultrapasso\\nEu não \"cinto\" usando cadarço\\nConheço os limites por isso ultrapasso, por isso ultrapasso\\n\\n\\nE ela vem com carinho e eu agi igual um calo\\nNão sei porque, mas sempre que tem que falar me calo\\nO menos dela sempre mais e o meu mais sempre menos\\nQuis transformar minha loucura nos seus dias amenos\\n\\nEla as vezes ta que nem dalit, cheia de não me toque\\nRepetido eu sou seu card, vê se não me troque\\nA minha vida é toda torta e ela tem toque\\nAs vezes me enche tanto me sinto Bangkok\\n\\nFalei que orgulho é opção\\nEla diz que eu sou doente\\nFalei se orgulho é solução\\nSaí pra esfriar a mente\\n\\nMenino prepotente\\nJá dizia minha coroa\\n\"A vida é tão simples e nós que complica atoa\"\\n\\nDe João de barro à beija flor\\nNós fomos papagaio\\nEu sempre tinha que repetir\\nE tu falava pra caralho\\n\\n\\nJá cansei de C\\'est La Vie\\nEnquanto isso eu tô aqui\\nNão me apegando em crenças\\nSó pensando se ela ouvir\\n\\nSe não surtir efeito assim eu me calo\\nMas se fizer efeito vai ser igual a falta do Roberto Carlos\\nE eu vou ser rei igual Roberto Carlos\\nEu vou ser rei, eu vou ser rei\\n\\n\\nRefrão\\nEntão me diz quem é você, onde tu tá agora?\\nO que tu tá fazendo essa hora?\\nA mina que eu conheci dizia que ela não chora\\n\\nMe diz cadê você? Ou melhor\\nQuem você é agora?\\nO que tu tá fazendo essa hora?\\n\\nA mina que eu conheci dizia que ela não chora\\nA mina que eu conheci dizia que ela não chora\\nO que tu tá fazendo essa hora?\\n\\nQuem você é agora?\\nA mina que eu conheci dizia que ela não chora', 'lang': 'pt', 'id': 'd38c6f50-3f2a-4717-acb3-0f3b9fedb3b9', 'genius_views': 17, 'youtube_views': 1292}\n",
      "{'audio_filepath': '/app/suno/data/hoot/audios/genius/si6wZ00c5yw.mp3', 'duration': 260, 'text': \"i wasn't always like this uncommitted to my embrace but lately i feel like there's nothing else for me these days 'cause everybody's movin' with the seasons while i hold the door for all my demons that i can't resist no i wasn't meant for this so i'm trying to keep my head above the water but the waves bear more than life promised to offer me but maybe someday i'll resurface on my own yeah maybe someday where it hurts is where i'll grow oh tell me someday i won't fall apart like i used to but it's only monday can someday come soon i can never understand every thought inside my head and trying to unravel it was the reason why she left 'cause everybody wants someone to fight for but no one ever stays when they can't afford to rebuild and repair a story not like the fairytales so i'm trying to keep my head above the water but the waves bear more than life promised to offer me but maybe someday i'll resurface on my own yeah maybe someday where it hurts is where i'll grow oh tell me someday i won't fall apart like i used to but it's only monday can someday come soon ooh they make it look so easy to hold the stars maybe i'm too scarred ooh i've tried and tried but how did it get so hard to love my heart but maybe someday i'll resurface on my own yeah maybe someday where it hurts is where i'll grow oh tell me someday i won't fall apart like i used to but it's only monday can someday come soon it's only monday can sunday come soon\", 'lyrics': \"[Verse 1]\\nI wasn't always like this\\nUncommitted to my embrace\\nBut lately, I feel like\\nThere's nothing else for\\u2005me\\u2005these days\\n'Cause everybody's\\u2005movin' with the seasons\\nWhile I hold\\u2005the door for all my demons\\nThat I can't resist\\nNo, I\\u205fwasn't\\u205fmeant\\u205ffor this\\n\\n[Pre-Chorus]\\nSo I'm\\u205ftrying to keep\\u205fmy head above the water\\nBut the waves bear more than life promised to offer me\\n[Chorus]\\nBut maybe someday\\nI'll resurface on my own\\nYeah maybe someday\\nWhere it hurts is where I'll grow\\nOh tell me, someday\\nI won't fall apart like I used to\\nBut it's only Monday\\nCan someday come soon?\\n\\n[Verse 2]\\nI can never understand\\nEvery thought inside my head\\nAnd trying to unravel it\\nWas the reason why she left\\n'Cause everybody wants someone to fight for\\nBut no one ever stays when they can't afford\\nTo rebuild and repair a story not like the fairytales\\n\\n[Pre-Chorus]\\nSo I'm trying to keep my head above the water\\nBut the waves bear more than life promised to offer me\\n\\n[Chorus]\\nBut maybe someday\\nI'll resurface on my own\\nYeah maybe someday\\nWhere it hurts is where I'll grow\\nOh tell me, someday\\nI won't fall apart like I used to\\nBut it's only Monday\\nCan someday come soon?\\n\\n\\n[Bridge]\\nOoh, they make it look so easy\\nTo hold the stars\\nMaybe I'm too scarred\\nOoh, I've tried and tried\\nBut how did it get so hard\\nTo love my heart?\\n\\n[Chorus]\\nBut maybe someday\\nI'll resurface on my own\\nYeah maybe someday\\nWhere it hurts is where I'll grow\\nOh tell me, someday\\nI won't fall apart like I used to\\nBut it's only Monday\\nCan someday come soon?\\n\\n[Outro]\\nIt's only Monday, can Sunday come soon?\", 'lang': 'en', 'id': '82eae2f1-c6a5-47b4-a827-f676b27602f4', 'genius_views': 72, 'youtube_views': 344}\n",
      "{'audio_filepath': '/app/suno/data/hoot/audios/genius/N8rASZnK-ls.mp3', 'duration': 223, 'text': \"las jotas fam diguem que n'és de la teva ubicació on estàs no et veig fa temps diuen que ara tens una casa prop de japó que ja no preferies recordar tots els moments t'enrollo com uramaki que el ritme amb tu no freni estic calculant la money més al sud que nagasaki el ritme vull que em porti celebrem que ja no em porti nena y si tú quieres recorrer tokio en mi carro bebemo' par de trago' de eso' sé que es amargo toy esperando a que te quites el quimono y honey yo te como honey yo sé que si me voy contigo a japón atrás lo dejo to' por esta ocasión baby sé dónde te escondes tú solo dime entonces tu ubicación vamos pal' cuarto pa' prender un philie en la maleta me he traído ese papel de blunt tengo a mis enemigos haciéndose el harakiri porque pa' colmo me tenío que echar una novia recuerda soy el de la foto quien recorría contigo el monte fuji en moto a mí me gustas tú bebé y en eso hago hincapié iré y te buscaré todo ha cambiado no sé cómo estarás yo ahora me siento más centrado no te niego que lo que sentí por ti es fuerte está claro no nos quedemos con lo malo aposté por ti y apostar por ti es como apostar por el jugando a los dados nena me has dejao' tocado mirando hacia mi fin deseando que esto vuelva por sus manos nena y si tú quieres recorrer tokio en mi carro bebemo' par de trago' de eso' sé que es amargo toy esperando a que te quites el quimono y honey yo te como honey yo sé que si me voy contigo a japón atrás lo dejo to' por esta ocasión baby sé dónde te escondes tú solo dime entonces tu ubicación baby que saps que tu ets el yin i jo el yang que jo amb tu nena vull anar a japan i mirar te aquest somriure tots aquests petons al dia fins que ens fem grans i viure en un temple d'amor a mi no em torni a robar el cor perquè tu ets la meva geisha no vull viure amb la mateixa per menjar me el món nena vente al templo templo tú eres del mismo cuento cuento y yo tú samurai seré por ti yo cambiaré bésame y si te busco yo me pierdo en tu cama y luego me reencuentro cuando prendemo' en llamas el techo en la tana trinchao' con kattana y el pecho me lo he pateao' ya ma' diguem que n'és de la teva ubicació on estàs no et veig fa temps diuen que ara tens una casa prop de japó que ja no preferies recordar tots els moments nena y si tú quieres recorrer tokio en mi carro bebemo' par de trago' de eso' sé que es amargo toy esperando a que te quites el quimono y honey yo te como honey yo sé que si me voy contigo a japón atrás lo dejo to' por esta ocasión baby sé dónde te escondes tú solo dime entonces tu ubicación\", 'lyrics': '[Letra de \"Japan\" ft. 31 FAM]\\n\\n[Intro]\\nLas Jotas\\n31 FAM\\n\\n[Verso 1]\\nDiguem que n\\'és de la teva ubicació\\nOn estàs no et veig fa temps\\nDiuen que ara tens una casa prop de Japó\\nQue ja no preferies recordar tots els moments\\nT\\'enrollo com uramaki\\nQue el ritme amb tu no freni\\nEstic calculant la money\\nMés al sud que Nagasaki\\nEl ritme vull que em porti\\nCelebrem que ja no em porti\\n\\n[Estribillo]\\nNena, y si tú quieres recorrer Tokio en mi carro\\nBebemo\\' par de trago\\' de eso\\', sé que es amargo\\nToy esperando a que te quites el Quimono\\nY, honey, yo te como\\n\\n[Post-Estribillo]\\nHoney, yo sé que si me voy contigo a Japón\\nAtrás lo dejo to\\' por esta ocasión\\nBaby, sé dónde te escondes\\nTú solo dime entonces tu ubicación\\n\\n[Verso 2]\\nVamos pal\\' cuarto pa\\' prender un Philie\\nEn la maleta me he traído ese papel de blunt\\nTengo a mis enemigos haciéndose el Harakiri\\nPorque pa\\' colmo me tenío que echar una novia\\n\\nRecuerda, soy el de la foto\\nQuien recorría contigo el monte Fuji en moto\\nA mí me gustas tú, bebé\\nY en eso hago hincapié, iré y te buscaré\\n\\n\\nTodo ha cambiado\\nNo sé cómo estarás, yo ahora me siento más centrado\\nNo te niego que lo que sentí por ti es fuerte, está claro\\nNo nos quedemos con lo malo\\n\\nAposté por ti\\nY apostar por ti es como apostar por el 0 jugando a los dados\\nNena, me has dejao\\' tocado\\nMirando hacia mi fin, deseando que esto vuelva por sus manos\\n\\n[Estribillo]\\nNena, y si tú quieres recorrer Tokio en mi carro\\nBebemo\\' par de trago\\' de eso\\', sé que es amargo\\nToy esperando a que te quites el Quimono\\nY, honey, yo te como\\n\\n[Post-Estribillo]\\nHoney, yo sé que si me voy contigo a Japón\\nAtrás lo dejo to\\' por esta ocasión\\nBaby, sé dónde te escondes\\nTú solo dime entonces tu ubicación\\n\\n[Verso 3]\\nBaby, que saps que tu ets el Yin i jo el Yang\\nQue jo amb tu nena vull anar a Japan\\nI mirar-te aquest somriure tots aquests petons al dia\\nFins que ens fem grans\\n\\n\\nI viure en un temple d\\'amor\\nA mi no em torni a robar el cor\\nPerquè tu ets la meva Geisha\\nNo vull viure amb la mateixa per menjar-me el món\\n\\nNena, vente al templo, templo\\nTú eres del mismo cuento, cuento\\nY yo, tú samurai seré\\nPor ti yo cambiaré\\n\\nBésame, y si te busco, yo me pierdo en tu cama\\nY luego me reencuentro cuando prendemo\\' en llamas\\nEl techo en la tana, trinchao\\' con kattana\\nY el pecho me lo he pateao\\' ya, ma\\'\\n\\n[Puente]\\nDiguem que n\\'és de la teva ubicació\\nOn estàs no et veig fa temps\\nDiuen que ara tens una casa prop de Japó\\nQue ja no preferies recordar tots els moments\\n\\n[Estribillo]\\nNena, y si tú quieres recorrer Tokio en mi carro\\nBebemo\\' par de trago\\' de eso\\', sé que es amargo\\nToy esperando a que te quites el Quimono\\nY, honey, yo te como\\n\\n[Post-Estribillo]\\nHoney, yo sé que si me voy contigo a Japón\\nAtrás lo dejo to\\' por esta ocasión\\nBaby, sé dónde te escondes\\nTú solo dime entonces tu ubicación', 'lang': 'ca', 'id': '03a03aa6-fb6d-44e4-ab4d-5a3555424e26', 'genius_views': 117, 'youtube_views': 293258}\n",
      "11\n"
     ]
    }
   ],
   "source": [
    "with open(\"tmp/genius_hq_silent_80_ids.txt\", \"r\") as fp:\n",
    "    ids = set(fp.read().splitlines())\n",
    "print(len(ids))\n",
    "n_silent_in_train = 0\n",
    "for train_info in train_infos:\n",
    "    if train_info[\"id\"] in ids:\n",
    "        n_silent_in_train += 1\n",
    "        print(train_info)\n",
    "print(n_silent_in_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "755afe1f",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "suno_env_dev",
   "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.10.15"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
