#!/usr/bin/env bash
# XVVIIX - Local Engine Setup (macOS / Linux)
set -u
cd "$(dirname "$0")"

G='\033[0;32m'; R='\033[0;31m'; Y='\033[1;33m'; N='\033[0m'

echo
echo "  ============================================================"
echo "                XVVIIX - Local Engine Setup"
echo "  ============================================================"
echo
echo "   This will set up the Demucs AI engine on this computer."
echo
echo "     [1] Check Python"
echo "     [2] Create an isolated environment in this folder"
echo "     [3] Download the AI engine"
echo "     [4] Start the engine"
echo
echo "   Download size:"
echo "     - CPU only        : about 250 MB"
echo "     - NVIDIA GPU      : about 2.5 GB (CUDA libraries)"
echo
echo "   Everything stays in this folder. Delete it to uninstall."
echo
read -rp "   Press Enter to continue... " _
echo

echo "  [1/4] Checking Python..."
PY=""
for c in python3.12 python3.11 python3.10 python3; do
  if command -v "$c" >/dev/null 2>&1; then PY="$c"; break; fi
done
if [ -z "$PY" ]; then
  echo -e "       ${R}Python not found.${N}"
  echo "       Install it from https://www.python.org/downloads/"
  command -v brew >/dev/null 2>&1 && echo "       or run:  brew install python"
  exit 1
fi
echo -e "       ${G}OK - $($PY --version)${N}"
echo

echo "  [2/4] Creating environment..."
REUSE=0
if "$PY" -c "import torch,sys; v=tuple(int(x) for x in torch.__version__.split('.')[:2]); sys.exit(0 if v>=(2,0) else 1)" >/dev/null 2>&1; then
  REUSE=1
  TVER=$("$PY" -c "import torch;print(torch.__version__)" 2>/dev/null)
  TCUDA=$("$PY" -c "import torch;print('yes' if torch.cuda.is_available() else 'no')" 2>/dev/null)
  echo -e "       ${G}Found PyTorch $TVER on your system (CUDA: $TCUDA)${N}"
  echo "       Reusing it - only a few MB will be downloaded."
fi
if [ -x ".venv/bin/python" ]; then
  echo -e "       ${G}OK - environment already exists${N}"
else
  if [ "$REUSE" = "1" ]; then
    "$PY" -m venv --system-site-packages .venv || { echo -e "       ${R}FAILED${N}"; exit 1; }
  else
    "$PY" -m venv .venv || { echo -e "       ${R}FAILED${N}"; exit 1; }
  fi
  echo -e "       ${G}OK - created${N}"
fi
VPY=".venv/bin/python"
echo

echo "  [3/4] Installing the AI engine..."
if [ -f ".venv/.installed" ]; then
  echo -e "       ${G}OK - already installed${N}"
else
  "$VPY" -m pip install --quiet --upgrade pip
  if [ "$REUSE" = "1" ]; then
    echo "       Using the PyTorch already on your system - skipping the big download."
  elif command -v nvidia-smi >/dev/null 2>&1; then
    echo "       NVIDIA GPU detected - installing CUDA build (about 2.5 GB)"
    "$VPY" -m pip install torch torchaudio --index-url https://download.pytorch.org/whl/cu121 \
      || "$VPY" -m pip install torch torchaudio --index-url https://download.pytorch.org/whl/cpu
  elif [ "$(uname -s)" = "Darwin" ]; then
    echo "       macOS detected - installing the standard build (about 250 MB)"
    "$VPY" -m pip install torch torchaudio
  else
    echo "       No NVIDIA GPU - installing the small CPU build (about 250 MB)"
    "$VPY" -m pip install torch torchaudio --index-url https://download.pytorch.org/whl/cpu
  fi
  "$VPY" -m pip install demucs soundfile || { echo -e "       ${R}FAILED${N}"; exit 1; }
  touch .venv/.installed
  echo -e "       ${G}OK - installed${N}"
fi
echo

# unpack the embedded engine (single heredoc, decoded portably)
if base64 --help 2>&1 | grep -q -- '-d,'; then DEC="base64 -d"; else DEC="base64 --decode"; fi
cat <<'XVVIIX_B64' > .xvviix_payload.b64
IiIiClhWVklJWCAtIGxvY2FsIEdQVS9DUFUgZW5naW5lLgoKUnVucyBEZW11Y3Mgb24gdGhlIHVzZXIncyBvd24gbWFjaGluZSBhbmQgZXhwb3NlcyBhIHRpbnkgSFRUUCBBUEkgdGhhdCB0aGUKd2Vic2l0ZSAoaG9zdGVkIG9uIEdpdEh1YiBQYWdlcykgY2FuIGNhbGwuIEF1ZGlvIG5ldmVyIGxlYXZlcyB0aGUgbWFjaGluZS4KClN0YXJ0ZWQgYXV0b21hdGljYWxseSBieSBpbnN0YWxsLXh2dmlpeC5iYXQgLyBpbnN0YWxsLXh2dmlpeC5zaC4KIiIiCgppbXBvcnQganNvbgppbXBvcnQgb3MKaW1wb3J0IHJlCmltcG9ydCBzaHV0aWwKaW1wb3J0IHN1YnByb2Nlc3MKaW1wb3J0IHN5cwppbXBvcnQgdGhyZWFkaW5nCmltcG9ydCB1dWlkCmZyb20gZW1haWwucGFyc2VyIGltcG9ydCBCeXRlc1BhcnNlcgpmcm9tIGVtYWlsLnBvbGljeSBpbXBvcnQgZGVmYXVsdApmcm9tIGh0dHAuc2VydmVyIGltcG9ydCBUaHJlYWRpbmdIVFRQU2VydmVyLCBCYXNlSFRUUFJlcXVlc3RIYW5kbGVyCmZyb20gcGF0aGxpYiBpbXBvcnQgUGF0aApmcm9tIHVybGxpYi5wYXJzZSBpbXBvcnQgdW5xdW90ZQoKUk9PVCA9IFBhdGgoX19maWxlX18pLnJlc29sdmUoKS5wYXJlbnQKVVBMT0FEUyA9IFJPT1QgLyAidXBsb2FkcyIKT1VUUFVUUyA9IFJPT1QgLyAib3V0cHV0cyIKVVBMT0FEUy5ta2RpcihleGlzdF9vaz1UcnVlKQpPVVRQVVRTLm1rZGlyKGV4aXN0X29rPVRydWUpCgpIT1NUID0gb3MuZW52aXJvbi5nZXQoIlhWVklJWF9IT1NUIiwgIjEyNy4wLjAuMSIpClBPUlQgPSBpbnQob3MuZW52aXJvbi5nZXQoIlhWVklJWF9QT1JUIiwgIjg3NjUiKSkKTUFYX1VQTE9BRCA9IDUwMCAqIDEwMjQgKiAxMDI0CkFMTE9XRURfRVhUID0geyIud2F2IiwgIi5tcDMiLCAiLmZsYWMiLCAiLm00YSIsICIuYWFjIiwgIi5vZ2ciLCAiLmFpZmYiLCAiLmFpZiJ9ClNURU1fTkFNRVMgPSB7InZvY2FscyIsICJkcnVtcyIsICJiYXNzIiwgIm90aGVyIn0KU0FGRSA9IHJlLmNvbXBpbGUociJeW1x3LlwtXSskIikKUFJPR1JFU1NfUkUgPSByZS5jb21waWxlKHIiKFxkezEsM30pJSIpCgpqb2JzID0ge30KCgpkZWYgZ3B1X2luZm8oKToKICAgIHRyeToKICAgICAgICBpbXBvcnQgdG9yY2gKCiAgICAgICAgaWYgdG9yY2guY3VkYS5pc19hdmFpbGFibGUoKToKICAgICAgICAgICAgcmV0dXJuIHsiZGV2aWNlIjogImN1ZGEiLCAibmFtZSI6IHRvcmNoLmN1ZGEuZ2V0X2RldmljZV9uYW1lKDApfQogICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICBwYXNzCiAgICByZXR1cm4geyJkZXZpY2UiOiAiY3B1IiwgIm5hbWUiOiAiQ1BVIn0KCgpERVZJQ0UgPSBncHVfaW5mbygpCgoKY2xhc3MgSGFuZGxlcihCYXNlSFRUUFJlcXVlc3RIYW5kbGVyKToKICAgIHNlcnZlcl92ZXJzaW9uID0gIlhWVklJWC8yLjAiCgogICAgZGVmIGxvZ19tZXNzYWdlKHNlbGYsIGZtdCwgKmFyZ3MpOgogICAgICAgICMga2VlcCB0aGUgY29uc29sZSByZWFkYWJsZSBmb3Igbm9uLXRlY2huaWNhbCB1c2VycwogICAgICAgIGlmICIvYXBpL2hlYWx0aCIgbm90IGluIChhcmdzWzBdIGlmIGFyZ3MgZWxzZSAiIik6CiAgICAgICAgICAgIHN5cy5zdGRvdXQud3JpdGUoIiAgLSAlc1xuIiAlIChmbXQgJSBhcmdzKSkKCiAgICBkZWYgX2NvcnMoc2VsZik6CiAgICAgICAgb3JpZ2luID0gc2VsZi5oZWFkZXJzLmdldCgiT3JpZ2luIikKICAgICAgICBpZiBvcmlnaW46CiAgICAgICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbiIsIG9yaWdpbikKICAgICAgICAgICAgc2VsZi5zZW5kX2hlYWRlcigiVmFyeSIsICJPcmlnaW4iKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbiIsICIqIikKICAgICAgICBzZWxmLnNlbmRfaGVhZGVyKCJBY2Nlc3MtQ29udHJvbC1BbGxvdy1IZWFkZXJzIiwgIkNvbnRlbnQtVHlwZSwgUmFuZ2UiKQogICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkFjY2Vzcy1Db250cm9sLUFsbG93LU1ldGhvZHMiLCAiR0VULCBQT1NULCBIRUFELCBPUFRJT05TIikKICAgICAgICBzZWxmLnNlbmRfaGVhZGVyKCJBY2Nlc3MtQ29udHJvbC1FeHBvc2UtSGVhZGVycyIsICJDb250ZW50LUxlbmd0aCwgQ29udGVudC1SYW5nZSwgQWNjZXB0LVJhbmdlcyIpCiAgICAgICAgc2VsZi5zZW5kX2hlYWRlcigiQWNjZXNzLUNvbnRyb2wtTWF4LUFnZSIsICI4NjQwMCIpCgogICAgZGVmIGVuZF9oZWFkZXJzKHNlbGYpOgogICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkNhY2hlLUNvbnRyb2wiLCAibm8tc3RvcmUiKQogICAgICAgIHNlbGYuX2NvcnMoKQogICAgICAgIHN1cGVyKCkuZW5kX2hlYWRlcnMoKQoKICAgIGRlZiBkb19PUFRJT05TKHNlbGYpOgogICAgICAgIHNlbGYuc2VuZF9yZXNwb25zZSgyMDQpCiAgICAgICAgc2VsZi5zZW5kX2hlYWRlcigiQ29udGVudC1MZW5ndGgiLCAiMCIpCiAgICAgICAgc2VsZi5lbmRfaGVhZGVycygpCgogICAgZGVmIHNlbmRfanNvbihzZWxmLCBkYXRhLCBjb2RlPTIwMCk6CiAgICAgICAgcmF3ID0ganNvbi5kdW1wcyhkYXRhKS5lbmNvZGUoKQogICAgICAgIHNlbGYuc2VuZF9yZXNwb25zZShjb2RlKQogICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkNvbnRlbnQtVHlwZSIsICJhcHBsaWNhdGlvbi9qc29uIikKICAgICAgICBzZWxmLnNlbmRfaGVhZGVyKCJDb250ZW50LUxlbmd0aCIsIHN0cihsZW4ocmF3KSkpCiAgICAgICAgc2VsZi5lbmRfaGVhZGVycygpCiAgICAgICAgc2VsZi53ZmlsZS53cml0ZShyYXcpCgogICAgIyAtLS0tLS0tLS0tLS0tLS0tIFBPU1QgLS0tLS0tLS0tLS0tLS0tLQogICAgZGVmIGRvX1BPU1Qoc2VsZik6CiAgICAgICAgaWYgc2VsZi5wYXRoICE9ICIvYXBpL3NwbGl0IjoKICAgICAgICAgICAgc2VsZi5zZW5kX2pzb24oeyJlcnJvciI6ICJOb3QgZm91bmQifSwgNDA0KQogICAgICAgICAgICByZXR1cm4KICAgICAgICB0cnk6CiAgICAgICAgICAgIGxlbmd0aCA9IGludChzZWxmLmhlYWRlcnMuZ2V0KCJDb250ZW50LUxlbmd0aCIsICIwIikpCiAgICAgICAgICAgIGlmIGxlbmd0aCA8PSAwOgogICAgICAgICAgICAgICAgcmFpc2UgVmFsdWVFcnJvcigiRW1wdHkgcmVxdWVzdCIpCiAgICAgICAgICAgIGlmIGxlbmd0aCA+IE1BWF9VUExPQUQ6CiAgICAgICAgICAgICAgICBzZWxmLnNlbmRfanNvbih7ImVycm9yIjogIkZpbGUgbGFyZ2VyIHRoYW4gNTAwIE1CIn0sIDQxMykKICAgICAgICAgICAgICAgIHJldHVybgogICAgICAgICAgICBjdHlwZSA9IHNlbGYuaGVhZGVycy5nZXQoIkNvbnRlbnQtVHlwZSIsICIiKQogICAgICAgICAgICBpZiAibXVsdGlwYXJ0L2Zvcm0tZGF0YSIgbm90IGluIGN0eXBlOgogICAgICAgICAgICAgICAgcmFpc2UgVmFsdWVFcnJvcigiRXhwZWN0ZWQgbXVsdGlwYXJ0L2Zvcm0tZGF0YSIpCgogICAgICAgICAgICBib2R5ID0gc2VsZi5yZmlsZS5yZWFkKGxlbmd0aCkKICAgICAgICAgICAgbXNnID0gQnl0ZXNQYXJzZXIocG9saWN5PWRlZmF1bHQpLnBhcnNlYnl0ZXMoCiAgICAgICAgICAgICAgICBmIkNvbnRlbnQtVHlwZToge2N0eXBlfVxyXG5NSU1FLVZlcnNpb246IDEuMFxyXG5cclxuIi5lbmNvZGUoKSArIGJvZHkKICAgICAgICAgICAgKQoKICAgICAgICAgICAgZmlsZW5hbWUgPSBmaWxlZGF0YSA9IE5vbmUKICAgICAgICAgICAgZmllbGRzID0ge30KICAgICAgICAgICAgZm9yIHBhcnQgaW4gbXNnLml0ZXJfcGFydHMoKToKICAgICAgICAgICAgICAgIG5hbWUgPSBwYXJ0LmdldF9wYXJhbSgibmFtZSIsIGhlYWRlcj0iY29udGVudC1kaXNwb3NpdGlvbiIpCiAgICAgICAgICAgICAgICBpZiBuYW1lID09ICJmaWxlIjoKICAgICAgICAgICAgICAgICAgICBmaWxlbmFtZSA9IHBhcnQuZ2V0X2ZpbGVuYW1lKCkKICAgICAgICAgICAgICAgICAgICBmaWxlZGF0YSA9IHBhcnQuZ2V0X3BheWxvYWQoZGVjb2RlPVRydWUpCiAgICAgICAgICAgICAgICBlbGlmIG5hbWU6CiAgICAgICAgICAgICAgICAgICAgZmllbGRzW25hbWVdID0gcGFydC5nZXRfY29udGVudCgpCgogICAgICAgICAgICBpZiBub3QgZmlsZW5hbWUgb3Igbm90IGZpbGVkYXRhOgogICAgICAgICAgICAgICAgcmFpc2UgVmFsdWVFcnJvcigiTm8gYXVkaW8gZmlsZSByZWNlaXZlZCIpCiAgICAgICAgICAgIGV4dCA9IFBhdGgoZmlsZW5hbWUpLnN1ZmZpeC5sb3dlcigpIG9yICIud2F2IgogICAgICAgICAgICBpZiBleHQgbm90IGluIEFMTE9XRURfRVhUOgogICAgICAgICAgICAgICAgcmFpc2UgVmFsdWVFcnJvcihmJ1Vuc3VwcG9ydGVkIGZpbGUgdHlwZSAie2V4dH0iJykKCiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIHN0ZW1zID0ganNvbi5sb2FkcyhmaWVsZHMuZ2V0KCJzdGVtcyIsICJbXSIpKQogICAgICAgICAgICBleGNlcHQganNvbi5KU09ORGVjb2RlRXJyb3I6CiAgICAgICAgICAgICAgICBzdGVtcyA9IFtdCiAgICAgICAgICAgIHN0ZW1zID0gW3MgZm9yIHMgaW4gc3RlbXMgaWYgcyBpbiBTVEVNX05BTUVTXSBvciBsaXN0KFNURU1fTkFNRVMpCgogICAgICAgICAgICBqb2IgPSBzdHIodXVpZC51dWlkNCgpKQogICAgICAgICAgICBzcmMgPSBVUExPQURTIC8gKGpvYiArIGV4dCkKICAgICAgICAgICAgc3JjLndyaXRlX2J5dGVzKGZpbGVkYXRhKQogICAgICAgICAgICBqb2JzW2pvYl0gPSB7InN0YXR1cyI6ICJxdWV1ZWQiLCAicHJvZ3Jlc3MiOiAwLCAibmFtZSI6IGZpbGVuYW1lfQogICAgICAgICAgICB0aHJlYWRpbmcuVGhyZWFkKHRhcmdldD1ydW5fc3BsaXQsIGFyZ3M9KGpvYiwgc3JjLCBzdGVtcyksIGRhZW1vbj1UcnVlKS5zdGFydCgpCiAgICAgICAgICAgIHNlbGYuc2VuZF9qc29uKHsiam9iX2lkIjogam9ifSkKICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGV4YzoKICAgICAgICAgICAgc2VsZi5zZW5kX2pzb24oeyJlcnJvciI6IHN0cihleGMpfSwgNDAwKQoKICAgICMgLS0tLS0tLS0tLS0tLS0tLSBHRVQgLS0tLS0tLS0tLS0tLS0tLQogICAgZGVmIGRvX0hFQUQoc2VsZik6CiAgICAgICAgc2VsZi5kb19HRVQoKQoKICAgIGRlZiBkb19HRVQoc2VsZik6CiAgICAgICAgaWYgc2VsZi5wYXRoID09ICIvYXBpL2hlYWx0aCI6CiAgICAgICAgICAgIHNlbGYuc2VuZF9qc29uKHsKICAgICAgICAgICAgICAgICJhcHAiOiAiWFZWSUlYIiwKICAgICAgICAgICAgICAgICJ2ZXJzaW9uIjogIjIuMCIsCiAgICAgICAgICAgICAgICAiZW5naW5lIjogImRlbXVjcyIsCiAgICAgICAgICAgICAgICAiZGV2aWNlIjogREVWSUNFWyJkZXZpY2UiXSwKICAgICAgICAgICAgICAgICJkZXZpY2VfbmFtZSI6IERFVklDRVsibmFtZSJdLAogICAgICAgICAgICAgICAgIm9rIjogVHJ1ZSwKICAgICAgICAgICAgfSkKICAgICAgICAgICAgcmV0dXJuCgogICAgICAgIGlmIHNlbGYucGF0aC5zdGFydHN3aXRoKCIvYXBpL3N0YXR1cy8iKToKICAgICAgICAgICAgam9iID0gc2VsZi5wYXRoLnJzcGxpdCgiLyIsIDEpWy0xXQogICAgICAgICAgICBzZWxmLnNlbmRfanNvbihqb2JzLmdldChqb2IsIHsiZXJyb3IiOiAiVW5rbm93biBqb2IifSkpCiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBpZiBzZWxmLnBhdGguc3RhcnRzd2l0aCgiL2FwaS9kb3dubG9hZC8iKToKICAgICAgICAgICAgc2VsZi5fZG93bmxvYWQoKQogICAgICAgICAgICByZXR1cm4KCiAgICAgICAgc2VsZi5zZW5kX2pzb24oeyJlcnJvciI6ICJOb3QgZm91bmQifSwgNDA0KQoKICAgIGRlZiBfZG93bmxvYWQoc2VsZik6CiAgICAgICAgcGF0aCwgXywgcXVlcnkgPSBzZWxmLnBhdGgucGFydGl0aW9uKCI/IikKICAgICAgICBpbmxpbmUgPSAiaW5saW5lPTEiIGluIHF1ZXJ5CiAgICAgICAgcGFydHMgPSBwYXRoLnNwbGl0KCIvIikKICAgICAgICBpZiBsZW4ocGFydHMpICE9IDc6CiAgICAgICAgICAgIHNlbGYuc2VuZF9qc29uKHsiZXJyb3IiOiAiSW52YWxpZCBwYXRoIn0sIDQwMCkKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgXywgXywgXywgam9iLCBtb2RlbCwgc29uZywgZmlsZW5hbWUgPSBbdW5xdW90ZShwKSBmb3IgcCBpbiBwYXJ0c10KICAgICAgICBmb3IgYyBpbiAoam9iLCBtb2RlbCwgc29uZywgZmlsZW5hbWUpOgogICAgICAgICAgICBpZiBub3QgU0FGRS5tYXRjaChjKSBvciAiLi4iIGluIGM6CiAgICAgICAgICAgICAgICBzZWxmLnNlbmRfanNvbih7ImVycm9yIjogIkludmFsaWQgcGF0aCJ9LCA0MDApCiAgICAgICAgICAgICAgICByZXR1cm4KCiAgICAgICAgcm9vdCA9IE9VVFBVVFMucmVzb2x2ZSgpCiAgICAgICAgdGFyZ2V0ID0gKE9VVFBVVFMgLyBqb2IgLyBtb2RlbCAvIHNvbmcgLyBmaWxlbmFtZSkucmVzb2x2ZSgpCiAgICAgICAgdHJ5OgogICAgICAgICAgICB0YXJnZXQucmVsYXRpdmVfdG8ocm9vdCkKICAgICAgICBleGNlcHQgVmFsdWVFcnJvcjoKICAgICAgICAgICAgc2VsZi5zZW5kX2pzb24oeyJlcnJvciI6ICJJbnZhbGlkIHBhdGgifSwgNDAwKQogICAgICAgICAgICByZXR1cm4KICAgICAgICBpZiBub3QgdGFyZ2V0LmlzX2ZpbGUoKToKICAgICAgICAgICAgc2VsZi5zZW5kX2pzb24oeyJlcnJvciI6ICJOb3QgZm91bmQifSwgNDA0KQogICAgICAgICAgICByZXR1cm4KCiAgICAgICAgc2l6ZSA9IHRhcmdldC5zdGF0KCkuc3Rfc2l6ZQogICAgICAgIHN0YXJ0LCBlbmQsIHN0YXR1cyA9IDAsIHNpemUgLSAxLCAyMDAKICAgICAgICBybmcgPSBzZWxmLmhlYWRlcnMuZ2V0KCJSYW5nZSIsICIiKQogICAgICAgIG0gPSByZS5tYXRjaChyImJ5dGVzPShcZCopLShcZCopJCIsIHJuZy5zdHJpcCgpKSBpZiBybmcgZWxzZSBOb25lCiAgICAgICAgaWYgbSBhbmQgc2l6ZToKICAgICAgICAgICAgcywgZSA9IG0uZ3JvdXAoMSksIG0uZ3JvdXAoMikKICAgICAgICAgICAgaWYgczoKICAgICAgICAgICAgICAgIHN0YXJ0ID0gaW50KHMpCiAgICAgICAgICAgICAgICBpZiBlOgogICAgICAgICAgICAgICAgICAgIGVuZCA9IG1pbihpbnQoZSksIHNpemUgLSAxKQogICAgICAgICAgICBlbGlmIGU6CiAgICAgICAgICAgICAgICBzdGFydCA9IG1heCgwLCBzaXplIC0gaW50KGUpKQogICAgICAgICAgICBpZiBzdGFydCA+IGVuZCBvciBzdGFydCA+PSBzaXplOgogICAgICAgICAgICAgICAgc2VsZi5zZW5kX3Jlc3BvbnNlKDQxNikKICAgICAgICAgICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkNvbnRlbnQtUmFuZ2UiLCBmImJ5dGVzICove3NpemV9IikKICAgICAgICAgICAgICAgIHNlbGYuZW5kX2hlYWRlcnMoKQogICAgICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgICAgIHN0YXR1cyA9IDIwNgoKICAgICAgICBsZW5ndGggPSBlbmQgLSBzdGFydCArIDEKICAgICAgICBzZWxmLnNlbmRfcmVzcG9uc2Uoc3RhdHVzKQogICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkNvbnRlbnQtVHlwZSIsICJhdWRpby93YXYiKQogICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkFjY2VwdC1SYW5nZXMiLCAiYnl0ZXMiKQogICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkNvbnRlbnQtRGlzcG9zaXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICAgZid7ImlubGluZSIgaWYgaW5saW5lIGVsc2UgImF0dGFjaG1lbnQifTsgZmlsZW5hbWU9IntmaWxlbmFtZX0iJykKICAgICAgICBzZWxmLnNlbmRfaGVhZGVyKCJDb250ZW50LUxlbmd0aCIsIHN0cihsZW5ndGgpKQogICAgICAgIGlmIHN0YXR1cyA9PSAyMDY6CiAgICAgICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkNvbnRlbnQtUmFuZ2UiLCBmImJ5dGVzIHtzdGFydH0te2VuZH0ve3NpemV9IikKICAgICAgICBzZWxmLmVuZF9oZWFkZXJzKCkKICAgICAgICBpZiBzZWxmLmNvbW1hbmQgPT0gIkhFQUQiOgogICAgICAgICAgICByZXR1cm4KICAgICAgICB3aXRoIHRhcmdldC5vcGVuKCJyYiIpIGFzIGY6CiAgICAgICAgICAgIGYuc2VlayhzdGFydCkKICAgICAgICAgICAgbGVmdCA9IGxlbmd0aAogICAgICAgICAgICB3aGlsZSBsZWZ0ID4gMDoKICAgICAgICAgICAgICAgIGNodW5rID0gZi5yZWFkKG1pbig2NTUzNiwgbGVmdCkpCiAgICAgICAgICAgICAgICBpZiBub3QgY2h1bms6CiAgICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgICAgIHNlbGYud2ZpbGUud3JpdGUoY2h1bmspCiAgICAgICAgICAgICAgICBsZWZ0IC09IGxlbihjaHVuaykKCgpkZWYgcnVuX3NwbGl0KGpvYiwgc3JjLCBzdGVtcyk6CiAgICBvdXQgPSBPVVRQVVRTIC8gam9iCiAgICBvdXQubWtkaXIoZXhpc3Rfb2s9VHJ1ZSkKICAgIGpvYnNbam9iXS51cGRhdGUoc3RhdHVzPSJwcm9jZXNzaW5nIiwgcHJvZ3Jlc3M9NSkKICAgIG1vZGVsID0gImh0ZGVtdWNzIgogICAgdHJ5OgogICAgICAgIGNtZCA9IFtzeXMuZXhlY3V0YWJsZSwgIi1tIiwgImRlbXVjcyIsICItbiIsIG1vZGVsLCAiLS1vdXQiLCBzdHIob3V0KSwgc3RyKHNyYyldCiAgICAgICAgaWYgREVWSUNFWyJkZXZpY2UiXSA9PSAiY3VkYSI6CiAgICAgICAgICAgIGNtZCArPSBbIi1kIiwgImN1ZGEiXQogICAgICAgIHByb2MgPSBzdWJwcm9jZXNzLlBvcGVuKGNtZCwgc3Rkb3V0PXN1YnByb2Nlc3MuUElQRSwgc3RkZXJyPXN1YnByb2Nlc3MuU1RET1VULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ9VHJ1ZSwgYnVmc2l6ZT0xKQogICAgICAgIGZvciBsaW5lIGluIHByb2Muc3Rkb3V0OgogICAgICAgICAgICBoaXQgPSBQUk9HUkVTU19SRS5zZWFyY2gobGluZSkKICAgICAgICAgICAgaWYgaGl0OgogICAgICAgICAgICAgICAgam9ic1tqb2JdWyJwcm9ncmVzcyJdID0gbWF4KDUsIG1pbig5NSwgaW50KGhpdC5ncm91cCgxKSkpKQogICAgICAgIHByb2Mud2FpdCgpCiAgICAgICAgaWYgcHJvYy5yZXR1cm5jb2RlICE9IDA6CiAgICAgICAgICAgIHJhaXNlIFJ1bnRpbWVFcnJvcigiRGVtdWNzIGNvdWxkIG5vdCBwcm9jZXNzIHRoaXMgZmlsZS4iKQoKICAgICAgICBmb2xkZXIgPSBvdXQgLyBtb2RlbCAvIHNyYy5zdGVtCiAgICAgICAgZm91bmQgPSB7cC5zdGVtOiBwIGZvciBwIGluIGZvbGRlci5nbG9iKCIqLndhdiIpIGlmIHAuaXNfZmlsZSgpfQogICAgICAgIGNob3NlbiA9IHtrOiB2IGZvciBrLCB2IGluIGZvdW5kLml0ZW1zKCkgaWYgayBpbiBzdGVtc30gb3IgZm91bmQKICAgICAgICBmaWxlcyA9IHtrOiBmIi9hcGkvZG93bmxvYWQve2pvYn0ve21vZGVsfS97c3JjLnN0ZW19L3t2Lm5hbWV9IiBmb3IgaywgdiBpbiBjaG9zZW4uaXRlbXMoKX0KICAgICAgICBqb2JzW2pvYl0udXBkYXRlKHN0YXR1cz0iY29tcGxldGUiLCBwcm9ncmVzcz0xMDAsIGZpbGVzPWZpbGVzKQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBleGM6CiAgICAgICAgam9ic1tqb2JdLnVwZGF0ZShzdGF0dXM9ImVycm9yIiwgZXJyb3I9c3RyKGV4YykpCiAgICBmaW5hbGx5OgogICAgICAgIHRyeToKICAgICAgICAgICAgc3JjLnVubGluayhtaXNzaW5nX29rPVRydWUpCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICAgICAgcGFzcwoKCmRlZiBtYWluKCk6CiAgICBsaW5lID0gIj0iICogNTgKICAgIHByaW50KGxpbmUpCiAgICBwcmludCgiICAgWFZWSUlYIC0gTG9jYWwgRW5naW5lIikKICAgIHByaW50KGxpbmUpCiAgICBwcmludChmIiAgIERldmljZSAgOiB7REVWSUNFWyduYW1lJ119IikKICAgIHByaW50KGYiICAgQWRkcmVzcyA6IGh0dHA6Ly97SE9TVH06e1BPUlR9IikKICAgIHByaW50KGxpbmUpCiAgICBwcmludCgpCiAgICBwcmludCgiICAgUkVBRFkgLSBnbyBiYWNrIHRvIHRoZSB3ZWJzaXRlLCBpdCBjb25uZWN0cyBhdXRvbWF0aWNhbGx5LiIpCiAgICBwcmludCgiICAgS2VlcCB0aGlzIHdpbmRvdyBvcGVuLiBQcmVzcyBDdHJsK0MgdG8gc3RvcC4iKQogICAgcHJpbnQoKQogICAgdHJ5OgogICAgICAgIFRocmVhZGluZ0hUVFBTZXJ2ZXIoKEhPU1QsIFBPUlQpLCBIYW5kbGVyKS5zZXJ2ZV9mb3JldmVyKCkKICAgIGV4Y2VwdCBLZXlib2FyZEludGVycnVwdDoKICAgICAgICBwcmludCgiXG4gICBFbmdpbmUgc3RvcHBlZC4iKQoKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICBtYWluKCkK
XVVIIX_B64
$DEC < .xvviix_payload.b64 > xvviix_engine.py || {
  echo -e "       ${R}FAILED to unpack the engine${N}"; rm -f .xvviix_payload.b64; exit 1;
}
rm -f .xvviix_payload.b64

echo "  [4/4] Starting the engine..."
echo
echo "  ============================================================"
echo -e "     ${G}READY${N}"
echo "     Go back to the website - it connects automatically."
echo "     Keep this window open. Press Ctrl+C to stop."
echo "  ============================================================"
echo
"$VPY" xvviix_engine.py
